diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 79b755e97..46c44995b 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -671,7 +671,7 @@ void IndexAccess::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted.")); m_index->expectType(IntegerType(256)); if (type.isByteArray()) - m_type = make_shared(8, IntegerType::Modifier::Hash); + m_type = make_shared(1); else m_type = type.getBaseType(); m_isLValue = type.getLocation() != ArrayType::Location::CallData; diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index a878bb61a..55ec0cb59 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -41,14 +41,14 @@ namespace solidity { const map StandardSources = map{ - {"coin", R"(import "CoinReg";import "Config";import "configUser";contract coin is configUser{function coin(string3 name, uint denom) {CoinReg(Config(configAddr()).lookup(3)).register(name, denom);}})"}, + {"coin", R"(import "CoinReg";import "Config";import "configUser";contract coin is configUser{function coin(bytes3 name, uint denom) {CoinReg(Config(configAddr()).lookup(3)).register(name, denom);}})"}, {"Coin", R"(contract Coin{function isApprovedFor(address _target,address _proxy)constant returns(bool _r){}function isApproved(address _proxy)constant returns(bool _r){}function sendCoinFrom(address _from,uint256 _val,address _to){}function coinBalanceOf(address _a)constant returns(uint256 _r){}function sendCoin(uint256 _val,address _to){}function coinBalance()constant returns(uint256 _r){}function approve(address _a){}})"}, - {"CoinReg", R"(contract CoinReg{function count()constant returns(uint256 r){}function info(uint256 i)constant returns(address addr,string3 name,uint256 denom){}function register(string3 name,uint256 denom){}function unregister(){}})"}, + {"CoinReg", R"(contract CoinReg{function count()constant returns(uint256 r){}function info(uint256 i)constant returns(address addr,bytes3 name,uint256 denom){}function register(bytes3 name,uint256 denom){}function unregister(){}})"}, {"configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xc6d9d2cd449a754c494264e1809c50e34d64562b;}})"}, {"Config", R"(contract Config{function lookup(uint256 service)constant returns(address a){}function kill(){}function unregister(uint256 id){}function register(uint256 id,address service){}})"}, {"mortal", R"(import "owned";contract mortal is owned {function kill() { if (msg.sender == owner) suicide(owner); }})"}, - {"named", R"(import "Config";import "NameReg";import "configUser";contract named is configUser {function named(string32 name) {NameReg(Config(configAddr()).lookup(1)).register(name);}})"}, - {"NameReg", R"(contract NameReg{function register(string32 name){}function addressOf(string32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(string32 name){}})"}, + {"named", R"(import "Config";import "NameReg";import "configUser";contract named is configUser {function named(bytes32 name) {NameReg(Config(configAddr()).lookup(1)).register(name);}})"}, + {"NameReg", R"(contract NameReg{function register(bytes32 name){}function addressOf(bytes32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(bytes32 name){}})"}, {"owned", R"(contract owned{function owned(){owner = msg.sender;}modifier onlyowner(){if(msg.sender==owner)_}address owner;})"}, {"service", R"(import "Config";import "configUser";contract service is configUser{function service(uint _n){Config(configAddr()).register(_n, this);}})"}, {"std", R"(import "owned";import "mortal";import "Config";import "configUser";import "NameReg";import "named";)"} diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index 8a26b5d17..7b078e03e 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -178,7 +178,7 @@ void CompilerUtils::computeHashStatic(Type const& _type, bool _padToWordBoundari unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries) { unsigned numBytes = _type.getCalldataEncodedSize(_padToWordBoundaries); - bool leftAligned = _type.getCategory() == Type::Category::String; + bool leftAligned = _type.getCategory() == Type::Category::FixedBytes; if (numBytes == 0) m_context << eth::Instruction::POP << u256(0); else @@ -202,7 +202,7 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) const { unsigned numBytes = _type.getCalldataEncodedSize(_padToWordBoundaries); - bool leftAligned = _type.getCategory() == Type::Category::String; + bool leftAligned = _type.getCategory() == Type::Category::FixedBytes; if (numBytes == 0) m_context << eth::Instruction::POP; else diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 129261120..3cee40df1 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -123,23 +123,25 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con Type::Category stackTypeCategory = _typeOnStack.getCategory(); Type::Category targetTypeCategory = _targetType.getCategory(); - if (stackTypeCategory == Type::Category::String) + switch (stackTypeCategory) { - StaticStringType const& typeOnStack = dynamic_cast(_typeOnStack); + case Type::Category::FixedBytes: + { + FixedBytesType const& typeOnStack = dynamic_cast(_typeOnStack); if (targetTypeCategory == Type::Category::Integer) { - // conversion from string to hash. no need to clean the high bit + // conversion from bytes to integer. no need to clean the high bit // only to shift right because of opposite alignment IntegerType const& targetIntegerType = dynamic_cast(_targetType); - 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; + if (targetIntegerType.getNumBits() < typeOnStack.getNumBytes() * 8) + appendTypeConversion(IntegerType(typeOnStack.getNumBytes() * 8), _targetType, _cleanupNeeded); } else { - // clear lower-order bytes for conversion to shorter strings - we always clean - solAssert(targetTypeCategory == Type::Category::String, "Invalid type conversion requested."); - StaticStringType const& targetType = dynamic_cast(_targetType); + // clear lower-order bytes for conversion to shorter bytes - we always clean + solAssert(targetTypeCategory == Type::Category::FixedBytes, "Invalid type conversion requested."); + FixedBytesType const& targetType = dynamic_cast(_targetType); if (targetType.getNumBytes() < typeOnStack.getNumBytes()) { if (targetType.getNumBytes() == 0) @@ -151,22 +153,24 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con } } } - else if (stackTypeCategory == Type::Category::Enum) - solAssert(targetTypeCategory == Type::Category::Integer || - targetTypeCategory == Type::Category::Enum, ""); - else if (stackTypeCategory == Type::Category::Integer || - stackTypeCategory == Type::Category::Contract || - stackTypeCategory == Type::Category::IntegerConstant) - { - if (targetTypeCategory == Type::Category::String && stackTypeCategory == Type::Category::Integer) + break; + case Type::Category::Enum: + solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Enum, ""); + break; + case Type::Category::Integer: + case Type::Category::Contract: + case Type::Category::IntegerConstant: + if (targetTypeCategory == Type::Category::FixedBytes) { - // conversion from hash to string. no need to clean the high bit + solAssert(stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::IntegerConstant, + "Invalid conversion to FixedBytesType requested."); + // conversion from bytes 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); - 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; + FixedBytesType const& targetBytesType = dynamic_cast(_targetType); + if (auto typeOnStack = dynamic_cast(&_typeOnStack)) + if (targetBytesType.getNumBytes() * 8 > typeOnStack->getNumBits()) + appendHighBitsCleanup(*typeOnStack); + m_context << (u256(1) << (256 - targetBytesType.getNumBytes() * 8)) << eth::Instruction::MUL; } else if (targetTypeCategory == Type::Category::Enum) // just clean @@ -176,7 +180,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con 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::IntegerConstant) { IntegerConstantType const& constType = dynamic_cast(_typeOnStack); @@ -188,7 +192,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()) @@ -197,10 +201,12 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con appendHighBitsCleanup(targetType); } } - } - else if (_typeOnStack != _targetType) + break; + default: // All other types should not be convertible to non-equal types. - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested.")); + solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); + break; + } } bool ExpressionCompiler::visit(Assignment const& _assignment) @@ -775,7 +781,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) // no lvalue, just retrieve the value m_context << eth::Instruction::ADD << eth::Instruction::CALLDATALOAD - << u256(0) << eth::Instruction::BYTE; + << ((u256(0xff) << (256 - 8))) << eth::Instruction::AND; break; case ArrayType::Location::Memory: solAssert(false, "Memory lvalues not yet implemented."); @@ -870,7 +876,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) { case Type::Category::IntegerConstant: case Type::Category::Bool: - case Type::Category::String: + case Type::Category::FixedBytes: m_context << _literal.getType()->literalValue(&_literal); break; default: diff --git a/libsolidity/GlobalContext.cpp b/libsolidity/GlobalContext.cpp index 411e99abb..80cebd760 100644 --- a/libsolidity/GlobalContext.cpp +++ b/libsolidity/GlobalContext.cpp @@ -41,23 +41,23 @@ m_magicVariables(vector>{make_shared< make_shared("suicide", make_shared(strings{"address"}, strings{}, FunctionType::Location::Suicide)), make_shared("sha3", - make_shared(strings(), strings{"hash"}, FunctionType::Location::SHA3, true)), + make_shared(strings(), strings{"bytes32"}, FunctionType::Location::SHA3, true)), make_shared("log0", - make_shared(strings{"hash"},strings{}, FunctionType::Location::Log0)), + make_shared(strings{"bytes32"}, strings{}, FunctionType::Location::Log0)), make_shared("log1", - make_shared(strings{"hash", "hash"},strings{}, FunctionType::Location::Log1)), + make_shared(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Location::Log1)), make_shared("log2", - make_shared(strings{"hash", "hash", "hash"},strings{}, FunctionType::Location::Log2)), + make_shared(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Location::Log2)), make_shared("log3", - make_shared(strings{"hash", "hash", "hash", "hash"},strings{}, FunctionType::Location::Log3)), + make_shared(strings{"bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Location::Log3)), make_shared("log4", - make_shared(strings{"hash", "hash", "hash", "hash", "hash"},strings{}, FunctionType::Location::Log4)), + make_shared(strings{"bytes32", "bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Location::Log4)), make_shared("sha256", - make_shared(strings(), strings{"hash"}, FunctionType::Location::SHA256, true)), + make_shared(strings(), strings{"bytes32"}, FunctionType::Location::SHA256, true)), make_shared("ecrecover", - make_shared(strings{"hash", "hash8", "hash", "hash"}, strings{"address"}, FunctionType::Location::ECRecover)), + make_shared(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Location::ECRecover)), make_shared("ripemd160", - make_shared(strings(), strings{"hash160"}, FunctionType::Location::RIPEMD160, true))}) + make_shared(strings(), strings{"bytes20"}, FunctionType::Location::RIPEMD160, true))}) { } diff --git a/libsolidity/LValue.cpp b/libsolidity/LValue.cpp index a036be80b..a56ed54c7 100644 --- a/libsolidity/LValue.cpp +++ b/libsolidity/LValue.cpp @@ -234,7 +234,7 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const } /// Used in StorageByteArrayElement -static IntegerType byteType(8, IntegerType::Modifier::Hash); +static FixedBytesType byteType(1); StorageByteArrayElement::StorageByteArrayElement(CompilerContext& _compilerContext): LValue(_compilerContext, byteType) @@ -250,6 +250,7 @@ void StorageByteArrayElement::retrieveValue(SourceLocation const&, bool _remove) else m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD << eth::Instruction::DUP2 << eth::Instruction::BYTE; + m_context << (u256(1) << (256 - 8)) << eth::Instruction::MUL; } void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, bool _move) const @@ -265,8 +266,9 @@ void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, boo m_context << eth::Instruction::DUP2 << u256(0xff) << eth::Instruction::MUL << eth::Instruction::NOT << eth::Instruction::AND; // stack: value ref (1<<(32-byte_number)) old_full_value_with_cleared_byte - m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP4 << eth::Instruction::MUL - << eth::Instruction::OR; + m_context << eth::Instruction::SWAP1; + m_context << (u256(1) << (256 - 8)) << eth::Instruction::DUP5 << eth::Instruction::DIV + << eth::Instruction::MUL << eth::Instruction::OR; // stack: value ref new_full_value m_context << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; if (_move) diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 85979b566..2d8a49fcd 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -252,77 +252,44 @@ namespace solidity K(UInt240, "uint240", 0) \ K(UInt248, "uint248", 0) \ K(UInt256, "uint256", 0) \ - K(Hash, "hash", 0) \ - K(Hash8, "hash8", 0) \ - K(Hash16, "hash16", 0) \ - K(Hash24, "hash24", 0) \ - K(Hash32, "hash32", 0) \ - K(Hash40, "hash40", 0) \ - K(Hash48, "hash48", 0) \ - K(Hash56, "hash56", 0) \ - K(Hash64, "hash64", 0) \ - K(Hash72, "hash72", 0) \ - K(Hash80, "hash80", 0) \ - K(Hash88, "hash88", 0) \ - K(Hash96, "hash96", 0) \ - K(Hash104, "hash104", 0) \ - K(Hash112, "hash112", 0) \ - K(Hash120, "hash120", 0) \ - K(Hash128, "hash128", 0) \ - K(Hash136, "hash136", 0) \ - K(Hash144, "hash144", 0) \ - K(Hash152, "hash152", 0) \ - K(Hash160, "hash160", 0) \ - K(Hash168, "hash168", 0) \ - K(Hash176, "hash178", 0) \ - K(Hash184, "hash184", 0) \ - K(Hash192, "hash192", 0) \ - K(Hash200, "hash200", 0) \ - K(Hash208, "hash208", 0) \ - K(Hash216, "hash216", 0) \ - K(Hash224, "hash224", 0) \ - K(Hash232, "hash232", 0) \ - K(Hash240, "hash240", 0) \ - K(Hash248, "hash248", 0) \ - K(Hash256, "hash256", 0) \ + K(Bytes0, "bytes0", 0) \ + K(Bytes1, "bytes1", 0) \ + K(Bytes2, "bytes2", 0) \ + K(Bytes3, "bytes3", 0) \ + K(Bytes4, "bytes4", 0) \ + K(Bytes5, "bytes5", 0) \ + K(Bytes6, "bytes6", 0) \ + K(Bytes7, "bytes7", 0) \ + K(Bytes8, "bytes8", 0) \ + K(Bytes9, "bytes9", 0) \ + K(Bytes10, "bytes10", 0) \ + K(Bytes11, "bytes11", 0) \ + K(Bytes12, "bytes12", 0) \ + K(Bytes13, "bytes13", 0) \ + K(Bytes14, "bytes14", 0) \ + K(Bytes15, "bytes15", 0) \ + K(Bytes16, "bytes16", 0) \ + K(Bytes17, "bytes17", 0) \ + K(Bytes18, "bytes18", 0) \ + K(Bytes19, "bytes19", 0) \ + K(Bytes20, "bytes20", 0) \ + K(Bytes21, "bytes21", 0) \ + K(Bytes22, "bytes22", 0) \ + K(Bytes23, "bytes23", 0) \ + K(Bytes24, "bytes24", 0) \ + K(Bytes25, "bytes25", 0) \ + K(Bytes26, "bytes26", 0) \ + K(Bytes27, "bytes27", 0) \ + K(Bytes28, "bytes28", 0) \ + K(Bytes29, "bytes29", 0) \ + K(Bytes30, "bytes30", 0) \ + K(Bytes31, "bytes31", 0) \ + K(Bytes32, "bytes32", 0) \ + K(Bytes, "bytes", 0) \ + K(Byte, "byte", 0) \ K(Address, "address", 0) \ K(Bool, "bool", 0) \ - K(Bytes, "bytes", 0) \ K(StringType, "string", 0) \ - K(String0, "string0", 0) \ - K(String1, "string1", 0) \ - K(String2, "string2", 0) \ - K(String3, "string3", 0) \ - K(String4, "string4", 0) \ - K(String5, "string5", 0) \ - K(String6, "string6", 0) \ - K(String7, "string7", 0) \ - K(String8, "string8", 0) \ - K(String9, "string9", 0) \ - K(String10, "string10", 0) \ - K(String11, "string11", 0) \ - K(String12, "string12", 0) \ - K(String13, "string13", 0) \ - K(String14, "string14", 0) \ - K(String15, "string15", 0) \ - K(String16, "string16", 0) \ - K(String17, "string17", 0) \ - K(String18, "string18", 0) \ - K(String19, "string19", 0) \ - K(String20, "string20", 0) \ - K(String21, "string21", 0) \ - K(String22, "string22", 0) \ - K(String23, "string23", 0) \ - K(String24, "string24", 0) \ - K(String25, "string25", 0) \ - K(String26, "string26", 0) \ - K(String27, "string27", 0) \ - K(String28, "string28", 0) \ - K(String29, "string29", 0) \ - K(String30, "string30", 0) \ - K(String31, "string31", 0) \ - K(String32, "string32", 0) \ - K(Text, "text", 0) \ K(Real, "real", 0) \ K(UReal, "ureal", 0) \ T(TypesEnd, NULL, 0) /* used as type enum end marker */ \ diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 454d79d9b..bd55e2a8b 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -37,26 +37,36 @@ namespace solidity TypePointer Type::fromElementaryTypeName(Token::Value _typeToken) { - solAssert(Token::isElementaryTypeName(_typeToken), "Elementary type name expected."); + char const* tokenCstr = Token::toString(_typeToken); + solAssert(Token::isElementaryTypeName(_typeToken), + "Expected an elementary type name but got " + ((tokenCstr) ? std::string(Token::toString(_typeToken)) : "")); - if (Token::Int <= _typeToken && _typeToken <= Token::Hash256) + if (Token::Int <= _typeToken && _typeToken <= Token::Bytes32) { int offset = _typeToken - Token::Int; int bytes = offset % 33; - if (bytes == 0) + if (bytes == 0 && _typeToken != Token::Bytes0) bytes = 32; int modifier = offset / 33; - return make_shared(bytes * 8, - modifier == 0 ? IntegerType::Modifier::Signed : - modifier == 1 ? IntegerType::Modifier::Unsigned : - IntegerType::Modifier::Hash); + switch(modifier) + { + case 0: + return make_shared(bytes * 8, IntegerType::Modifier::Signed); + case 1: + return make_shared(bytes * 8, IntegerType::Modifier::Unsigned); + case 2: + return make_shared(bytes); + default: + solAssert(false, "Unexpected modifier value. Should never happen"); + return TypePointer(); + } } + else if (_typeToken == Token::Byte) + return make_shared(1); else if (_typeToken == Token::Address) return make_shared(0, IntegerType::Modifier::Address); else if (_typeToken == Token::Bool) return make_shared(); - else if (Token::String0 <= _typeToken && _typeToken <= Token::String32) - return make_shared(int(_typeToken) - int(Token::String0)); else if (_typeToken == Token::Bytes) return make_shared(ArrayType::Location::Storage); else @@ -123,7 +133,7 @@ TypePointer Type::forLiteral(Literal const& _literal) return make_shared(_literal); case Token::StringLiteral: //@todo put larger strings into dynamic strings - return StaticStringType::smallestTypeForLiteral(_literal.getValue()); + return FixedBytesType::smallestTypeForLiteral(_literal.getValue()); default: return shared_ptr(); } @@ -159,8 +169,6 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const return false; if (isAddress()) return convertTo.isAddress(); - else if (isHash()) - return convertTo.isHash(); else if (isSigned()) return convertTo.isSigned(); else @@ -169,14 +177,10 @@ 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 || - _convertTo.getCategory() == Category::Enum; + _convertTo.getCategory() == Category::Contract || + _convertTo.getCategory() == Category::Enum || + _convertTo.getCategory() == Category::FixedBytes; } TypePointer IntegerType::unaryOperatorResult(Token::Value _operator) const @@ -187,16 +191,10 @@ TypePointer IntegerType::unaryOperatorResult(Token::Value _operator) const // no further unary operators for addresses else if (isAddress()) return TypePointer(); - // "~" is ok for all other types - else if (_operator == Token::BitNot) - return shared_from_this(); - // nothing else for hashes - else if (isHash()) - return TypePointer(); - // for non-hash integers, we allow +, -, ++ and -- + // for non-address integers, we allow +, -, ++ and -- else if (_operator == Token::Add || _operator == Token::Sub || _operator == Token::Inc || _operator == Token::Dec || - _operator == Token::After) + _operator == Token::After || _operator == Token::BitNot) return shared_from_this(); else return TypePointer(); @@ -214,7 +212,7 @@ string IntegerType::toString() const { if (isAddress()) return "address"; - string prefix = isHash() ? "hash" : (isSigned() ? "int" : "uint"); + string prefix = isSigned() ? "int" : "uint"; return prefix + dev::toString(m_bits); } @@ -230,14 +228,11 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe // All integer types can be compared if (Token::isCompareOp(_operator)) return commonType; - - // Nothing else can be done with addresses, but hashes can receive bit operators + // Nothing else can be done with addresses if (commonType->isAddress()) return TypePointer(); - else if (commonType->isHash() && !Token::isBitOp(_operator)) - return TypePointer(); - else - return commonType; + + return commonType; } const MemberList IntegerType::AddressMemberList = @@ -284,8 +279,17 @@ IntegerConstantType::IntegerConstantType(Literal const& _literal) bool IntegerConstantType::isImplicitlyConvertibleTo(Type const& _convertTo) const { - TypePointer integerType = getIntegerType(); - return integerType && integerType->isImplicitlyConvertibleTo(_convertTo); + shared_ptr integerType = getIntegerType(); + if (!integerType) + return false; + + if (_convertTo.getCategory() == Category::FixedBytes) + { + FixedBytesType const& convertTo = dynamic_cast(_convertTo); + return convertTo.getNumBytes() * 8 >= integerType->getNumBits(); + } + + return integerType->isImplicitlyConvertibleTo(_convertTo); } bool IntegerConstantType::isExplicitlyConvertibleTo(Type const& _convertTo) const @@ -433,50 +437,73 @@ shared_ptr IntegerConstantType::getIntegerType() const : IntegerType::Modifier::Unsigned); } -shared_ptr StaticStringType::smallestTypeForLiteral(string const& _literal) +shared_ptr FixedBytesType::smallestTypeForLiteral(string const& _literal) { if (_literal.length() <= 32) - return make_shared(_literal.length()); - return shared_ptr(); + return make_shared(_literal.length()); + return shared_ptr(); } -StaticStringType::StaticStringType(int _bytes): m_bytes(_bytes) +FixedBytesType::FixedBytesType(int _bytes): m_bytes(_bytes) { solAssert(m_bytes >= 0 && m_bytes <= 32, - "Invalid byte number for static string type: " + dev::toString(m_bytes)); + "Invalid byte number for fixed bytes type: " + dev::toString(m_bytes)); } -bool StaticStringType::isImplicitlyConvertibleTo(Type const& _convertTo) const +bool FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const { if (_convertTo.getCategory() != getCategory()) return false; - StaticStringType const& convertTo = dynamic_cast(_convertTo); + FixedBytesType const& convertTo = dynamic_cast(_convertTo); return convertTo.m_bytes >= m_bytes; } -bool StaticStringType::isExplicitlyConvertibleTo(Type const& _convertTo) const +bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - if (_convertTo.getCategory() == getCategory()) - return true; if (_convertTo.getCategory() == Category::Integer) { IntegerType const& convertTo = dynamic_cast(_convertTo); - if (convertTo.isHash() && (m_bytes * 8 == convertTo.getNumBits())) + if (m_bytes * 8 <= convertTo.getNumBits()) return true; } - return false; + return _convertTo.getCategory() == Category::Contract || + _convertTo.getCategory() == getCategory(); +} + +TypePointer FixedBytesType::unaryOperatorResult(Token::Value _operator) const +{ + // "delete" and "~" is okay for FixedBytesType + if (_operator == Token::Delete) + return make_shared(); + else if (_operator == Token::BitNot) + return shared_from_this(); + + return TypePointer(); +} + +TypePointer FixedBytesType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const +{ + auto commonType = dynamic_pointer_cast(Type::commonType(shared_from_this(), _other)); + if (!commonType) + return TypePointer(); + + // FixedBytes can be compared and have bitwise operators applied to them + if (Token::isCompareOp(_operator) || Token::isBitOp(_operator)) + return commonType; + + return TypePointer(); } -bool StaticStringType::operator==(Type const& _other) const +bool FixedBytesType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) return false; - StaticStringType const& other = dynamic_cast(_other); + FixedBytesType const& other = dynamic_cast(_other); return other.m_bytes == m_bytes; } -u256 StaticStringType::literalValue(const Literal* _literal) const +u256 FixedBytesType::literalValue(const Literal* _literal) const { solAssert(_literal, ""); u256 value = 0; @@ -1124,7 +1151,7 @@ MagicType::MagicType(MagicType::Kind _kind): case Kind::Block: m_members = MemberList({{"coinbase", make_shared(0, IntegerType::Modifier::Address)}, {"timestamp", make_shared(256)}, - {"blockhash", make_shared(strings{"uint"}, strings{"hash"}, FunctionType::Location::BlockHash)}, + {"blockhash", make_shared(strings{"uint"}, strings{"bytes32"}, FunctionType::Location::BlockHash)}, {"difficulty", make_shared(256)}, {"number", make_shared(256)}, {"gaslimit", make_shared(256)}}); diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 6cef8d64a..fd59a37ad 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -77,12 +77,12 @@ public: enum class Category { Integer, IntegerConstant, Bool, Real, Array, - String, Contract, Struct, Function, Enum, + FixedBytes, Contract, Struct, Function, Enum, Mapping, Void, TypeType, Modifier, Magic }; - ///@{ - ///@name Factory functions + /// @{ + /// @name Factory functions /// Factory functions that convert an AST @ref TypeName to a Type. static TypePointer fromElementaryTypeName(Token::Value _typeToken); static TypePointer fromElementaryTypeName(std::string const& _name); @@ -158,14 +158,14 @@ protected: }; /** - * Any kind of integer type including hash and address. + * Any kind of integer type (signed, unsigned, address). */ class IntegerType: public Type { public: enum class Modifier { - Unsigned, Signed, Hash, Address + Unsigned, Signed, Address }; virtual Category getCategory() const override { return Category::Integer; } @@ -186,7 +186,6 @@ public: virtual std::string toString() const override; int getNumBits() const { return m_bits; } - bool isHash() const { return m_modifier == Modifier::Hash || m_modifier == Modifier::Address; } bool isAddress() const { return m_modifier == Modifier::Address; } bool isSigned() const { return m_modifier == Modifier::Signed; } @@ -232,27 +231,29 @@ private: }; /** - * String type with fixed length, up to 32 bytes. + * Bytes type with fixed length of up to 32 bytes. */ -class StaticStringType: public Type +class FixedBytesType: public Type { public: - virtual Category getCategory() const override { return Category::String; } + virtual Category getCategory() const override { return Category::FixedBytes; } - /// @returns the smallest string type for the given literal or an empty pointer + /// @returns the smallest bytes type for the given literal or an empty pointer /// if no type fits. - static std::shared_ptr smallestTypeForLiteral(std::string const& _literal); + static std::shared_ptr smallestTypeForLiteral(std::string const& _literal); - explicit StaticStringType(int _bytes); + explicit FixedBytesType(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 TypePointer unaryOperatorResult(Token::Value _operator) const override; + virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override; virtual unsigned getCalldataEncodedSize(bool _padded) const override { return _padded && m_bytes > 0 ? 32 : m_bytes; } virtual bool isValueType() const override { return true; } - virtual std::string toString() const override { return "string" + dev::toString(m_bytes); } + virtual std::string toString() const override { return "bytes" + dev::toString(m_bytes); } virtual u256 literalValue(Literal const* _literal) const override; int getNumBytes() const { return m_bytes; } diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index bb258334c..28934160a 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -77,15 +77,15 @@ namespace { IntegerType const* it = dynamic_cast(_type); unsigned size = it->getNumBits() / 8; - SolidityType::Type typeCode = it->isAddress() ? SolidityType::Type::Address : it->isHash() ? SolidityType::Type::Hash : it->isSigned() ? SolidityType::Type::SignedInteger : SolidityType::Type::UnsignedInteger; + SolidityType::Type typeCode = it->isAddress() ? SolidityType::Type::Address : it->isSigned() ? SolidityType::Type::SignedInteger : SolidityType::Type::UnsignedInteger; return SolidityType { typeCode, size }; } case Type::Category::Bool: return SolidityType { SolidityType::Type::Bool, _type->getSizeOnStack() * 32 }; - case Type::Category::String: + case Type::Category::FixedBytes: { - StaticStringType const* s = dynamic_cast(_type); - return SolidityType { SolidityType::Type::String, static_cast(s->getNumBytes()) }; + FixedBytesType const* s = dynamic_cast(_type); + return SolidityType { SolidityType::Type::FixedBytes, static_cast(s->getNumBytes()) }; } case Type::Category::Contract: return SolidityType { SolidityType::Type::Address, _type->getSizeOnStack() * 32 }; diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 92111996c..0294ca7c3 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -72,10 +72,9 @@ struct SolidityType { SignedInteger, UnsignedInteger, - Hash, Bool, Address, - String, + FixedBytes, }; Type type; unsigned size; //bytes diff --git a/test/SolidityABIJSON.cpp b/test/SolidityABIJSON.cpp index 5f67a5667..195270138 100644 --- a/test/SolidityABIJSON.cpp +++ b/test/SolidityABIJSON.cpp @@ -339,10 +339,10 @@ BOOST_AUTO_TEST_CASE(inherited) char const* sourceCode = " contract Base { \n" " function baseFunction(uint p) returns (uint i) { return p; } \n" - " event baseEvent(string32 indexed evtArgBase); \n" + " event baseEvent(bytes32 indexed evtArgBase); \n" " } \n" " contract Derived is Base { \n" - " function derivedFunction(string32 p) returns (string32 i) { return p; } \n" + " function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } \n" " event derivedEvent(uint indexed evtArgDerived); \n" " }"; @@ -369,12 +369,12 @@ BOOST_AUTO_TEST_CASE(inherited) "inputs": [{ "name": "p", - "type": "string32" + "type": "bytes32" }], "outputs": [{ "name": "i", - "type": "string32" + "type": "bytes32" }] }, { @@ -394,7 +394,7 @@ BOOST_AUTO_TEST_CASE(inherited) [{ "indexed": true, "name": "evtArgBase", - "type": "string32" + "type": "bytes32" }] }])"; diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 3205c038a..2f965849b 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -507,23 +507,23 @@ BOOST_AUTO_TEST_CASE(small_signed_types) BOOST_AUTO_TEST_CASE(strings) { char const* sourceCode = "contract test {\n" - " function fixed() returns(string32 ret) {\n" + " function fixed() returns(bytes32 ret) {\n" " return \"abc\\x00\\xff__\";\n" " }\n" - " function pipeThrough(string2 small, bool one) returns(string16 large, bool oneRet) {\n" + " function pipeThrough(bytes2 small, bool one) returns(bytes16 large, bool oneRet) {\n" " oneRet = one;\n" " large = small;\n" " }\n" "}\n"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("fixed()") == encodeArgs(string("abc\0\xff__", 7))); - BOOST_CHECK(callContractFunction("pipeThrough(string2,bool)", string("\0\x02", 2), true) == encodeArgs(string("\0\x2", 2), true)); + BOOST_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true) == encodeArgs(string("\0\x2", 2), true)); } BOOST_AUTO_TEST_CASE(empty_string_on_stack) { char const* sourceCode = "contract test {\n" - " function run(string0 empty, uint8 inp) returns(uint16 a, string0 b, string4 c) {\n" + " function run(bytes0 empty, uint8 inp) returns(uint16 a, bytes0 b, bytes4 c) {\n" " var x = \"abc\";\n" " var y = \"\";\n" " var z = inp;\n" @@ -531,7 +531,7 @@ BOOST_AUTO_TEST_CASE(empty_string_on_stack) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("run(string0,uint8)", string(), byte(0x02)) == encodeArgs(0x2, string(""), string("abc\0"))); + BOOST_CHECK(callContractFunction("run(bytes0,uint8)", string(), byte(0x02)) == encodeArgs(0x2, string(""), string("abc\0"))); } BOOST_AUTO_TEST_CASE(state_smoke_test) @@ -948,8 +948,8 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) { char const* sourceCode = "contract test {\n" " uint256 public data;\n" - " string6 public name;\n" - " hash public a_hash;\n" + " bytes6 public name;\n" + " bytes32 public a_hash;\n" " address public an_address;\n" " function test() {\n" " data = 8;\n" @@ -971,7 +971,7 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) BOOST_AUTO_TEST_CASE(complex_accessors) { char const* sourceCode = "contract test {\n" - " mapping(uint256 => string4) public to_string_map;\n" + " mapping(uint256 => bytes4) public to_string_map;\n" " mapping(uint256 => bool) public to_bool_map;\n" " mapping(uint256 => uint256) public to_uint_map;\n" " mapping(uint256 => mapping(uint256 => uint256)) public to_multiple_map;\n" @@ -1076,96 +1076,96 @@ 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) +BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_smaller_size) { char const* sourceCode = R"( contract Test { - function pipeTrough(string3 input) returns (string3 ret) { - return string3(input); + function pipeTrough(bytes3 input) returns (bytes2 ret) { + return bytes2(input); } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("pipeTrough(string3)", "abc") == encodeArgs("abc")); + BOOST_CHECK(callContractFunction("pipeTrough(bytes3)", "abc") == encodeArgs("ab")); } -BOOST_AUTO_TEST_CASE(convert_hash_to_string_same_size) +BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_size) { char const* sourceCode = R"( contract Test { - function hashToString(hash h) returns (string32 s) { - return string32(h); + function uintToBytes(uint256 h) returns (bytes32 s) { + return bytes32(h); } })"; compileAndRun(sourceCode); u256 a("0x6162630000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK(callContractFunction("hashToString(hash256)", a) == encodeArgs(a)); + BOOST_CHECK(callContractFunction("uintToBytes(uint256)", a) == encodeArgs(a)); } -BOOST_AUTO_TEST_CASE(convert_hash_to_string_different_size) +BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_different_size) { char const* sourceCode = R"( contract Test { - function hashToString(hash160 h) returns (string20 s) { - return string20(h); + function uintToBytes(uint160 h) returns (bytes20 s) { + return bytes20(h); } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("hashToString(hash160)", u160("0x6161626361626361626361616263616263616263")) == - encodeArgs(string("aabcabcabcaabcabcabc"))); + BOOST_CHECK(callContractFunction("uintToBytes(uint160)", + u160("0x6161626361626361626361616263616263616263")) == encodeArgs(string("aabcabcabcaabcabcabc"))); } -BOOST_AUTO_TEST_CASE(convert_string_to_hash_same_size) +BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_size) { char const* sourceCode = R"( contract Test { - function stringToHash(string32 s) returns (hash h) { - return hash(s); + function bytesToUint(bytes32 s) returns (uint256 h) { + return uint(s); } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("stringToHash(string32)", string("abc2")) == - encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000"))); + BOOST_CHECK(callContractFunction("bytesToUint(bytes32)", string("abc2")) == + encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000"))); } -BOOST_AUTO_TEST_CASE(convert_string_to_hash_different_size) +BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_different_size) { char const* sourceCode = R"( contract Test { - function stringToHash(string20 s) returns (hash160 h) { - return hash160(s); + function bytesToUint(bytes20 s) returns (uint160 h) { + return uint160(s); } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("stringToHash(string20)", string("aabcabcabcaabcabcabc")) == - encodeArgs(u160("0x6161626361626361626361616263616263616263"))); + BOOST_CHECK(callContractFunction("bytesToUint(bytes20)", string("aabcabcabcaabcabcabc")) == + encodeArgs(u160("0x6161626361626361626361616263616263616263"))); } -BOOST_AUTO_TEST_CASE(convert_string_to_hash_different_min_size) +BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_different_min_size) { char const* sourceCode = R"( contract Test { - function stringToHash(string1 s) returns (hash8 h) { - return hash8(s); + function bytesToUint(bytes1 s) returns (uint8 h) { + return uint8(s); } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("stringToHash(string1)", string("a")) == - encodeArgs(u256("0x61"))); + BOOST_CHECK(callContractFunction("bytesToUint(bytes1)", string("a")) == + encodeArgs(u256("0x61"))); } -BOOST_AUTO_TEST_CASE(convert_hash_to_string_different_min_size) +BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_different_min_size) { char const* sourceCode = R"( contract Test { - function HashToString(hash8 h) returns (string1 s) { - return string1(h); + function UintToBytes(uint8 h) returns (bytes1 s) { + return bytes1(h); } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("HashToString(hash8)", u256("0x61")) == - encodeArgs(string("a"))); + BOOST_CHECK(callContractFunction("UintToBytes(uint8)", u256("0x61")) == + encodeArgs(string("a"))); } BOOST_AUTO_TEST_CASE(send_ether) @@ -1299,7 +1299,7 @@ BOOST_AUTO_TEST_CASE(suicide) BOOST_AUTO_TEST_CASE(sha3) { char const* sourceCode = "contract test {\n" - " function a(hash input) returns (hash sha3hash) {\n" + " function a(bytes32 input) returns (bytes32 sha3hash) {\n" " return sha3(input);\n" " }\n" "}\n"; @@ -1308,15 +1308,15 @@ BOOST_AUTO_TEST_CASE(sha3) { return dev::sha3(toBigEndian(_x)); }; - testSolidityAgainstCpp("a(hash256)", f, u256(4)); - testSolidityAgainstCpp("a(hash256)", f, u256(5)); - testSolidityAgainstCpp("a(hash256)", f, u256(-1)); + testSolidityAgainstCpp("a(bytes32)", f, u256(4)); + testSolidityAgainstCpp("a(bytes32)", f, u256(5)); + testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); } BOOST_AUTO_TEST_CASE(sha256) { char const* sourceCode = "contract test {\n" - " function a(hash input) returns (hash sha256hash) {\n" + " function a(bytes32 input) returns (bytes32 sha256hash) {\n" " return sha256(input);\n" " }\n" "}\n"; @@ -1327,15 +1327,15 @@ BOOST_AUTO_TEST_CASE(sha256) dev::sha256(dev::ref(toBigEndian(_input)), bytesRef(&ret[0], 32)); return ret; }; - testSolidityAgainstCpp("a(hash256)", f, u256(4)); - testSolidityAgainstCpp("a(hash256)", f, u256(5)); - testSolidityAgainstCpp("a(hash256)", f, u256(-1)); + testSolidityAgainstCpp("a(bytes32)", f, u256(4)); + testSolidityAgainstCpp("a(bytes32)", f, u256(5)); + testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); } BOOST_AUTO_TEST_CASE(ripemd) { char const* sourceCode = "contract test {\n" - " function a(hash input) returns (hash sha256hash) {\n" + " function a(bytes32 input) returns (bytes32 sha256hash) {\n" " return ripemd160(input);\n" " }\n" "}\n"; @@ -1346,15 +1346,15 @@ BOOST_AUTO_TEST_CASE(ripemd) dev::ripemd160(dev::ref(toBigEndian(_input)), bytesRef(&ret[0], 32)); return u256(ret) >> (256 - 160); }; - testSolidityAgainstCpp("a(hash256)", f, u256(4)); - testSolidityAgainstCpp("a(hash256)", f, u256(5)); - testSolidityAgainstCpp("a(hash256)", f, u256(-1)); + testSolidityAgainstCpp("a(bytes32)", f, u256(4)); + testSolidityAgainstCpp("a(bytes32)", f, u256(5)); + testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); } BOOST_AUTO_TEST_CASE(ecrecover) { char const* sourceCode = "contract test {\n" - " function a(hash h, uint8 v, hash r, hash s) returns (address addr) {\n" + " function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address addr) {\n" " return ecrecover(h, v, r, s);\n" " }\n" "}\n"; @@ -1364,7 +1364,7 @@ BOOST_AUTO_TEST_CASE(ecrecover) u256 r("0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"); u256 s("0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"); u160 addr("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); - BOOST_CHECK(callContractFunction("a(hash256,uint8,hash256,hash256)", h, v, r, s) == encodeArgs(addr)); + BOOST_CHECK(callContractFunction("a(bytes32,uint8,bytes32,bytes32)", h, v, r, s) == encodeArgs(addr)); } BOOST_AUTO_TEST_CASE(inter_contract_calls) @@ -1524,17 +1524,17 @@ BOOST_AUTO_TEST_CASE(inter_contract_calls_with_local_vars) BOOST_REQUIRE(callContractFunction("callHelper(uint256,uint256)", a, b) == encodeArgs(a * b + 9)); } -BOOST_AUTO_TEST_CASE(strings_in_calls) +BOOST_AUTO_TEST_CASE(fixed_bytes_in_calls) { char const* sourceCode = R"( contract Helper { - function invoke(string3 x, bool stop) returns (string4 ret) { + function invoke(bytes3 x, bool stop) returns (bytes4 ret) { return x; } } contract Main { Helper h; - function callHelper(string2 x, bool stop) returns (string5 ret) { + function callHelper(bytes2 x, bool stop) returns (bytes5 ret) { return h.invoke(x, stop); } function getHelper() returns (address addr) { @@ -1549,21 +1549,21 @@ BOOST_AUTO_TEST_CASE(strings_in_calls) compileAndRun(sourceCode, 0, "Main"); BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes()); BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress)); - BOOST_CHECK(callContractFunction("callHelper(string2,bool)", string("\0a", 2), true) == encodeArgs(string("\0a\0\0\0", 5))); + BOOST_CHECK(callContractFunction("callHelper(bytes2,bool)", string("\0a", 2), true) == encodeArgs(string("\0a\0\0\0", 5))); } BOOST_AUTO_TEST_CASE(constructor_arguments) { char const* sourceCode = R"( contract Helper { - string3 name; + bytes3 name; bool flag; - function Helper(string3 x, bool f) { + function Helper(bytes3 x, bool f) { name = x; flag = f; } - function getName() returns (string3 ret) { return name; } + function getName() returns (bytes3 ret) { return name; } function getFlag() returns (bool ret) { return flag; } } contract Main { @@ -1572,7 +1572,7 @@ BOOST_AUTO_TEST_CASE(constructor_arguments) h = new Helper("abc", true); } function getFlag() returns (bool ret) { return h.getFlag(); } - function getName() returns (string3 ret) { return h.getName(); } + function getName() returns (bytes3 ret) { return h.getName(); } })"; compileAndRun(sourceCode, 0, "Main"); BOOST_REQUIRE(callContractFunction("getFlag()") == encodeArgs(true)); @@ -1583,13 +1583,13 @@ BOOST_AUTO_TEST_CASE(functions_called_by_constructor) { char const* sourceCode = R"( contract Test { - string3 name; + bytes3 name; bool flag; function Test() { setName("abc"); } - function getName() returns (string3 ret) { return name; } - function setName(string3 _name) private { name = _name; } + function getName() returns (bytes3 ret) { return name; } + function setName(bytes3 _name) private { name = _name; } })"; compileAndRun(sourceCode); BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc")); @@ -1697,13 +1697,13 @@ BOOST_AUTO_TEST_CASE(value_for_constructor) { char const* sourceCode = R"( contract Helper { - string3 name; + bytes3 name; bool flag; - function Helper(string3 x, bool f) { + function Helper(bytes3 x, bool f) { name = x; flag = f; } - function getName() returns (string3 ret) { return name; } + function getName() returns (bytes3 ret) { return name; } function getFlag() returns (bool ret) { return flag; } } contract Main { @@ -1712,7 +1712,7 @@ BOOST_AUTO_TEST_CASE(value_for_constructor) h = new Helper.value(10)("abc", true); } function getFlag() returns (bool ret) { return h.getFlag(); } - function getName() returns (string3 ret) { return h.getName(); } + function getName() returns (bytes3 ret) { return h.getName(); } function getBalances() returns (uint me, uint them) { me = this.balance; them = h.balance;} })"; compileAndRun(sourceCode, 22, "Main"); @@ -2090,13 +2090,13 @@ BOOST_AUTO_TEST_CASE(event) { char const* sourceCode = R"( contract ClientReceipt { - event Deposit(address indexed _from, hash indexed _id, uint _value); - function deposit(hash _id, bool _manually) { + event Deposit(address indexed _from, bytes32 indexed _id, uint _value); + function deposit(bytes32 _id, bool _manually) { if (_manually) { - hash s = 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20; - log3(msg.value, s, hash32(msg.sender), _id); + bytes32 s = 0x19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f; + log3(bytes32(msg.value), s, bytes32(msg.sender), _id); } else - Deposit(hash32(msg.sender), _id, msg.value); + Deposit(msg.sender, _id, msg.value); } } )"; @@ -2105,12 +2105,12 @@ BOOST_AUTO_TEST_CASE(event) u256 id(0x1234); for (bool manually: {true, false}) { - callContractFunctionWithValue("deposit(hash256,bool)", value, id, manually); + callContractFunctionWithValue("deposit(bytes32,bool)", value, id, manually); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(value))); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3); - BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256)"))); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,bytes32,uint256)"))); BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(m_sender)); BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(id)); } @@ -2139,21 +2139,21 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data) { char const* sourceCode = R"( contract ClientReceipt { - event Deposit(address _from, hash _id, uint _value, bool _flag); - function deposit(hash _id) { - Deposit(msg.sender, hash32(_id), msg.value, true); + event Deposit(address _from, bytes32 _id, uint _value, bool _flag); + function deposit(bytes32 _id) { + Deposit(msg.sender, _id, msg.value, true); } } )"; compileAndRun(sourceCode); u256 value(18); u256 id(0x1234); - callContractFunctionWithValue("deposit(hash256)", value, id); + callContractFunctionWithValue("deposit(bytes32)", value, id); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs((u160)m_sender, id, value, true)); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,bytes32,uint256,bool)"))); } BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) @@ -2187,7 +2187,7 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) { char const* sourceCode = R"( contract c { - function foo(uint a, uint b, uint c) returns (hash d) + function foo(uint a, uint b, uint c) returns (bytes32 d) { d = sha3(a, b, c); } @@ -2205,7 +2205,7 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals) { char const* sourceCode = R"( contract c { - function foo(uint a, uint16 b) returns (hash d) + function foo(uint a, uint16 b) returns (bytes32 d) { d = sha3(a, b, 145); } @@ -2223,11 +2223,11 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals) { char const* sourceCode = R"( contract c { - function foo() returns (hash d) + function foo() returns (bytes32 d) { d = sha3("foo"); } - function bar(uint a, uint16 b) returns (hash d) + function bar(uint a, uint16 b) returns (bytes32 d) { d = sha3(a, b, 145, "foo"); } @@ -2254,7 +2254,7 @@ BOOST_AUTO_TEST_CASE(generic_call) contract sender { function doSend(address rec) returns (uint d) { - string4 signature = string4(string32(sha3("receive(uint256)"))); + bytes4 signature = bytes4(bytes32(sha3("receive(uint256)"))); rec.call.value(2)(signature, 23); return receiver(rec).received(); } @@ -2290,7 +2290,7 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) { char const* sourceCode = R"( contract C { - function() returns (hash) { + function() returns (bytes32) { return sha3("abc", msg.data); } } @@ -3181,7 +3181,6 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap) BOOST_CHECK(callContractFunction("m_i()") == encodeArgs(4)); } - BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityInterface.cpp b/test/SolidityInterface.cpp index ecab64c8c..48e2fd7aa 100644 --- a/test/SolidityInterface.cpp +++ b/test/SolidityInterface.cpp @@ -84,10 +84,10 @@ BOOST_AUTO_TEST_CASE(single_function) BOOST_AUTO_TEST_CASE(single_constant_function) { ContractDefinition const& contract = checkInterface( - "contract test { function f(uint a) constant returns(hash8 x) { 1==2; } }"); + "contract test { function f(uint a) constant returns(bytes1 x) { 1==2; } }"); BOOST_REQUIRE_EQUAL(1, contract.getDefinedFunctions().size()); BOOST_CHECK_EQUAL(getSourcePart(*contract.getDefinedFunctions().front()), - "function f(uint256 a)constant returns(hash8 x){}"); + "function f(uint256 a)constant returns(bytes1 x){}"); } BOOST_AUTO_TEST_CASE(multiple_functions) @@ -128,15 +128,15 @@ BOOST_AUTO_TEST_CASE(inheritance) char const* sourceCode = " contract Base { \n" " function baseFunction(uint p) returns (uint i) { return p; } \n" - " event baseEvent(string32 indexed evtArgBase); \n" + " event baseEvent(bytes32 indexed evtArgBase); \n" " } \n" " contract Derived is Base { \n" - " function derivedFunction(string32 p) returns (string32 i) { return p; } \n" + " function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } \n" " event derivedEvent(uint indexed evtArgDerived); \n" " }"; ContractDefinition const& contract = checkInterface(sourceCode); set expectedFunctions({"function baseFunction(uint256 p)returns(uint256 i){}", - "function derivedFunction(string32 p)returns(string32 i){}"}); + "function derivedFunction(bytes32 p)returns(bytes32 i){}"}); BOOST_REQUIRE_EQUAL(2, contract.getDefinedFunctions().size()); BOOST_CHECK(expectedFunctions == set({getSourcePart(*contract.getDefinedFunctions().at(0)), getSourcePart(*contract.getDefinedFunctions().at(1))})); diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index c3a4a3377..a310800f7 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -75,6 +75,7 @@ static FunctionTypePointer const& retrieveFunctionBySignature(ContractDefinition FixedHash<4> hash(dev::sha3(_signature)); return _contract->getInterfaceFunctions()[hash]; } + } BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution) @@ -353,7 +354,7 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature) " ret = arg1 + arg2;\n" " }\n" "}\n"; - BOOST_CHECK_NO_THROW(sourceUnit = parseTextAndResolveNames(text)); + ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) { @@ -366,16 +367,16 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases) { ASTPointer sourceUnit; char const* text = "contract Test {\n" - " function boo(uint arg1, hash arg2, address arg3) returns (uint ret) {\n" + " function boo(uint arg1, bytes32 arg2, address arg3) returns (uint ret) {\n" " ret = 5;\n" " }\n" "}\n"; - BOOST_CHECK_NO_THROW(sourceUnit = parseTextAndResolveNames(text)); + ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_EQUAL("boo(uint256,hash256,address)", functions[0]->getCanonicalSignature()); + BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->getCanonicalSignature()); } } @@ -537,7 +538,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation) contract B { function f() mod1(2, true) mod2("0123456") { } modifier mod1(uint a, bool b) { if (b) _ } - modifier mod2(string7 a) { while (a == "1234567") _ } + modifier mod2(bytes7 a) { while (a == "1234567") _ } } )"; ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(text), "Parsing and Name Resolving Failed"); @@ -558,9 +559,9 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters) { char const* text = R"( contract B { - function f(uint8 a) mod1(a, true) mod2(r) returns (string7 r) { } + function f(uint8 a) mod1(a, true) mod2(r) returns (bytes7 r) { } modifier mod1(uint a, bool b) { if (b) _ } - modifier mod2(string7 a) { while (a == "1234567") _ } + modifier mod2(bytes7 a) { while (a == "1234567") _ } } )"; ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(text), "Parsing and Name Resolving Failed"); @@ -631,8 +632,8 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) " uint64(2);\n" " }\n" "uint256 public foo;\n" - "mapping(uint=>string4) public map;\n" - "mapping(uint=>mapping(uint=>string4)) public multiple_map;\n" + "mapping(uint=>bytes4) public map;\n" + "mapping(uint=>mapping(uint=>bytes4)) public multiple_map;\n" "}\n"; ASTPointer source; @@ -650,7 +651,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) auto params = function->getParameterTypeNames(); BOOST_CHECK_EQUAL(params.at(0), "uint256"); returnParams = function->getReturnParameterTypeNames(); - BOOST_CHECK_EQUAL(returnParams.at(0), "string4"); + BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4"); BOOST_CHECK(function->isConstant()); function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)"); @@ -659,7 +660,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) BOOST_CHECK_EQUAL(params.at(0), "uint256"); BOOST_CHECK_EQUAL(params.at(1), "uint256"); returnParams = function->getReturnParameterTypeNames(); - BOOST_CHECK_EQUAL(returnParams.at(0), "string4"); + BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4"); BOOST_CHECK(function->isConstant()); } @@ -800,7 +801,7 @@ BOOST_AUTO_TEST_CASE(event) { char const* text = R"( contract c { - event e(uint indexed a, string3 indexed s, bool indexed b); + event e(uint indexed a, bytes3 indexed s, bool indexed b); function f() { e(2, "abc", true); } })"; ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(text), "Parsing and Name Resolving Failed"); @@ -810,7 +811,7 @@ BOOST_AUTO_TEST_CASE(event_too_many_indexed) { char const* text = R"( contract c { - event e(uint indexed a, string3 indexed b, bool indexed c, uint indexed d); + event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d); function f() { e(2, "abc", true); } })"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); @@ -820,7 +821,7 @@ BOOST_AUTO_TEST_CASE(event_call) { char const* text = R"( contract c { - event e(uint a, string3 indexed s, bool indexed b); + event e(uint a, bytes3 indexed s, bool indexed b); function f() { e(2, "abc", true); } })"; ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(text), "Parsing and Name Resolving Failed"); @@ -830,7 +831,7 @@ BOOST_AUTO_TEST_CASE(event_inheritance) { char const* text = R"( contract base { - event e(uint a, string3 indexed s, bool indexed b); + event e(uint a, bytes3 indexed s, bool indexed b); } contract c is base { function f() { e(2, "abc", true); } @@ -1287,6 +1288,122 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName) +{ + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int) == *make_shared(256, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int8) == *make_shared(8, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int16) == *make_shared(16, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int24) == *make_shared(24, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int32) == *make_shared(32, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int40) == *make_shared(40, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int48) == *make_shared(48, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int56) == *make_shared(56, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int64) == *make_shared(64, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int72) == *make_shared(72, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int80) == *make_shared(80, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int88) == *make_shared(88, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int96) == *make_shared(96, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int104) == *make_shared(104, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int112) == *make_shared(112, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int120) == *make_shared(120, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int128) == *make_shared(128, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int136) == *make_shared(136, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int144) == *make_shared(144, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int152) == *make_shared(152, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int160) == *make_shared(160, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int168) == *make_shared(168, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int176) == *make_shared(176, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int184) == *make_shared(184, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int192) == *make_shared(192, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int200) == *make_shared(200, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int208) == *make_shared(208, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int216) == *make_shared(216, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int224) == *make_shared(224, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int232) == *make_shared(232, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int240) == *make_shared(240, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int248) == *make_shared(248, IntegerType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Int256) == *make_shared(256, IntegerType::Modifier::Signed)); + + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt) == *make_shared(256, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt8) == *make_shared(8, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt16) == *make_shared(16, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt24) == *make_shared(24, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt32) == *make_shared(32, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt40) == *make_shared(40, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt48) == *make_shared(48, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt56) == *make_shared(56, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt64) == *make_shared(64, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt72) == *make_shared(72, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt80) == *make_shared(80, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt88) == *make_shared(88, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt96) == *make_shared(96, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt104) == *make_shared(104, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt112) == *make_shared(112, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt120) == *make_shared(120, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt128) == *make_shared(128, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt136) == *make_shared(136, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt144) == *make_shared(144, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt152) == *make_shared(152, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt160) == *make_shared(160, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt168) == *make_shared(168, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt176) == *make_shared(176, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt184) == *make_shared(184, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt192) == *make_shared(192, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt200) == *make_shared(200, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt208) == *make_shared(208, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt216) == *make_shared(216, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt224) == *make_shared(224, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt232) == *make_shared(232, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt240) == *make_shared(240, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt248) == *make_shared(248, IntegerType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::UInt256) == *make_shared(256, IntegerType::Modifier::Unsigned)); + + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Byte) == *make_shared(1)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes0) == *make_shared(0)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes1) == *make_shared(1)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes2) == *make_shared(2)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes3) == *make_shared(3)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes4) == *make_shared(4)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes5) == *make_shared(5)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes6) == *make_shared(6)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes7) == *make_shared(7)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes8) == *make_shared(8)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes9) == *make_shared(9)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes10) == *make_shared(10)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes11) == *make_shared(11)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes12) == *make_shared(12)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes13) == *make_shared(13)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes14) == *make_shared(14)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes15) == *make_shared(15)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes16) == *make_shared(16)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes17) == *make_shared(17)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes18) == *make_shared(18)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes19) == *make_shared(19)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes20) == *make_shared(20)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes21) == *make_shared(21)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes22) == *make_shared(22)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes23) == *make_shared(23)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes24) == *make_shared(24)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes25) == *make_shared(25)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes26) == *make_shared(26)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes27) == *make_shared(27)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes28) == *make_shared(28)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes29) == *make_shared(29)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes30) == *make_shared(30)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes31) == *make_shared(31)); + BOOST_CHECK(*Type::fromElementaryTypeName(Token::Bytes32) == *make_shared(32)); +} + +BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1) +{ + char const* text = R"( + contract c { + bytes arr; + function f() { byte a = arr[0];} + })"; + ETH_TEST_REQUIRE_NO_THROW(parseTextAndResolveNames(text), "Type resolving failed"); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index 88b86e638..2f5d06ef6 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(empty_function) { char const* text = "contract test {\n" " uint256 stateVar;\n" - " function functionName(hash160 arg1, address addr) constant\n" + " function functionName(bytes20 arg1, address addr) constant\n" " returns (int id)\n" " { }\n" "}\n"; @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(single_function_param) { char const* text = "contract test {\n" " uint256 stateVar;\n" - " function functionName(hash hashin) returns (hash hashout) {}\n" + " function functionName(bytes32 input) returns (bytes32 out) {}\n" "}\n"; ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed."); } @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) char const* text = "contract test {\n" " uint256 stateVar;\n" " /// This is a test function\n" - " function functionName(hash hashin) returns (hash hashout) {}\n" + " function functionName(bytes32 input) returns (bytes32 out) {}\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(contract = parseText(text), "Parsing failed"); auto functions = contract->getDefinedFunctions(); @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) char const* text = "contract test {\n" " uint256 stateVar;\n" " // We won't see this comment\n" - " function functionName(hash hashin) returns (hash hashout) {}\n" + " function functionName(bytes32 input) returns (bytes32 out) {}\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(contract = parseText(text), "Parsing failed"); auto functions = contract->getDefinedFunctions(); @@ -164,13 +164,13 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) char const* text = "contract test {\n" " uint256 stateVar;\n" " /// This is test function 1\n" - " function functionName1(hash hashin) returns (hash hashout) {}\n" + " function functionName1(bytes32 input) returns (bytes32 out) {}\n" " /// This is test function 2\n" - " function functionName2(hash hashin) returns (hash hashout) {}\n" + " function functionName2(bytes32 input) returns (bytes32 out) {}\n" " // nothing to see here\n" - " function functionName3(hash hashin) returns (hash hashout) {}\n" + " function functionName3(bytes32 input) returns (bytes32 out) {}\n" " /// This is test function 4\n" - " function functionName4(hash hashin) returns (hash hashout) {}\n" + " function functionName4(bytes32 input) returns (bytes32 out) {}\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(contract = parseText(text), "Parsing failed"); auto functions = contract->getDefinedFunctions(); @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) " uint256 stateVar;\n" " /// This is a test function\n" " /// and it has 2 lines\n" - " function functionName1(hash hashin) returns (hash hashout) {}\n" + " function functionName1(bytes32 input) returns (bytes32 out) {}\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(contract = parseText(text), "Parsing failed"); auto functions = contract->getDefinedFunctions(); @@ -217,12 +217,12 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) " var b;\n" " /// I should not interfere with actual natspec comments\n" " uint256 c;\n" - " mapping(address=>hash) d;\n" - " string name = \"Solidity\";" + " mapping(address=>bytes32) d;\n" + " bytes7 name = \"Solidity\";" " }\n" " /// This is a test function\n" " /// and it has 2 lines\n" - " function fun(hash hashin) returns (hash hashout) {}\n" + " function fun(bytes32 input) returns (bytes32 out) {}\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(contract = parseText(text), "Parsing failed"); auto functions = contract->getDefinedFunctions(); @@ -246,8 +246,8 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature) " var b;\n" " /// I should not interfere with actual natspec comments\n" " uint256 c;\n" - " mapping(address=>hash) d;\n" - " string name = \"Solidity\";" + " mapping(address=>bytes32) d;\n" + " bytes7 name = \"Solidity\";" " }\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(contract = parseText(text), "Parsing failed"); @@ -269,8 +269,8 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) " var b;\n" " /// I should not interfere with actual natspec comments\n" " uint256 c;\n" - " mapping(address=>hash) d;\n" - " string name = \"Solidity\";" + " mapping(address=>bytes32) d;\n" + " bytes7 name = \"Solidity\";" " }\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(contract = parseText(text), "Parsing failed"); @@ -296,7 +296,7 @@ BOOST_AUTO_TEST_CASE(struct_definition) BOOST_AUTO_TEST_CASE(mapping) { char const* text = "contract test {\n" - " mapping(address => string) names;\n" + " mapping(address => bytes32) names;\n" "}\n"; ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed"); } @@ -307,7 +307,7 @@ BOOST_AUTO_TEST_CASE(mapping_in_struct) " struct test_struct {\n" " address addr;\n" " uint256 count;\n" - " mapping(hash => test_struct) self_reference;\n" + " mapping(bytes32 => test_struct) self_reference;\n" " }\n" "}\n"; ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed"); @@ -318,7 +318,7 @@ BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct) char const* text = "contract test {\n" " struct test_struct {\n" " address addr;\n" - " mapping (uint64 => mapping (hash => uint)) complex_mapping;\n" + " mapping (uint64 => mapping (bytes32 => uint)) complex_mapping;\n" " }\n" "}\n"; ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed"); @@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE(variable_definition) " function fun(uint256 a) {\n" " var b;\n" " uint256 c;\n" - " mapping(address=>hash) d;\n" + " mapping(address=>bytes32) d;\n" " customtype varname;\n" " }\n" "}\n"; @@ -343,8 +343,8 @@ BOOST_AUTO_TEST_CASE(variable_definition_with_initialization) " function fun(uint256 a) {\n" " var b = 2;\n" " uint256 c = 0x87;\n" - " mapping(address=>hash) d;\n" - " string name = \"Solidity\";" + " mapping(address=>bytes32) d;\n" + " bytes7 name = \"Solidity\";" " customtype varname;\n" " }\n" "}\n"; @@ -366,7 +366,7 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_mapping) char const* text = R"( contract test { function fun() { - mapping(var=>hash) d; + mapping(var=>bytes32) d; } } )"; @@ -662,7 +662,7 @@ BOOST_AUTO_TEST_CASE(event_arguments) { char const* text = R"( contract c { - event e(uint a, string32 s); + event e(uint a, bytes32 s); })"; ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed"); } @@ -671,7 +671,7 @@ BOOST_AUTO_TEST_CASE(event_arguments_indexed) { char const* text = R"( contract c { - event e(uint a, string32 indexed s, bool indexed b); + event e(uint a, bytes32 indexed s, bool indexed b); })"; ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed"); } @@ -799,7 +799,7 @@ BOOST_AUTO_TEST_CASE(arrays_in_events) { char const* text = R"( contract c { - event e(uint[10] a, string7[8] indexed b, c[3] x); + event e(uint[10] a, bytes7[8] indexed b, c[3] x); })"; ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed"); }