Changed occurences of isByteArray() to isByteArrayOrString(). The idea

is to, in a future commit, replace such occurences of
isByteArrayOrString() which are required to return True only for Bytes
type with a new isByteArray() function.
This commit is contained in:
nishant-sachdeva 2022-01-28 23:27:05 +05:30
parent a05d2b356a
commit 9043621747
15 changed files with 120 additions and 120 deletions

View File

@ -441,7 +441,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
{
bool allowed = false;
if (auto arrayType = dynamic_cast<ArrayType const*>(type))
allowed = arrayType->isByteArray();
allowed = arrayType->isByteArrayOrString();
if (!allowed)
m_errorReporter.fatalTypeError(9259_error, _variable.location(), "Only constants of value type and byte array type are implemented.");
}

View File

@ -1783,7 +1783,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
(
(
resultArrayType->isPointer() ||
(argArrayType->isByteArray() && resultArrayType->isByteArray())
(argArrayType->isByteArrayOrString() && resultArrayType->isByteArrayOrString())
) &&
resultArrayType->location() == DataLocation::Storage
),
@ -1791,7 +1791,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
);
else
solAssert(
argArrayType->isByteArray() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes,
argArrayType->isByteArrayOrString() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes,
""
);
}

View File

@ -1206,7 +1206,7 @@ BoolResult StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo)
);
return
arrayType->location() != DataLocation::CallData &&
arrayType->isByteArray() &&
arrayType->isByteArrayOrString() &&
!(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer());
}
else
@ -1530,7 +1530,7 @@ BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const
if (_convertTo.category() != category())
return false;
auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
if (convertTo.isByteArray() != isByteArray() || convertTo.isString() != isString())
if (convertTo.isByteArrayOrString() != isByteArrayOrString() || convertTo.isString() != isString())
return false;
// memory/calldata to storage can be converted, but only to a direct storage reference
if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer())
@ -1571,11 +1571,11 @@ BoolResult ArrayType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return true;
// allow conversion bytes <-> string and bytes -> bytesNN
if (_convertTo.category() != category())
return isByteArray() && !isString() && _convertTo.category() == Type::Category::FixedBytes;
return isByteArrayOrString() && !isString() && _convertTo.category() == Type::Category::FixedBytes;
auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
if (convertTo.location() != location())
return false;
if (!isByteArray() || !convertTo.isByteArray())
if (!isByteArrayOrString() || !convertTo.isByteArrayOrString())
return false;
return true;
}
@ -1585,7 +1585,7 @@ string ArrayType::richIdentifier() const
string id;
if (isString())
id = "t_string";
else if (isByteArray())
else if (isByteArrayOrString())
id = "t_bytes";
else
{
@ -1608,7 +1608,7 @@ bool ArrayType::operator==(Type const& _other) const
ArrayType const& other = dynamic_cast<ArrayType const&>(_other);
if (
!ReferenceType::operator==(other) ||
other.isByteArray() != isByteArray() ||
other.isByteArrayOrString() != isByteArrayOrString() ||
other.isString() != isString() ||
other.isDynamicallySized() != isDynamicallySized()
)
@ -1751,7 +1751,7 @@ string ArrayType::toString(bool _short) const
string ret;
if (isString())
ret = "string";
else if (isByteArray())
else if (isByteArrayOrString())
ret = "bytes";
else
{
@ -1770,7 +1770,7 @@ string ArrayType::canonicalName() const
string ret;
if (isString())
ret = "string";
else if (isByteArray())
else if (isByteArrayOrString())
ret = "bytes";
else
{
@ -1784,7 +1784,7 @@ string ArrayType::canonicalName() const
string ArrayType::signatureInExternalFunction(bool _structsByName) const
{
if (isByteArray())
if (isByteArrayOrString())
return canonicalName();
else
{
@ -1899,7 +1899,7 @@ u256 ArrayType::memoryDataSize() const
{
solAssert(!isDynamicallySized(), "");
solAssert(m_location == DataLocation::Memory, "");
solAssert(!isByteArray(), "");
solAssert(!isByteArrayOrString(), "");
bigint size = bigint(m_length) * m_baseType->memoryHeadSize();
solAssert(size <= numeric_limits<u256>::max(), "Array size does not fit u256.");
return u256(size);
@ -2701,7 +2701,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
}
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
{
if (arrayType->isByteArray())
if (arrayType->isByteArrayOrString())
// Return byte arrays as whole.
break;
returnType = arrayType->baseType();
@ -2720,7 +2720,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
if (member.type->category() != Category::Mapping)
{
if (auto arrayType = dynamic_cast<ArrayType const*>(member.type))
if (!arrayType->isByteArray())
if (!arrayType->isByteArrayOrString())
continue;
m_returnParameterTypes.push_back(TypeProvider::withLocationIfReference(
DataLocation::Memory,
@ -3813,7 +3813,7 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
}
else if (
auto const* arrayType = dynamic_cast<ArrayType const*>(m_actualType);
arrayType && arrayType->isByteArray()
arrayType && arrayType->isByteArrayOrString()
)
members.emplace_back("concat", TypeProvider::function(
TypePointers{},

View File

@ -838,7 +838,7 @@ public:
BoolResult validForLocation(DataLocation _loc) const override;
/// @returns true if this is a byte array or a string
bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; }
bool isByteArrayOrString() const { return m_arrayKind != ArrayKind::Ordinary; }
/// @returns true if this is a string
bool isString() const { return m_arrayKind == ArrayKind::String; }
Type const* baseType() const { solAssert(!!m_baseType, ""); return m_baseType; }
@ -849,11 +849,11 @@ public:
std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const override;
/// The offset to advance in calldata to move from one array element to the next.
unsigned calldataStride() const { return isByteArray() ? 1 : m_baseType->calldataHeadSize(); }
unsigned calldataStride() const { return isByteArrayOrString() ? 1 : m_baseType->calldataHeadSize(); }
/// The offset to advance in memory to move from one array element to the next.
unsigned memoryStride() const { return isByteArray() ? 1 : m_baseType->memoryHeadSize(); }
unsigned memoryStride() const { return isByteArrayOrString() ? 1 : m_baseType->memoryHeadSize(); }
/// The offset to advance in storage to move from one array element to the next.
unsigned storageStride() const { return isByteArray() ? 1 : m_baseType->storageBytes(); }
unsigned storageStride() const { return isByteArrayOrString() ? 1 : m_baseType->storageBytes(); }
void clearCache() const override;

View File

@ -312,7 +312,7 @@ string ABIFunctions::abiEncodingFunction(
{
case DataLocation::CallData:
if (
fromArray->isByteArray() ||
fromArray->isByteArrayOrString() ||
*fromArray->baseType() == *TypeProvider::uint256() ||
*fromArray->baseType() == FixedBytesType(32)
)
@ -320,7 +320,7 @@ string ABIFunctions::abiEncodingFunction(
else
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
case DataLocation::Memory:
if (fromArray->isByteArray())
if (fromArray->isByteArrayOrString())
return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options);
else
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
@ -448,7 +448,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
solAssert(fromArrayType.location() == DataLocation::CallData, "");
solAssert(
fromArrayType.isByteArray() ||
fromArrayType.isByteArrayOrString() ||
*fromArrayType.baseType() == *TypeProvider::uint256() ||
*fromArrayType.baseType() == FixedBytesType(32),
""
@ -468,7 +468,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
_to.identifier() +
_options.toFunctionNameSuffix();
return createFunction(functionName, [&]() {
bool needsPadding = _options.padded && fromArrayType.isByteArray();
bool needsPadding = _options.padded && fromArrayType.isByteArrayOrString();
if (fromArrayType.isDynamicallySized())
{
Whiskers templ(R"(
@ -482,7 +482,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
)");
templ("storeLength", arrayStoreLengthForEncodingFunction(toArrayType, _options));
templ("functionName", functionName);
if (fromArrayType.isByteArray() || fromArrayType.calldataStride() == 1)
if (fromArrayType.isByteArrayOrString() || fromArrayType.calldataStride() == 1)
templ("scaleLengthByStride", "");
else
templ("scaleLengthByStride",
@ -536,7 +536,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), "");
solAssert(_from.length() == _to.length(), "");
solAssert(!_from.isByteArray(), "");
solAssert(!_from.isByteArrayOrString(), "");
if (_from.dataStoredIn(DataLocation::Storage))
solAssert(_from.baseType()->storageBytes() > 16, "");
@ -647,10 +647,10 @@ string ABIFunctions::abiEncodingFunctionMemoryByteArray(
solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), "");
solAssert(_from.length() == _to.length(), "");
solAssert(_from.dataStoredIn(DataLocation::Memory), "");
solAssert(_from.isByteArray(), "");
solAssert(_from.isByteArrayOrString(), "");
return createFunction(functionName, [&]() {
solAssert(_to.isByteArray(), "");
solAssert(_to.isByteArrayOrString(), "");
Whiskers templ(R"(
function <functionName>(value, pos) -> end {
let length := <lengthFun>(value)
@ -686,9 +686,9 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
solAssert(_from.dataStoredIn(DataLocation::Storage), "");
return createFunction(functionName, [&]() {
if (_from.isByteArray())
if (_from.isByteArrayOrString())
{
solAssert(_to.isByteArray(), "");
solAssert(_to.isByteArrayOrString(), "");
Whiskers templ(R"(
// <readableTypeNameFrom> -> <readableTypeNameTo>
function <functionName>(value, pos) -> ret {
@ -1168,7 +1168,7 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from
string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
{
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
if (_type.isByteArray())
if (_type.isByteArrayOrString())
return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory);
solAssert(_type.calldataStride() > 0, "");
@ -1275,7 +1275,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
{
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
solAssert(_type.isByteArray(), "");
solAssert(_type.isByteArrayOrString(), "");
string functionName =
"abi_decode_available_length_" +

View File

@ -50,8 +50,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
solAssert(_targetType.location() == DataLocation::Storage, "");
Type const* uint256 = TypeProvider::uint256();
Type const* targetBaseType = _targetType.isByteArray() ? uint256 : _targetType.baseType();
Type const* sourceBaseType = _sourceType.isByteArray() ? uint256 : _sourceType.baseType();
Type const* targetBaseType = _targetType.isByteArrayOrString() ? uint256 : _targetType.baseType();
Type const* sourceBaseType = _sourceType.isByteArrayOrString() ? uint256 : _sourceType.baseType();
// TODO unroll loop for small sizes
@ -97,7 +97,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack: target_ref source_ref source_length target_ref target_length
if (_targetType.isDynamicallySized())
// store new target length
if (!_targetType.isByteArray())
if (!_targetType.isByteArrayOrString())
// Otherwise, length will be stored below.
_context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE;
if (sourceBaseType->category() == Type::Category::Mapping)
@ -126,7 +126,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
evmasm::AssemblyItem copyLoopEndWithoutByteOffset = _context.newTag();
// special case for short byte arrays: Store them together with their length.
if (_targetType.isByteArray())
if (_targetType.isByteArrayOrString())
{
// stack: target_ref target_data_end source_length target_data_pos source_ref
_context << Instruction::DUP3;
@ -141,7 +141,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
_context << Instruction::DUP3 << u256(31) << Instruction::LT;
evmasm::AssemblyItem longByteArray = _context.appendConditionalJump();
// store the short byte array
solAssert(_sourceType.isByteArray(), "");
solAssert(_sourceType.isByteArrayOrString(), "");
if (_sourceType.location() == DataLocation::Storage)
{
// just copy the slot, it contains length and data
@ -323,7 +323,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
{
if (!_sourceType.isDynamicallySized())
m_context << _sourceType.length();
if (!_sourceType.isByteArray())
if (!_sourceType.isByteArrayOrString())
convertLengthToSize(_sourceType);
string routine = "calldatacopy(target, source, len)\n";
@ -375,14 +375,14 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
m_context << Instruction::SWAP1 << u256(32) << Instruction::ADD;
m_context << Instruction::SWAP1;
}
if (!_sourceType.isByteArray())
if (!_sourceType.isByteArrayOrString())
convertLengthToSize(_sourceType);
// stack: <target> <source> <size>
m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4;
// We can resort to copying full 32 bytes only if
// - the length is known to be a multiple of 32 or
// - we will pad to full 32 bytes later anyway.
if (!_sourceType.isByteArray() || _padToWordBoundaries)
if (!_sourceType.isByteArrayOrString() || _padToWordBoundaries)
utils.memoryCopy32();
else
utils.memoryCopy();
@ -390,7 +390,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
m_context << Instruction::SWAP1 << Instruction::POP;
// stack: <target> <size>
bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArray();
bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArrayOrString();
if (paddingNeeded)
{
@ -446,7 +446,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
m_context << Instruction::DUP1 << Instruction::ISZERO;
evmasm::AssemblyItem loopEnd = m_context.appendConditionalJump();
// Special case for tightly-stored byte arrays
if (_sourceType.isByteArray())
if (_sourceType.isByteArrayOrString())
{
// stack here: memory_offset storage_offset length
m_context << Instruction::DUP1 << u256(31) << Instruction::LT;
@ -482,14 +482,14 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
}
// stack here: memory_end_offset storage_data_offset memory_offset
bool haveByteOffset = !_sourceType.isByteArray() && storageBytes <= 16;
bool haveByteOffset = !_sourceType.isByteArrayOrString() && storageBytes <= 16;
if (haveByteOffset)
m_context << u256(0) << Instruction::SWAP1;
// stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset
evmasm::AssemblyItem loopStart = m_context.newTag();
m_context << loopStart;
// load and store
if (_sourceType.isByteArray())
if (_sourceType.isByteArrayOrString())
{
// Packed both in storage and memory.
m_context << Instruction::DUP2 << Instruction::SLOAD;
@ -528,12 +528,12 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
// stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset
if (haveByteOffset)
m_context << Instruction::SWAP1 << Instruction::POP;
if (!_sourceType.isByteArray())
if (!_sourceType.isByteArrayOrString())
{
solAssert(_sourceType.calldataStride() % 32 == 0, "");
solAssert(_sourceType.memoryStride() % 32 == 0, "");
}
if (_padToWordBoundaries && _sourceType.isByteArray())
if (_padToWordBoundaries && _sourceType.isByteArrayOrString())
{
// memory_end_offset - start is the actual length (we want to compute the ceil of).
// memory_offset - start is its next multiple of 32, but it might be off by 32.
@ -624,7 +624,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
m_context << u256(0) << Instruction::DUP3 << Instruction::SSTORE;
// Special case: short byte arrays are stored togeher with their length
evmasm::AssemblyItem endTag = m_context.newTag();
if (_type.isByteArray())
if (_type.isByteArrayOrString())
{
// stack: ref old_length
m_context << Instruction::DUP1 << u256(31) << Instruction::LT;
@ -664,7 +664,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
ArrayType const& _type = dynamic_cast<ArrayType const&>(*type);
solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), "");
if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32)
if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32)
solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type.");
unsigned stackHeightStart = _context.stackHeight();
@ -677,7 +677,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "2");
// Special case for short byte arrays, they are stored together with their length
if (_type.isByteArray())
if (_type.isByteArrayOrString())
{
evmasm::AssemblyItem regularPath = _context.newTag();
// We start by a large case-distinction about the old and new length of the byte array.
@ -766,7 +766,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
// stack: ref new_length old_length
// store new length
_context << Instruction::DUP2;
if (_type.isByteArray())
if (_type.isByteArrayOrString())
// For a "long" byte array, store length as 2*length+1
_context << Instruction::DUP1 << Instruction::ADD << u256(1) << Instruction::ADD;
_context << Instruction::DUP4 << Instruction::SSTORE;
@ -806,10 +806,10 @@ void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const
{
solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), "");
if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32)
if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32)
solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type.");
if (_type.isByteArray())
if (_type.isByteArrayOrString())
{
// We almost always just add 2 (length of byte arrays is shifted left by one)
// except for the case where we transition from a short byte array
@ -850,10 +850,10 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
{
solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), "");
if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32)
if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32)
solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type.");
if (_type.isByteArray())
if (_type.isByteArrayOrString())
{
m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1;
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
@ -999,7 +999,7 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con
}
else
{
if (!_arrayType.isByteArray())
if (!_arrayType.isByteArrayOrString())
{
if (_arrayType.location() == DataLocation::Memory)
m_context << _arrayType.memoryStride();
@ -1031,7 +1031,7 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType, unsigned _stackDept
break;
case DataLocation::Storage:
m_context << Instruction::SLOAD;
if (_arrayType.isByteArray())
if (_arrayType.isByteArrayOrString())
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
break;
}
@ -1062,7 +1062,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
{
case DataLocation::Memory:
// stack: <base_ref> <index>
if (!_arrayType.isByteArray())
if (!_arrayType.isByteArrayOrString())
m_context << u256(_arrayType.memoryHeadSize()) << Instruction::MUL;
if (_arrayType.isDynamicallySized())
m_context << u256(32) << Instruction::ADD;
@ -1071,7 +1071,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
m_context << Instruction::ADD;
break;
case DataLocation::CallData:
if (!_arrayType.isByteArray())
if (!_arrayType.isByteArrayOrString())
{
m_context << _arrayType.calldataStride();
m_context << Instruction::MUL;
@ -1090,7 +1090,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
// stack: [<base_ref>] <index> <base_ref>
evmasm::AssemblyItem endTag = m_context.newTag();
if (_arrayType.isByteArray())
if (_arrayType.isByteArrayOrString())
{
// Special case of short byte arrays.
m_context << Instruction::SWAP1;
@ -1153,7 +1153,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d
{
solAssert(_arrayType.baseType()->storageBytes() <= 32, "");
if (
!_arrayType.isByteArray() &&
!_arrayType.isByteArrayOrString() &&
_arrayType.baseType()->storageBytes() < 32 &&
m_context.useABICoderV2()
)
@ -1165,7 +1165,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d
CompilerUtils(m_context).loadFromMemoryDynamic(
*_arrayType.baseType(),
true,
!_arrayType.isByteArray(),
!_arrayType.isByteArrayOrString(),
false
);
}

View File

@ -970,7 +970,7 @@ void CompilerUtils::convertType(
else if (targetTypeCategory == Type::Category::Array)
{
auto const& arrayType = dynamic_cast<ArrayType const&>(_targetType);
solAssert(arrayType.isByteArray());
solAssert(arrayType.isByteArrayOrString());
size_t storageSize = 32 + ((data.size() + 31) / 32) * 32;
allocateMemory(storageSize);
// stack: mempos
@ -992,7 +992,7 @@ void CompilerUtils::convertType(
if (_targetType.category() == Type::Category::FixedBytes)
{
solAssert(
typeOnStack.isByteArray() && !typeOnStack.isString(),
typeOnStack.isByteArrayOrString() && !typeOnStack.isString(),
"Array types other than bytes not convertible to bytesNN."
);
solAssert(typeOnStack.isDynamicallySized());
@ -1019,7 +1019,7 @@ void CompilerUtils::convertType(
case DataLocation::Storage:
// Other cases are done explicitly in LValue::storeValue, and only possible by assignment.
solAssert(
(targetType.isPointer() || (typeOnStack.isByteArray() && targetType.isByteArray())) &&
(targetType.isPointer() || (typeOnStack.isByteArrayOrString() && targetType.isByteArrayOrString())) &&
typeOnStack.location() == DataLocation::Storage,
"Invalid conversion to storage type."
);
@ -1105,7 +1105,7 @@ void CompilerUtils::convertType(
}
case DataLocation::CallData:
solAssert(
((targetType.isByteArray() && typeOnStack.isByteArray()) || _typeOnStack == _targetType) &&
((targetType.isByteArrayOrString() && typeOnStack.isByteArrayOrString()) || _typeOnStack == _targetType) &&
typeOnStack.location() == DataLocation::CallData,
"Invalid conversion to calldata type."
);
@ -1119,7 +1119,7 @@ void CompilerUtils::convertType(
if (_targetType.category() == Type::Category::FixedBytes)
{
solAssert(
typeOnStack.arrayType().isByteArray() && !typeOnStack.arrayType().isString(),
typeOnStack.arrayType().isByteArrayOrString() && !typeOnStack.arrayType().isString(),
"Array types other than bytes not convertible to bytesNN."
);
solAssert(typeOnStack.isDynamicallySized());
@ -1142,7 +1142,7 @@ void CompilerUtils::convertType(
auto const& targetArrayType = dynamic_cast<ArrayType const&>(_targetType);
solAssert(
typeOnStack.arrayType().isImplicitlyConvertibleTo(targetArrayType) ||
(typeOnStack.arrayType().isByteArray() && targetArrayType.isByteArray())
(typeOnStack.arrayType().isByteArrayOrString() && targetArrayType.isByteArrayOrString())
);
solAssert(
typeOnStack.arrayType().dataStoredIn(DataLocation::CallData) &&

View File

@ -153,7 +153,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (paramTypes[i]->isDynamicallySized())
{
solAssert(
dynamic_cast<ArrayType const&>(*paramTypes[i]).isByteArray(),
dynamic_cast<ArrayType const&>(*paramTypes[i]).isByteArrayOrString(),
"Expected string or byte array for mapping key type"
);
@ -239,7 +239,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (returnTypes[i]->category() == Type::Category::Mapping)
continue;
if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]))
if (!arrayType->isByteArray())
if (!arrayType->isByteArrayOrString())
continue;
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second);
@ -1047,7 +1047,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// stack: ArrayReference (newLength-1)
ArrayUtils(m_context).accessIndex(*arrayType, false);
if (arrayType->isByteArray())
if (arrayType->isByteArrayOrString())
setLValue<StorageByteArrayElement>(_functionCall);
else
setLValueToStorageItem(_functionCall);
@ -1084,7 +1084,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
utils().moveToStackTop(1 + type->sizeOnStack());
utils().moveToStackTop(1 + type->sizeOnStack());
// stack: argValue storageSlot slotOffset
if (!arrayType->isByteArray())
if (!arrayType->isByteArrayOrString())
StorageItem(m_context, *paramType).storeValue(*type, _functionCall.location(), true);
else
StorageByteArrayElement(m_context).storeValue(*type, _functionCall.location(), true);
@ -1165,7 +1165,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// update free memory pointer
m_context << Instruction::DUP1;
// Stack: memptr requested_length requested_length
if (arrayType.isByteArray())
if (arrayType.isByteArrayOrString())
// Round up to multiple of 32
m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND;
else
@ -2086,7 +2086,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
{
case DataLocation::Storage:
ArrayUtils(m_context).accessIndex(arrayType);
if (arrayType.isByteArray())
if (arrayType.isByteArrayOrString())
{
solAssert(!arrayType.isString(), "Index access to string is not allowed.");
setLValue<StorageByteArrayElement>(_indexAccess);
@ -2096,7 +2096,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
break;
case DataLocation::Memory:
ArrayUtils(m_context).accessIndex(arrayType);
setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArray());
setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArrayOrString());
break;
case DataLocation::CallData:
ArrayUtils(m_context).accessCallDataArrayElement(arrayType);

View File

@ -1183,8 +1183,8 @@ string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type)
w("calldata", _type.location() == DataLocation::CallData);
if (_type.location() == DataLocation::Storage)
{
w("byteArray", _type.isByteArray());
if (_type.isByteArray())
w("byteArray", _type.isByteArrayOrString());
if (_type.isByteArrayOrString())
w("extractByteArrayLength", extractByteArrayLengthFunction());
}
@ -1220,7 +1220,7 @@ std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type)
solAssert(_type.location() == DataLocation::Storage, "");
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32);
if (_type.isByteArray())
if (_type.isByteArrayOrString())
return resizeDynamicByteArrayFunction(_type);
string functionName = "resize_array_" + _type.identifier();
@ -1259,7 +1259,7 @@ string YulUtilFunctions::cleanUpStorageArrayEndFunction(ArrayType const& _type)
{
solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.baseType()->category() != Type::Category::Mapping, "");
solAssert(!_type.isByteArray(), "");
solAssert(!_type.isByteArrayOrString(), "");
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32);
string functionName = "cleanup_storage_array_end_" + _type.identifier();
@ -1319,7 +1319,7 @@ string YulUtilFunctions::resizeDynamicByteArrayFunction(ArrayType const& _type)
string YulUtilFunctions::cleanUpDynamicByteArrayEndSlotsFunction(ArrayType const& _type)
{
solAssert(_type.isByteArray(), "");
solAssert(_type.isByteArrayOrString(), "");
solAssert(_type.isDynamicallySized(), "");
string functionName = "clean_up_bytearray_end_slots_" + _type.identifier();
@ -1479,7 +1479,7 @@ string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type)
solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), "");
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
if (_type.isByteArray())
if (_type.isByteArrayOrString())
return storageByteArrayPopFunction(_type);
string functionName = "array_pop_" + _type.identifier();
@ -1509,7 +1509,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type)
{
solAssert(_type.location() == DataLocation::Storage, "");
solAssert(_type.isDynamicallySized(), "");
solAssert(_type.isByteArray(), "");
solAssert(_type.isByteArrayOrString(), "");
string functionName = "byte_array_pop_" + _type.identifier();
return m_functionCollector.createFunction(functionName, [&]() {
@ -1566,7 +1566,7 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(array <values>) {
<?isByteArray>
<?isByteArrayOrString>
let data := sload(array)
let oldLen := <extractByteArrayLength>(data)
if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() }
@ -1598,20 +1598,20 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c
let slot, offset := <indexAccess>(array, oldLen)
<storeValue>(slot, offset <values>)
}
<!isByteArray>
<!isByteArrayOrString>
let oldLen := sload(array)
if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() }
sstore(array, add(oldLen, 1))
let slot, offset := <indexAccess>(array, oldLen)
<storeValue>(slot, offset <values>)
</isByteArray>
</isByteArrayOrString>
})")
("functionName", functionName)
("values", _fromType->sizeOnStack() == 0 ? "" : ", " + suffixedVariableNameList("value", 0, _fromType->sizeOnStack()))
("panic", panicFunction(PanicCode::ResourceError))
("extractByteArrayLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "")
("extractByteArrayLength", _type.isByteArrayOrString() ? extractByteArrayLengthFunction() : "")
("dataAreaFunction", arrayDataAreaFunction(_type))
("isByteArray", _type.isByteArray())
("isByteArrayOrString", _type.isByteArrayOrString())
("indexAccess", storageArrayIndexAccessFunction(_type))
("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType()))
("maxArrayLength", (u256(1) << 64).str())
@ -1642,9 +1642,9 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type)
slot, offset := <indexAccess>(array, oldLen)
})")
("functionName", functionName)
("isBytes", _type.isByteArray())
("increaseBytesSize", _type.isByteArray() ? increaseByteArraySizeFunction(_type) : "")
("extractLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "")
("isBytes", _type.isByteArrayOrString())
("increaseBytesSize", _type.isByteArrayOrString() ? increaseByteArraySizeFunction(_type) : "")
("extractLength", _type.isByteArrayOrString() ? extractByteArrayLengthFunction() : "")
("panic", panicFunction(PanicCode::ResourceError))
("fetchLength", arrayLengthFunction(_type))
("indexAccess", storageArrayIndexAccessFunction(_type))
@ -1795,7 +1795,7 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType,
if (!_toType.isDynamicallySized())
solAssert(!_fromType.isDynamicallySized() && _fromType.length() <= _toType.length(), "");
if (_fromType.isByteArray())
if (_fromType.isByteArrayOrString())
return copyByteArrayToStorageFunction(_fromType, _toType);
if (_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType())
return copyValueArrayStorageToStorageFunction(_fromType, _toType);
@ -1902,8 +1902,8 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy
*_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast<ReferenceType const&>(_toType),
""
);
solAssert(_fromType.isByteArray(), "");
solAssert(_toType.isByteArray(), "");
solAssert(_fromType.isByteArrayOrString(), "");
solAssert(_toType.isByteArrayOrString(), "");
string functionName = "copy_byte_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier();
return m_functionCollector.createFunction(functionName, [&](){
@ -1980,8 +1980,8 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const&
solAssert(_toType.baseType()->isValueType(), "");
solAssert(_fromType.baseType()->isImplicitlyConvertibleTo(*_toType.baseType()), "");
solAssert(!_fromType.isByteArray(), "");
solAssert(!_toType.isByteArray(), "");
solAssert(!_fromType.isByteArrayOrString(), "");
solAssert(!_toType.isByteArrayOrString(), "");
solAssert(_fromType.dataStoredIn(DataLocation::Storage), "");
solAssert(_toType.dataStoredIn(DataLocation::Storage), "");
@ -2155,7 +2155,7 @@ string YulUtilFunctions::arrayConvertLengthToSize(ArrayType const& _type)
})")
("functionName", functionName)
("stride", to_string(_type.location() == DataLocation::Memory ? _type.memoryStride() : _type.calldataStride()))
("byteArray", _type.isByteArray())
("byteArray", _type.isByteArrayOrString())
("mul", overflowCheckedIntMulFunction(*TypeProvider::uint256()))
.render();
default:
@ -2187,7 +2187,7 @@ string YulUtilFunctions::arrayAllocationSizeFunction(ArrayType const& _type)
)");
w("functionName", functionName);
w("panic", panicFunction(PanicCode::ResourceError));
w("byteArray", _type.isByteArray());
w("byteArray", _type.isByteArrayOrString());
w("roundUp", roundUpFunction());
w("dynamic", _type.isDynamicallySized());
return w.render();
@ -2262,7 +2262,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type)
("dataAreaFunc", arrayDataAreaFunction(_type))
("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction())
("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16)
("isBytesArray", _type.isByteArray())
("isBytesArray", _type.isByteArrayOrString())
("storageSize", _type.baseType()->storageSize().str())
("storageBytes", toString(_type.baseType()->storageBytes()))
("itemsPerSlot", to_string(32 / _type.baseType()->storageBytes()))
@ -2376,7 +2376,7 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type)
string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type)
{
solAssert(!_type.isByteArray(), "");
solAssert(!_type.isByteArrayOrString(), "");
if (_type.dataStoredIn(DataLocation::Storage))
solAssert(_type.baseType()->storageBytes() > 16, "");
string functionName = "array_nextElement_" + _type.identifier();
@ -2447,7 +2447,7 @@ string YulUtilFunctions::copyArrayFromStorageToMemoryFunction(ArrayType const& _
solAssert(_to.memoryStride() == 32, "");
solAssert(_to.baseType()->dataStoredIn(DataLocation::Memory), "");
solAssert(_from.baseType()->dataStoredIn(DataLocation::Storage), "");
solAssert(!_from.isByteArray(), "");
solAssert(!_from.isByteArrayOrString(), "");
solAssert(*_to.withLocation(DataLocation::Storage, _from.isPointer()) == _from, "");
return Whiskers(R"(
function <functionName>(slot) -> memPtr {
@ -2755,7 +2755,7 @@ string YulUtilFunctions::updateStorageValueFunction(
solAssert(_fromType.category() == Type::Category::StringLiteral, "");
solAssert(toReferenceType->category() == Type::Category::Array, "");
auto const& toArrayType = dynamic_cast<ArrayType const&>(*toReferenceType);
solAssert(toArrayType.isByteArray(), "");
solAssert(toArrayType.isByteArrayOrString(), "");
return Whiskers(R"(
function <functionName>(slot<?dynamicOffset>, offset</dynamicOffset>) {
@ -3216,7 +3216,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
auto const& fromType = dynamic_cast<ArraySliceType const&>(_from);
if (_to.category() == Type::Category::FixedBytes)
{
solAssert(fromType.arrayType().isByteArray(), "Array types other than bytes not convertible to bytesNN.");
solAssert(fromType.arrayType().isByteArrayOrString(), "Array types other than bytes not convertible to bytesNN.");
return bytesToFixedBytesConversionFunction(fromType.arrayType(), dynamic_cast<FixedBytesType const &>(_to));
}
solAssert(_to.category() == Type::Category::Array);
@ -3224,7 +3224,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
solAssert(
fromType.arrayType().isImplicitlyConvertibleTo(targetType) ||
(fromType.arrayType().isByteArray() && targetType.isByteArray())
(fromType.arrayType().isByteArrayOrString() && targetType.isByteArrayOrString())
);
solAssert(
fromType.arrayType().dataStoredIn(DataLocation::CallData) &&
@ -3256,7 +3256,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
auto const& fromArrayType = dynamic_cast<ArrayType const&>(_from);
if (_to.category() == Type::Category::FixedBytes)
{
solAssert(fromArrayType.isByteArray(), "Array types other than bytes not convertible to bytesNN.");
solAssert(fromArrayType.isByteArrayOrString(), "Array types other than bytes not convertible to bytesNN.");
return bytesToFixedBytesConversionFunction(fromArrayType, dynamic_cast<FixedBytesType const &>(_to));
}
solAssert(_to.category() == Type::Category::Array, "");
@ -3460,7 +3460,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
string YulUtilFunctions::bytesToFixedBytesConversionFunction(ArrayType const& _from, FixedBytesType const& _to)
{
solAssert(_from.isByteArray() && !_from.isString(), "");
solAssert(_from.isByteArrayOrString() && !_from.isString(), "");
solAssert(_from.isDynamicallySized(), "");
string functionName = "convert_bytes_to_fixedbytes_from_" + _from.identifier() + "_to_" + _to.identifier();
return m_functionCollector.createFunction(functionName, [&](auto& _args, auto& _returnParams) {
@ -3633,14 +3633,14 @@ string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayTy
{
if (_to.dataStoredIn(DataLocation::CallData))
solAssert(
_from.dataStoredIn(DataLocation::CallData) && _from.isByteArray() && _to.isByteArray(),
_from.dataStoredIn(DataLocation::CallData) && _from.isByteArrayOrString() && _to.isByteArrayOrString(),
""
);
// Other cases are done explicitly in LValue::storeValue, and only possible by assignment.
if (_to.location() == DataLocation::Storage)
solAssert(
(_to.isPointer() || (_from.isByteArray() && _to.isByteArray())) &&
(_to.isPointer() || (_from.isByteArrayOrString() && _to.isByteArrayOrString())) &&
_from.location() == DataLocation::Storage,
"Invalid conversion to storage type."
);
@ -4238,7 +4238,7 @@ string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const
}
else if (_to.category() == Type::Category::Array)
{
solAssert(dynamic_cast<ArrayType const&>(_to).isByteArray(), "");
solAssert(dynamic_cast<ArrayType const&>(_to).isByteArrayOrString(), "");
Whiskers templ(R"(
function <functionName>() -> converted {
converted := <copyLiteralToMemory>()

View File

@ -677,7 +677,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
continue;
if (
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]);
arrayType && !arrayType->isByteArray()
arrayType && !arrayType->isByteArrayOrString()
)
continue;
@ -698,7 +698,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
solAssert(returnTypes.size() == 1, "");
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front());
if (arrayType)
solAssert(arrayType->isByteArray(), "");
solAssert(arrayType->isByteArrayOrString(), "");
vector<string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
returnVariables += retVars;
code += Whiskers(R"(

View File

@ -2088,7 +2088,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
else if (dynamic_cast<UserDefinedValueType const*>(&actualType))
solAssert(member == "wrap" || member == "unwrap");
else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType))
solAssert(arrayType->isByteArray() && member == "concat");
solAssert(arrayType->isByteArrayOrString() && member == "concat");
else
// The old code generator had a generic "else" case here
// without any specific code being generated,
@ -2226,7 +2226,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
setLValue(_indexAccess, IRLValue{
*arrayType.baseType(),
IRLValue::Memory{memAddress, arrayType.isByteArray()}
IRLValue::Memory{memAddress, arrayType.isByteArrayOrString()}
});
break;
}
@ -2240,7 +2240,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
", " +
expressionAsType(*_indexAccess.indexExpression(), *TypeProvider::uint256()) +
")";
if (arrayType.isByteArray())
if (arrayType.isByteArrayOrString())
define(_indexAccess) <<
m_utils.cleanupFunction(*arrayType.baseType()) <<
"(calldataload(" <<

View File

@ -953,7 +953,7 @@ bool isReturnedFromStructGetter(Type const* _type)
if (category == Type::Category::Mapping)
return false;
if (category == Type::Category::Array)
return dynamic_cast<ArrayType const&>(*_type).isByteArray();
return dynamic_cast<ArrayType const&>(*_type).isByteArrayOrString();
// default
return true;
}
@ -990,7 +990,7 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
{
if (
type->isValueType() ||
(type->category() == Type::Category::Array && dynamic_cast<ArrayType const&>(*type).isByteArray())
(type->category() == Type::Category::Array && dynamic_cast<ArrayType const&>(*type).isByteArrayOrString())
)
{
solAssert(symbArguments.empty(), "");
@ -1071,7 +1071,7 @@ void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
if (auto sliceType = dynamic_cast<ArraySliceType const*>(argType))
arrayType = &sliceType->arrayType();
if (arrayType && arrayType->isByteArray() && smt::isFixedBytes(*funCallType))
if (arrayType && arrayType->isByteArrayOrString() && smt::isFixedBytes(*funCallType))
{
auto array = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(*argument));
bytesToFixedBytesAssertions(*array, _funCall);
@ -2695,14 +2695,14 @@ Expression const* SMTEncoder::cleanExpression(Expression const& _expr)
auto typeType = dynamic_cast<TypeType const*>(functionCall->expression().annotation().type);
solAssert(typeType, "");
if (auto const* arrayType = dynamic_cast<ArrayType const*>(typeType->actualType()))
if (arrayType->isByteArray())
if (arrayType->isByteArrayOrString())
{
// this is a cast to `bytes`
solAssert(functionCall->arguments().size() == 1, "");
Expression const& arg = *functionCall->arguments()[0];
if (
auto const* argArrayType = dynamic_cast<ArrayType const*>(arg.annotation().type);
argArrayType && argArrayType->isByteArray()
argArrayType && argArrayType->isByteArrayOrString()
)
return cleanExpression(arg);
}

View File

@ -96,7 +96,7 @@ SortPointer smtSort(frontend::Type const& _type)
auto sliceArrayType = dynamic_cast<ArraySliceType const*>(&_type);
ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast<ArrayType const*>(&_type);
if (
(arrayType && (arrayType->isString() || arrayType->isByteArray())) ||
(arrayType && (arrayType->isString() || arrayType->isByteArrayOrString())) ||
_type.category() == frontend::Type::Category::StringLiteral
)
tupleName = "bytes";

View File

@ -176,7 +176,7 @@ Json::Value ABI::formatType(
ret["type"] = _encodingType.canonicalName() + suffix;
else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_encodingType))
{
if (arrayType->isByteArray())
if (arrayType->isByteArrayOrString())
ret["type"] = _encodingType.canonicalName() + suffix;
else
{

View File

@ -94,7 +94,7 @@ void StorageLayout::generate(Type const* _type)
}
else if (auto arrayType = dynamic_cast<ArrayType const*>(_type))
{
if (arrayType->isByteArray())
if (arrayType->isByteArrayOrString())
typeInfo["encoding"] = "bytes";
else
{