1 /*
2 	This file is part of solidity.
3 
4 	solidity is free software: you can redistribute it and/or modify
5 	it under the terms of the GNU General Public License as published by
6 	the Free Software Foundation, either version 3 of the License, or
7 	(at your option) any later version.
8 
9 	solidity is distributed in the hope that it will be useful,
10 	but WITHOUT ANY WARRANTY; without even the implied warranty of
11 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 	GNU General Public License for more details.
13 
14 	You should have received a copy of the GNU General Public License
15 	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 // SPDX-License-Identifier: GPL-3.0
18 /**
19  * @author Christian <c@ethdev.com>
20  * @date 2014
21  * Solidity data types
22  */
23 
24 #include <libsolidity/ast/Types.h>
25 
26 #include <libsolidity/ast/AST.h>
27 #include <libsolidity/ast/TypeProvider.h>
28 
29 #include <libsolidity/analysis/ConstantEvaluator.h>
30 
31 #include <libsolutil/Algorithms.h>
32 #include <libsolutil/CommonData.h>
33 #include <libsolutil/CommonIO.h>
34 #include <libsolutil/FunctionSelector.h>
35 #include <libsolutil/Keccak256.h>
36 #include <libsolutil/UTF8.h>
37 
38 #include <boost/algorithm/string.hpp>
39 #include <boost/algorithm/string/classification.hpp>
40 #include <boost/algorithm/string/join.hpp>
41 #include <boost/algorithm/string/predicate.hpp>
42 #include <boost/algorithm/string/replace.hpp>
43 #include <boost/algorithm/string/split.hpp>
44 
45 #include <range/v3/view/enumerate.hpp>
46 #include <range/v3/view/reverse.hpp>
47 #include <range/v3/view/tail.hpp>
48 #include <range/v3/view/transform.hpp>
49 
50 #include <limits>
51 #include <unordered_set>
52 #include <utility>
53 
54 using namespace std;
55 using namespace solidity;
56 using namespace solidity::langutil;
57 using namespace solidity::frontend;
58 
59 namespace
60 {
61 
62 /// Checks whether _mantissa * (10 ** _expBase10) fits into 4096 bits.
fitsPrecisionBase10(bigint const & _mantissa,uint32_t _expBase10)63 bool fitsPrecisionBase10(bigint const& _mantissa, uint32_t _expBase10)
64 {
65 	double const log2Of10AwayFromZero = 3.3219280948873624;
66 	return fitsPrecisionBaseX(_mantissa, log2Of10AwayFromZero, _expBase10);
67 }
68 
69 /// Checks whether _value fits into IntegerType _type.
fitsIntegerType(bigint const & _value,IntegerType const & _type)70 BoolResult fitsIntegerType(bigint const& _value, IntegerType const& _type)
71 {
72 	if (_value < 0 && !_type.isSigned())
73 		return BoolResult::err("Cannot implicitly convert signed literal to unsigned type.");
74 
75 	if (_type.minValue() > _value || _value > _type.maxValue())
76 		return BoolResult::err("Literal is too large to fit in " + _type.toString(false) + ".");
77 
78 	return true;
79 }
80 
81 /// Checks whether _value fits into _bits bits when having 1 bit as the sign bit
82 /// if _signed is true.
fitsIntoBits(bigint const & _value,unsigned _bits,bool _signed)83 bool fitsIntoBits(bigint const& _value, unsigned _bits, bool _signed)
84 {
85 	return fitsIntegerType(
86 		_value,
87 		*TypeProvider::integer(
88 			_bits,
89 			_signed ? IntegerType::Modifier::Signed : IntegerType::Modifier::Unsigned
90 		)
91 	);
92 }
93 
transformParametersToExternal(TypePointers const & _parameters,bool _inLibrary)94 util::Result<TypePointers> transformParametersToExternal(TypePointers const& _parameters, bool _inLibrary)
95 {
96 	TypePointers transformed;
97 
98 	for (auto const& type: _parameters)
99 	{
100 		if (!type)
101 			return util::Result<TypePointers>::err("Type information not present.");
102 		else if (Type const* ext = type->interfaceType(_inLibrary).get())
103 			transformed.push_back(ext);
104 		else
105 			return util::Result<TypePointers>::err("Parameter should have external type.");
106 	}
107 
108 	return transformed;
109 }
110 
111 }
112 
Member(Declaration const * _declaration,Type const * _type)113 MemberList::Member::Member(Declaration const* _declaration, Type const* _type):
114 	Member(_declaration, _type, _declaration->name())
115 {}
116 
Member(Declaration const * _declaration,Type const * _type,string _name)117 MemberList::Member::Member(Declaration const* _declaration, Type const* _type, string _name):
118 	name(move(_name)),
119 	type(_type),
120 	declaration(_declaration)
121 {
122 }
123 
clearCache() const124 void Type::clearCache() const
125 {
126 	m_members.clear();
127 	m_stackItems.reset();
128 	m_stackSize.reset();
129 }
130 
computeOffsets(TypePointers const & _types)131 void StorageOffsets::computeOffsets(TypePointers const& _types)
132 {
133 	bigint slotOffset = 0;
134 	unsigned byteOffset = 0;
135 	map<size_t, pair<u256, unsigned>> offsets;
136 	for (size_t i = 0; i < _types.size(); ++i)
137 	{
138 		Type const* type = _types[i];
139 		if (!type->canBeStored())
140 			continue;
141 		if (byteOffset + type->storageBytes() > 32)
142 		{
143 			// would overflow, go to next slot
144 			++slotOffset;
145 			byteOffset = 0;
146 		}
147 		solAssert(slotOffset < bigint(1) << 256 ,"Object too large for storage.");
148 		offsets[i] = make_pair(u256(slotOffset), byteOffset);
149 		solAssert(type->storageSize() >= 1, "Invalid storage size.");
150 		if (type->storageSize() == 1 && byteOffset + type->storageBytes() <= 32)
151 			byteOffset += type->storageBytes();
152 		else
153 		{
154 			slotOffset += type->storageSize();
155 			byteOffset = 0;
156 		}
157 	}
158 	if (byteOffset > 0)
159 		++slotOffset;
160 	solAssert(slotOffset < bigint(1) << 256, "Object too large for storage.");
161 	m_storageSize = u256(slotOffset);
162 	swap(m_offsets, offsets);
163 }
164 
offset(size_t _index) const165 pair<u256, unsigned> const* StorageOffsets::offset(size_t _index) const
166 {
167 	if (m_offsets.count(_index))
168 		return &m_offsets.at(_index);
169 	else
170 		return nullptr;
171 }
172 
combine(MemberList const & _other)173 void MemberList::combine(MemberList const & _other)
174 {
175 	m_memberTypes += _other.m_memberTypes;
176 }
177 
memberStorageOffset(string const & _name) const178 pair<u256, unsigned> const* MemberList::memberStorageOffset(string const& _name) const
179 {
180 	StorageOffsets const& offsets = storageOffsets();
181 
182 	for (auto&& [index, member]: m_memberTypes | ranges::views::enumerate)
183 		if (member.name == _name)
184 			return offsets.offset(index);
185 	return nullptr;
186 }
187 
storageSize() const188 u256 const& MemberList::storageSize() const
189 {
190 	return storageOffsets().storageSize();
191 }
192 
storageOffsets() const193 StorageOffsets const& MemberList::storageOffsets() const {
194 	return m_storageOffsets.init([&]{
195 		TypePointers memberTypes;
196 		memberTypes.reserve(m_memberTypes.size());
197 		for (auto const& member: m_memberTypes)
198 			memberTypes.push_back(member.type);
199 
200 		StorageOffsets storageOffsets;
201 		storageOffsets.computeOffsets(memberTypes);
202 
203 		return storageOffsets;
204 	});
205 }
206 
207 /// Helper functions for type identifier
208 namespace
209 {
210 
parenthesizeIdentifier(string const & _internal)211 string parenthesizeIdentifier(string const& _internal)
212 {
213 	return "(" + _internal + ")";
214 }
215 
216 template <class Range>
identifierList(Range const && _list)217 string identifierList(Range const&& _list)
218 {
219 	return parenthesizeIdentifier(boost::algorithm::join(_list, ","));
220 }
221 
richIdentifier(Type const * _type)222 string richIdentifier(Type const* _type)
223 {
224 	return _type ? _type->richIdentifier() : "";
225 }
226 
identifierList(vector<Type const * > const & _list)227 string identifierList(vector<Type const*> const& _list)
228 {
229 	return identifierList(_list | ranges::views::transform(richIdentifier));
230 }
231 
identifierList(Type const * _type)232 string identifierList(Type const* _type)
233 {
234 	return parenthesizeIdentifier(richIdentifier(_type));
235 }
236 
identifierList(Type const * _type1,Type const * _type2)237 string identifierList(Type const* _type1, Type const* _type2)
238 {
239 	TypePointers list;
240 	list.push_back(_type1);
241 	list.push_back(_type2);
242 	return identifierList(list);
243 }
244 
parenthesizeUserIdentifier(string const & _internal)245 string parenthesizeUserIdentifier(string const& _internal)
246 {
247 	return parenthesizeIdentifier(_internal);
248 }
249 
250 }
251 
escapeIdentifier(string const & _identifier)252 string Type::escapeIdentifier(string const& _identifier)
253 {
254 	string ret = _identifier;
255 	// FIXME: should be _$$$_
256 	boost::algorithm::replace_all(ret, "$", "$$$");
257 	boost::algorithm::replace_all(ret, ",", "_$_");
258 	boost::algorithm::replace_all(ret, "(", "$_");
259 	boost::algorithm::replace_all(ret, ")", "_$");
260 	return ret;
261 }
262 
identifier() const263 string Type::identifier() const
264 {
265 	string ret = escapeIdentifier(richIdentifier());
266 	solAssert(ret.find_first_of("0123456789") != 0, "Identifier cannot start with a number.");
267 	solAssert(
268 		ret.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMONPQRSTUVWXYZ_$") == string::npos,
269 		"Identifier contains invalid characters."
270 	);
271 	return ret;
272 }
273 
commonType(Type const * _a,Type const * _b)274 Type const* Type::commonType(Type const* _a, Type const* _b)
275 {
276 	if (!_a || !_b)
277 		return nullptr;
278 	else if (_a->mobileType() && _b->isImplicitlyConvertibleTo(*_a->mobileType()))
279 		return _a->mobileType();
280 	else if (_b->mobileType() && _a->isImplicitlyConvertibleTo(*_b->mobileType()))
281 		return _b->mobileType();
282 	else
283 		return nullptr;
284 }
285 
members(ASTNode const * _currentScope) const286 MemberList const& Type::members(ASTNode const* _currentScope) const
287 {
288 	if (!m_members[_currentScope])
289 	{
290 		solAssert(
291 			_currentScope == nullptr ||
292 			dynamic_cast<SourceUnit const*>(_currentScope) ||
293 			dynamic_cast<ContractDefinition const*>(_currentScope),
294 		"");
295 		MemberList::MemberMap members = nativeMembers(_currentScope);
296 		if (_currentScope)
297 			members += boundFunctions(*this, *_currentScope);
298 		m_members[_currentScope] = make_unique<MemberList>(move(members));
299 	}
300 	return *m_members[_currentScope];
301 }
302 
fullEncodingType(bool _inLibraryCall,bool _encoderV2,bool) const303 Type const* Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) const
304 {
305 	Type const* encodingType = mobileType();
306 	if (encodingType)
307 		encodingType = encodingType->interfaceType(_inLibraryCall);
308 	if (encodingType)
309 		encodingType = encodingType->encodingType();
310 	// Structs are fine in the following circumstances:
311 	// - ABIv2 or,
312 	// - storage struct for a library
313 	if (_inLibraryCall && encodingType && encodingType->dataStoredIn(DataLocation::Storage))
314 		return encodingType;
315 	Type const* baseType = encodingType;
316 	while (auto const* arrayType = dynamic_cast<ArrayType const*>(baseType))
317 	{
318 		baseType = arrayType->baseType();
319 
320 		auto const* baseArrayType = dynamic_cast<ArrayType const*>(baseType);
321 		if (!_encoderV2 && baseArrayType && baseArrayType->isDynamicallySized())
322 			return nullptr;
323 	}
324 	if (!_encoderV2 && dynamic_cast<StructType const*>(baseType))
325 		return nullptr;
326 
327 	return encodingType;
328 }
329 
boundFunctions(Type const & _type,ASTNode const & _scope)330 MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope)
331 {
332 	vector<UsingForDirective const*> usingForDirectives;
333 	if (auto const* sourceUnit = dynamic_cast<SourceUnit const*>(&_scope))
334 		usingForDirectives += ASTNode::filteredNodes<UsingForDirective>(sourceUnit->nodes());
335 	else if (auto const* contract = dynamic_cast<ContractDefinition const*>(&_scope))
336 		usingForDirectives +=
337 			contract->usingForDirectives() +
338 			ASTNode::filteredNodes<UsingForDirective>(contract->sourceUnit().nodes());
339 	else
340 		solAssert(false, "");
341 
342 	// Normalise data location of type.
343 	DataLocation typeLocation = DataLocation::Storage;
344 	if (auto refType = dynamic_cast<ReferenceType const*>(&_type))
345 		typeLocation = refType->location();
346 
347 	set<Declaration const*> seenFunctions;
348 	MemberList::MemberMap members;
349 
350 	for (UsingForDirective const* ufd: usingForDirectives)
351 	{
352 		// Convert both types to pointers for comparison to see if the `using for`
353 		// directive applies.
354 		// Further down, we check more detailed for each function if `_type` is
355 		// convertible to the function parameter type.
356 		if (ufd->typeName() &&
357 			*TypeProvider::withLocationIfReference(typeLocation, &_type, true) !=
358 			*TypeProvider::withLocationIfReference(
359 				typeLocation,
360 				ufd->typeName()->annotation().type,
361 				true
362 			)
363 		)
364 			continue;
365 		auto const& library = dynamic_cast<ContractDefinition const&>(
366 			*ufd->libraryName().annotation().referencedDeclaration
367 		);
368 		for (FunctionDefinition const* function: library.definedFunctions())
369 		{
370 			if (!function->isOrdinary() || !function->isVisibleAsLibraryMember() || seenFunctions.count(function))
371 				continue;
372 			seenFunctions.insert(function);
373 			if (function->parameters().empty())
374 				continue;
375 			FunctionTypePointer fun =
376 				dynamic_cast<FunctionType const&>(*function->typeViaContractName()).asBoundFunction();
377 			if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
378 				members.emplace_back(function, fun);
379 		}
380 	}
381 
382 	return members;
383 }
384 
AddressType(StateMutability _stateMutability)385 AddressType::AddressType(StateMutability _stateMutability):
386 	m_stateMutability(_stateMutability)
387 {
388 	solAssert(m_stateMutability == StateMutability::Payable || m_stateMutability == StateMutability::NonPayable, "");
389 }
390 
richIdentifier() const391 string AddressType::richIdentifier() const
392 {
393 	if (m_stateMutability == StateMutability::Payable)
394 		return "t_address_payable";
395 	else
396 		return "t_address";
397 }
398 
isImplicitlyConvertibleTo(Type const & _other) const399 BoolResult AddressType::isImplicitlyConvertibleTo(Type const& _other) const
400 {
401 	if (_other.category() != category())
402 		return false;
403 	AddressType const& other = dynamic_cast<AddressType const&>(_other);
404 
405 	return other.m_stateMutability <= m_stateMutability;
406 }
407 
isExplicitlyConvertibleTo(Type const & _convertTo) const408 BoolResult AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const
409 {
410 	if ((_convertTo.category() == category()) || isImplicitlyConvertibleTo(_convertTo))
411 		return true;
412 	else if (auto const* contractType = dynamic_cast<ContractType const*>(&_convertTo))
413 		return (m_stateMutability >= StateMutability::Payable) || !contractType->isPayable();
414 	else if (m_stateMutability == StateMutability::NonPayable)
415 	{
416 		if (auto integerType = dynamic_cast<IntegerType const*>(&_convertTo))
417 			return (!integerType->isSigned() && integerType->numBits() == 160);
418 		else if (auto fixedBytesType = dynamic_cast<FixedBytesType const*>(&_convertTo))
419 			return (fixedBytesType->numBytes() == 20);
420 	}
421 
422 	return false;
423 }
424 
toString(bool) const425 string AddressType::toString(bool) const
426 {
427 	if (m_stateMutability == StateMutability::Payable)
428 		return "address payable";
429 	else
430 		return "address";
431 }
432 
canonicalName() const433 string AddressType::canonicalName() const
434 {
435 	return "address";
436 }
437 
literalValue(Literal const * _literal) const438 u256 AddressType::literalValue(Literal const* _literal) const
439 {
440 	solAssert(_literal, "");
441 	solAssert(_literal->value().substr(0, 2) == "0x", "");
442 	return u256(_literal->valueWithoutUnderscores());
443 }
444 
unaryOperatorResult(Token _operator) const445 TypeResult AddressType::unaryOperatorResult(Token _operator) const
446 {
447 	return _operator == Token::Delete ? TypeProvider::emptyTuple() : nullptr;
448 }
449 
450 
binaryOperatorResult(Token _operator,Type const * _other) const451 TypeResult AddressType::binaryOperatorResult(Token _operator, Type const* _other) const
452 {
453 	if (!TokenTraits::isCompareOp(_operator))
454 		return TypeResult::err("Arithmetic operations on addresses are not supported. Convert to integer first before using them.");
455 
456 	return Type::commonType(this, _other);
457 }
458 
operator ==(Type const & _other) const459 bool AddressType::operator==(Type const& _other) const
460 {
461 	if (_other.category() != category())
462 		return false;
463 	AddressType const& other = dynamic_cast<AddressType const&>(_other);
464 	return other.m_stateMutability == m_stateMutability;
465 }
466 
nativeMembers(ASTNode const *) const467 MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const
468 {
469 	MemberList::MemberMap members = {
470 		{"balance", TypeProvider::uint256()},
471 		{"code", TypeProvider::array(DataLocation::Memory)},
472 		{"codehash",  TypeProvider::fixedBytes(32)},
473 		{"call", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)},
474 		{"callcode", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)},
475 		{"delegatecall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false, StateMutability::NonPayable)},
476 		{"staticcall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}
477 	};
478 	if (m_stateMutability == StateMutability::Payable)
479 	{
480 		members.emplace_back(MemberList::Member{"send", TypeProvider::function(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send, false, StateMutability::NonPayable)});
481 		members.emplace_back(MemberList::Member{"transfer", TypeProvider::function(strings{"uint"}, strings(), FunctionType::Kind::Transfer, false, StateMutability::NonPayable)});
482 	}
483 	return members;
484 }
485 
486 namespace
487 {
488 
isValidShiftAndAmountType(Token _operator,Type const & _shiftAmountType)489 bool isValidShiftAndAmountType(Token _operator, Type const& _shiftAmountType)
490 {
491 	// Disable >>> here.
492 	if (_operator == Token::SHR)
493 		return false;
494 	else if (IntegerType const* otherInt = dynamic_cast<decltype(otherInt)>(&_shiftAmountType))
495 		return !otherInt->isSigned();
496 	else if (RationalNumberType const* otherRat = dynamic_cast<decltype(otherRat)>(&_shiftAmountType))
497 		return !otherRat->isFractional() && otherRat->integerType() && !otherRat->integerType()->isSigned();
498 	else
499 		return false;
500 }
501 
502 }
503 
IntegerType(unsigned _bits,IntegerType::Modifier _modifier)504 IntegerType::IntegerType(unsigned _bits, IntegerType::Modifier _modifier):
505 	m_bits(_bits), m_modifier(_modifier)
506 {
507 	solAssert(
508 		m_bits > 0 && m_bits <= 256 && m_bits % 8 == 0,
509 		"Invalid bit number for integer type: " + util::toString(m_bits)
510 	);
511 }
512 
richIdentifier() const513 string IntegerType::richIdentifier() const
514 {
515 	return "t_" + string(isSigned() ? "" : "u") + "int" + to_string(numBits());
516 }
517 
isImplicitlyConvertibleTo(Type const & _convertTo) const518 BoolResult IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
519 {
520 	if (_convertTo.category() == category())
521 	{
522 		IntegerType const& convertTo = dynamic_cast<IntegerType const&>(_convertTo);
523 		// disallowing unsigned to signed conversion of different bits
524 		if (isSigned() != convertTo.isSigned())
525 			return false;
526 		else if (convertTo.m_bits < m_bits)
527 			return false;
528 		else
529 			return true;
530 	}
531 	else if (_convertTo.category() == Category::FixedPoint)
532 	{
533 		FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
534 		return maxValue() <= convertTo.maxIntegerValue() && minValue() >= convertTo.minIntegerValue();
535 	}
536 	else
537 		return false;
538 }
539 
isExplicitlyConvertibleTo(Type const & _convertTo) const540 BoolResult IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
541 {
542 	if (isImplicitlyConvertibleTo(_convertTo))
543 		return true;
544 	else if (auto integerType = dynamic_cast<IntegerType const*>(&_convertTo))
545 		return (numBits() == integerType->numBits()) || (isSigned() == integerType->isSigned());
546 	else if (auto addressType = dynamic_cast<AddressType const*>(&_convertTo))
547 		return
548 			(addressType->stateMutability() != StateMutability::Payable) &&
549 			!isSigned() &&
550 			(numBits() == 160);
551 	else if (auto fixedBytesType = dynamic_cast<FixedBytesType const*>(&_convertTo))
552 		return (!isSigned() && (numBits() == fixedBytesType->numBytes() * 8));
553 	else if (dynamic_cast<EnumType const*>(&_convertTo))
554 		return true;
555 	else if (auto fixedPointType = dynamic_cast<FixedPointType const*>(&_convertTo))
556 		return (isSigned() == fixedPointType->isSigned()) && (numBits() == fixedPointType->numBits());
557 
558 	return false;
559 }
560 
unaryOperatorResult(Token _operator) const561 TypeResult IntegerType::unaryOperatorResult(Token _operator) const
562 {
563 	// "delete" is ok for all integer types
564 	if (_operator == Token::Delete)
565 		return TypeResult{TypeProvider::emptyTuple()};
566 	// unary negation only on signed types
567 	else if (_operator == Token::Sub)
568 		return isSigned() ? TypeResult{this} : TypeResult::err("Unary negation is only allowed for signed integers.");
569 	else if (_operator == Token::Inc || _operator == Token::Dec || _operator == Token::BitNot)
570 		return TypeResult{this};
571 	else
572 		return TypeResult::err("");
573 }
574 
operator ==(Type const & _other) const575 bool IntegerType::operator==(Type const& _other) const
576 {
577 	if (_other.category() != category())
578 		return false;
579 	IntegerType const& other = dynamic_cast<IntegerType const&>(_other);
580 	return other.m_bits == m_bits && other.m_modifier == m_modifier;
581 }
582 
toString(bool) const583 string IntegerType::toString(bool) const
584 {
585 	string prefix = isSigned() ? "int" : "uint";
586 	return prefix + util::toString(m_bits);
587 }
588 
min() const589 u256 IntegerType::min() const
590 {
591 	if (isSigned())
592 		return s2u(s256(minValue()));
593 	else
594 		return u256(minValue());
595 }
596 
max() const597 u256 IntegerType::max() const
598 {
599 	if (isSigned())
600 		return s2u(s256(maxValue()));
601 	else
602 		return u256(maxValue());
603 }
604 
minValue() const605 bigint IntegerType::minValue() const
606 {
607 	if (isSigned())
608 		return -(bigint(1) << (m_bits - 1));
609 	else
610 		return bigint(0);
611 }
612 
maxValue() const613 bigint IntegerType::maxValue() const
614 {
615 	if (isSigned())
616 		return (bigint(1) << (m_bits - 1)) - 1;
617 	else
618 		return (bigint(1) << m_bits) - 1;
619 }
620 
binaryOperatorResult(Token _operator,Type const * _other) const621 TypeResult IntegerType::binaryOperatorResult(Token _operator, Type const* _other) const
622 {
623 	if (
624 		_other->category() != Category::RationalNumber &&
625 		_other->category() != Category::FixedPoint &&
626 		_other->category() != category()
627 	)
628 		return nullptr;
629 	if (TokenTraits::isShiftOp(_operator))
630 	{
631 		// Shifts are not symmetric with respect to the type
632 		if (isValidShiftAndAmountType(_operator, *_other))
633 			return this;
634 		else
635 			return nullptr;
636 	}
637 	else if (Token::Exp == _operator)
638 	{
639 		if (auto otherIntType = dynamic_cast<IntegerType const*>(_other))
640 		{
641 			if (otherIntType->isSigned())
642 				return TypeResult::err("Exponentiation power is not allowed to be a signed integer type.");
643 		}
644 		else if (dynamic_cast<FixedPointType const*>(_other))
645 			return nullptr;
646 		else if (auto rationalNumberType = dynamic_cast<RationalNumberType const*>(_other))
647 		{
648 			if (rationalNumberType->isFractional())
649 				return TypeResult::err("Exponent is fractional.");
650 			if (!rationalNumberType->integerType())
651 				return TypeResult::err("Exponent too large.");
652 			if (rationalNumberType->isNegative())
653 				return TypeResult::err("Exponentiation power is not allowed to be a negative integer literal.");
654 		}
655 		return this;
656 	}
657 
658 	auto commonType = Type::commonType(this, _other); //might be an integer or fixed point
659 	if (!commonType)
660 		return nullptr;
661 
662 	// All integer types can be compared
663 	if (TokenTraits::isCompareOp(_operator))
664 		return commonType;
665 	if (TokenTraits::isBooleanOp(_operator))
666 		return nullptr;
667 	return commonType;
668 }
669 
FixedPointType(unsigned _totalBits,unsigned _fractionalDigits,FixedPointType::Modifier _modifier)670 FixedPointType::FixedPointType(unsigned _totalBits, unsigned _fractionalDigits, FixedPointType::Modifier _modifier):
671 	m_totalBits(_totalBits), m_fractionalDigits(_fractionalDigits), m_modifier(_modifier)
672 {
673 	solAssert(
674 		8 <= m_totalBits && m_totalBits <= 256 && m_totalBits % 8 == 0 && m_fractionalDigits <= 80,
675 		"Invalid bit number(s) for fixed type: " +
676 		util::toString(_totalBits) + "x" + util::toString(_fractionalDigits)
677 	);
678 }
679 
richIdentifier() const680 string FixedPointType::richIdentifier() const
681 {
682 	return "t_" + string(isSigned() ? "" : "u") + "fixed" + to_string(m_totalBits) + "x" + to_string(m_fractionalDigits);
683 }
684 
isImplicitlyConvertibleTo(Type const & _convertTo) const685 BoolResult FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
686 {
687 	if (_convertTo.category() == category())
688 	{
689 		FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
690 		if (convertTo.fractionalDigits() < m_fractionalDigits)
691 			return BoolResult::err("Too many fractional digits.");
692 		if (convertTo.numBits() < m_totalBits)
693 			return false;
694 		else
695 			return convertTo.maxIntegerValue() >= maxIntegerValue() && convertTo.minIntegerValue() <= minIntegerValue();
696 	}
697 	return false;
698 }
699 
isExplicitlyConvertibleTo(Type const & _convertTo) const700 BoolResult FixedPointType::isExplicitlyConvertibleTo(Type const& _convertTo) const
701 {
702 	return _convertTo.category() == category() || _convertTo.category() == Category::Integer;
703 }
704 
unaryOperatorResult(Token _operator) const705 TypeResult FixedPointType::unaryOperatorResult(Token _operator) const
706 {
707 	switch (_operator)
708 	{
709 	case Token::Delete:
710 		// "delete" is ok for all fixed types
711 		return TypeResult{TypeProvider::emptyTuple()};
712 	case Token::Add:
713 	case Token::Sub:
714 	case Token::Inc:
715 	case Token::Dec:
716 		// for fixed, we allow +, -, ++ and --
717 		return this;
718 	default:
719 		return nullptr;
720 	}
721 }
722 
operator ==(Type const & _other) const723 bool FixedPointType::operator==(Type const& _other) const
724 {
725 	if (_other.category() != category())
726 		return false;
727 	FixedPointType const& other = dynamic_cast<FixedPointType const&>(_other);
728 	return other.m_totalBits == m_totalBits && other.m_fractionalDigits == m_fractionalDigits && other.m_modifier == m_modifier;
729 }
730 
toString(bool) const731 string FixedPointType::toString(bool) const
732 {
733 	string prefix = isSigned() ? "fixed" : "ufixed";
734 	return prefix + util::toString(m_totalBits) + "x" + util::toString(m_fractionalDigits);
735 }
736 
maxIntegerValue() const737 bigint FixedPointType::maxIntegerValue() const
738 {
739 	bigint maxValue = (bigint(1) << (m_totalBits - (isSigned() ? 1 : 0))) - 1;
740 	return maxValue / boost::multiprecision::pow(bigint(10), m_fractionalDigits);
741 }
742 
minIntegerValue() const743 bigint FixedPointType::minIntegerValue() const
744 {
745 	if (isSigned())
746 	{
747 		bigint minValue = -(bigint(1) << (m_totalBits - (isSigned() ? 1 : 0)));
748 		return minValue / boost::multiprecision::pow(bigint(10), m_fractionalDigits);
749 	}
750 	else
751 		return bigint(0);
752 }
753 
binaryOperatorResult(Token _operator,Type const * _other) const754 TypeResult FixedPointType::binaryOperatorResult(Token _operator, Type const* _other) const
755 {
756 	auto commonType = Type::commonType(this, _other);
757 
758 	if (!commonType)
759 		return nullptr;
760 
761 	// All fixed types can be compared
762 	if (TokenTraits::isCompareOp(_operator))
763 		return commonType;
764 	if (TokenTraits::isBitOp(_operator) || TokenTraits::isBooleanOp(_operator) || _operator == Token::Exp)
765 		return nullptr;
766 	return commonType;
767 }
768 
asIntegerType() const769 IntegerType const* FixedPointType::asIntegerType() const
770 {
771 	return TypeProvider::integer(numBits(), isSigned() ? IntegerType::Modifier::Signed : IntegerType::Modifier::Unsigned);
772 }
773 
parseRational(string const & _value)774 tuple<bool, rational> RationalNumberType::parseRational(string const& _value)
775 {
776 	rational value;
777 	try
778 	{
779 		auto radixPoint = find(_value.begin(), _value.end(), '.');
780 
781 		if (radixPoint != _value.end())
782 		{
783 			if (
784 				!all_of(radixPoint + 1, _value.end(), ::isdigit) ||
785 				!all_of(_value.begin(), radixPoint, ::isdigit)
786 			)
787 				return make_tuple(false, rational(0));
788 
789 			// Only decimal notation allowed here, leading zeros would switch to octal.
790 			auto fractionalBegin = find_if_not(
791 				radixPoint + 1,
792 				_value.end(),
793 				[](char const& a) { return a == '0'; }
794 			);
795 
796 			rational numerator;
797 			rational denominator(1);
798 
799 			denominator = bigint(string(fractionalBegin, _value.end()));
800 			denominator /= boost::multiprecision::pow(
801 				bigint(10),
802 				static_cast<unsigned>(distance(radixPoint + 1, _value.end()))
803 			);
804 			numerator = bigint(string(_value.begin(), radixPoint));
805 			value = numerator + denominator;
806 		}
807 		else
808 			value = bigint(_value);
809 		return make_tuple(true, value);
810 	}
811 	catch (...)
812 	{
813 		return make_tuple(false, rational(0));
814 	}
815 }
816 
isValidLiteral(Literal const & _literal)817 tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal)
818 {
819 	rational value;
820 	try
821 	{
822 		ASTString valueString = _literal.valueWithoutUnderscores();
823 
824 		auto expPoint = find(valueString.begin(), valueString.end(), 'e');
825 		if (expPoint == valueString.end())
826 			expPoint = find(valueString.begin(), valueString.end(), 'E');
827 
828 		if (boost::starts_with(valueString, "0x"))
829 		{
830 			// process as hex
831 			value = bigint(valueString);
832 		}
833 		else if (expPoint != valueString.end())
834 		{
835 			// Parse mantissa and exponent. Checks numeric limit.
836 			tuple<bool, rational> mantissa = parseRational(string(valueString.begin(), expPoint));
837 
838 			if (!get<0>(mantissa))
839 				return make_tuple(false, rational(0));
840 			value = get<1>(mantissa);
841 
842 			// 0E... is always zero.
843 			if (value == 0)
844 				return make_tuple(true, rational(0));
845 
846 			bigint exp = bigint(string(expPoint + 1, valueString.end()));
847 
848 			if (exp > numeric_limits<int32_t>::max() || exp < numeric_limits<int32_t>::min())
849 				return make_tuple(false, rational(0));
850 
851 			uint32_t expAbs = bigint(abs(exp)).convert_to<uint32_t>();
852 
853 			if (exp < 0)
854 			{
855 				if (!fitsPrecisionBase10(abs(value.denominator()), expAbs))
856 					return make_tuple(false, rational(0));
857 				value /= boost::multiprecision::pow(
858 					bigint(10),
859 					expAbs
860 				);
861 			}
862 			else if (exp > 0)
863 			{
864 				if (!fitsPrecisionBase10(abs(value.numerator()), expAbs))
865 					return make_tuple(false, rational(0));
866 				value *= boost::multiprecision::pow(
867 					bigint(10),
868 					expAbs
869 				);
870 			}
871 		}
872 		else
873 		{
874 			// parse as rational number
875 			tuple<bool, rational> tmp = parseRational(valueString);
876 			if (!get<0>(tmp))
877 				return tmp;
878 			value = get<1>(tmp);
879 		}
880 	}
881 	catch (...)
882 	{
883 		return make_tuple(false, rational(0));
884 	}
885 	switch (_literal.subDenomination())
886 	{
887 		case Literal::SubDenomination::None:
888 		case Literal::SubDenomination::Wei:
889 		case Literal::SubDenomination::Second:
890 			break;
891 		case Literal::SubDenomination::Gwei:
892 			value *= bigint("1000000000");
893 			break;
894 		case Literal::SubDenomination::Ether:
895 			value *= bigint("1000000000000000000");
896 			break;
897 		case Literal::SubDenomination::Minute:
898 			value *= bigint("60");
899 			break;
900 		case Literal::SubDenomination::Hour:
901 			value *= bigint("3600");
902 			break;
903 		case Literal::SubDenomination::Day:
904 			value *= bigint("86400");
905 			break;
906 		case Literal::SubDenomination::Week:
907 			value *= bigint("604800");
908 			break;
909 		case Literal::SubDenomination::Year:
910 			value *= bigint("31536000");
911 			break;
912 	}
913 
914 
915 	return make_tuple(true, value);
916 }
917 
isImplicitlyConvertibleTo(Type const & _convertTo) const918 BoolResult RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
919 {
920 	switch (_convertTo.category())
921 	{
922 	case Category::Integer:
923 	{
924 		if (isFractional())
925 			return false;
926 		IntegerType const& targetType = dynamic_cast<IntegerType const&>(_convertTo);
927 		return fitsIntegerType(m_value.numerator(), targetType);
928 	}
929 	case Category::FixedPoint:
930 	{
931 		FixedPointType const& targetType = dynamic_cast<FixedPointType const&>(_convertTo);
932 		// Store a negative number into an unsigned.
933 		if (isNegative() && !targetType.isSigned())
934 			return false;
935 		if (!isFractional())
936 			return (targetType.minIntegerValue() <= m_value) && (m_value <= targetType.maxIntegerValue());
937 		rational value = m_value * pow(bigint(10), targetType.fractionalDigits());
938 		// Need explicit conversion since truncation will occur.
939 		if (value.denominator() != 1)
940 			return false;
941 		return fitsIntoBits(value.numerator(), targetType.numBits(), targetType.isSigned());
942 	}
943 	case Category::FixedBytes:
944 		return (m_value == rational(0)) || (m_compatibleBytesType && *m_compatibleBytesType == _convertTo);
945 	default:
946 		return false;
947 	}
948 }
949 
isExplicitlyConvertibleTo(Type const & _convertTo) const950 BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
951 {
952 	if (isImplicitlyConvertibleTo(_convertTo))
953 		return true;
954 
955 	auto category = _convertTo.category();
956 	if (category == Category::FixedBytes)
957 		return false;
958 	else if (auto addressType = dynamic_cast<AddressType const*>(&_convertTo))
959 		return	(m_value == 0) ||
960 			((addressType->stateMutability() != StateMutability::Payable) &&
961 			!isNegative() &&
962 			!isFractional() &&
963 			integerType() &&
964 			(integerType()->numBits() <= 160));
965 	else if (category == Category::Integer)
966 		return false;
967 	else if (auto enumType = dynamic_cast<EnumType const*>(&_convertTo))
968 		if (isNegative() || isFractional() || m_value >= enumType->numberOfMembers())
969 			return false;
970 
971 	Type const* mobType = mobileType();
972 	return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo));
973 
974 }
975 
unaryOperatorResult(Token _operator) const976 TypeResult RationalNumberType::unaryOperatorResult(Token _operator) const
977 {
978 	if (optional<rational> value = ConstantEvaluator::evaluateUnaryOperator(_operator, m_value))
979 		return TypeResult{TypeProvider::rationalNumber(*value)};
980 	else
981 		return nullptr;
982 }
983 
binaryOperatorResult(Token _operator,Type const * _other) const984 TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const* _other) const
985 {
986 	if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint)
987 	{
988 		if (isFractional())
989 			return TypeResult::err("Fractional literals not supported.");
990 		else if (!integerType())
991 			return TypeResult::err("Literal too large.");
992 
993 		// Shift and exp are not symmetric, so it does not make sense to swap
994 		// the types as below. As an exception, we always use uint here.
995 		if (TokenTraits::isShiftOp(_operator))
996 		{
997 			if (!isValidShiftAndAmountType(_operator, *_other))
998 				return nullptr;
999 			return isNegative() ? TypeProvider::int256() : TypeProvider::uint256();
1000 		}
1001 		else if (Token::Exp == _operator)
1002 		{
1003 			if (auto const* otherIntType = dynamic_cast<IntegerType const*>(_other))
1004 			{
1005 				if (otherIntType->isSigned())
1006 					return TypeResult::err("Exponentiation power is not allowed to be a signed integer type.");
1007 			}
1008 			else if (dynamic_cast<FixedPointType const*>(_other))
1009 				return TypeResult::err("Exponent is fractional.");
1010 
1011 			return isNegative() ? TypeProvider::int256() : TypeProvider::uint256();
1012 		}
1013 		else
1014 		{
1015 			auto commonType = Type::commonType(this, _other);
1016 			if (!commonType)
1017 				return nullptr;
1018 			return commonType->binaryOperatorResult(_operator, _other);
1019 		}
1020 	}
1021 	else if (_other->category() != category())
1022 		return nullptr;
1023 
1024 	RationalNumberType const& other = dynamic_cast<RationalNumberType const&>(*_other);
1025 	if (TokenTraits::isCompareOp(_operator))
1026 	{
1027 		// Since we do not have a "BoolConstantType", we have to do the actual comparison
1028 		// at runtime and convert to mobile typse first. Such a comparison is not a very common
1029 		// use-case and will be optimized away.
1030 		Type const* thisMobile = mobileType();
1031 		Type const* otherMobile = other.mobileType();
1032 		if (!thisMobile || !otherMobile)
1033 			return nullptr;
1034 		return thisMobile->binaryOperatorResult(_operator, otherMobile);
1035 	}
1036 	else if (optional<rational> value = ConstantEvaluator::evaluateBinaryOperator(_operator, m_value, other.m_value))
1037 	{
1038 		// verify that numerator and denominator fit into 4096 bit after every operation
1039 		if (value->numerator() != 0 && max(boost::multiprecision::msb(abs(value->numerator())), boost::multiprecision::msb(abs(value->denominator()))) > 4096)
1040 			return TypeResult::err("Precision of rational constants is limited to 4096 bits.");
1041 
1042 		return TypeResult{TypeProvider::rationalNumber(*value)};
1043 	}
1044 	else
1045 		return nullptr;
1046 }
1047 
richIdentifier() const1048 string RationalNumberType::richIdentifier() const
1049 {
1050 	// rational seemingly will put the sign always on the numerator,
1051 	// but let just make it deterministic here.
1052 	bigint numerator = abs(m_value.numerator());
1053 	bigint denominator = abs(m_value.denominator());
1054 	if (m_value < 0)
1055 		return "t_rational_minus_" + numerator.str() + "_by_" + denominator.str();
1056 	else
1057 		return "t_rational_" + numerator.str() + "_by_" + denominator.str();
1058 }
1059 
operator ==(Type const & _other) const1060 bool RationalNumberType::operator==(Type const& _other) const
1061 {
1062 	if (_other.category() != category())
1063 		return false;
1064 	RationalNumberType const& other = dynamic_cast<RationalNumberType const&>(_other);
1065 	return m_value == other.m_value;
1066 }
1067 
bigintToReadableString(bigint const & _num)1068 string RationalNumberType::bigintToReadableString(bigint const& _num)
1069 {
1070 	string str = _num.str();
1071 	if (str.size() > 32)
1072 	{
1073 		size_t omitted = str.size() - 8;
1074 		str = str.substr(0, 4) + "...(" + to_string(omitted) + " digits omitted)..." + str.substr(str.size() - 4, 4);
1075 	}
1076 	return str;
1077 }
1078 
toString(bool) const1079 string RationalNumberType::toString(bool) const
1080 {
1081 	if (!isFractional())
1082 		return "int_const " + bigintToReadableString(m_value.numerator());
1083 
1084 	string numerator = bigintToReadableString(m_value.numerator());
1085 	string denominator = bigintToReadableString(m_value.denominator());
1086 	return "rational_const " + numerator + " / " + denominator;
1087 }
1088 
literalValue(Literal const *) const1089 u256 RationalNumberType::literalValue(Literal const*) const
1090 {
1091 	// We ignore the literal and hope that the type was correctly determined to represent
1092 	// its value.
1093 
1094 	u256 value;
1095 	bigint shiftedValue;
1096 
1097 	if (!isFractional())
1098 		shiftedValue = m_value.numerator();
1099 	else
1100 	{
1101 		auto fixed = fixedPointType();
1102 		solAssert(fixed, "Rational number cannot be represented as fixed point type.");
1103 		unsigned fractionalDigits = fixed->fractionalDigits();
1104 		shiftedValue = m_value.numerator() * boost::multiprecision::pow(bigint(10), fractionalDigits) / m_value.denominator();
1105 	}
1106 
1107 	// we ignore the literal and hope that the type was correctly determined
1108 	solAssert(shiftedValue <= u256(-1), "Number constant too large.");
1109 	solAssert(shiftedValue >= -(bigint(1) << 255), "Number constant too small.");
1110 
1111 	if (m_value >= rational(0))
1112 		value = u256(shiftedValue);
1113 	else
1114 		value = s2u(s256(shiftedValue));
1115 	return value;
1116 }
1117 
mobileType() const1118 Type const* RationalNumberType::mobileType() const
1119 {
1120 	if (!isFractional())
1121 		return integerType();
1122 	else
1123 		return fixedPointType();
1124 }
1125 
integerType() const1126 IntegerType const* RationalNumberType::integerType() const
1127 {
1128 	solAssert(!isFractional(), "integerType() called for fractional number.");
1129 	bigint value = m_value.numerator();
1130 	bool negative = (value < 0);
1131 	if (negative) // convert to positive number of same bit requirements
1132 		value = ((0 - value) - 1) << 1;
1133 	if (value > u256(-1))
1134 		return nullptr;
1135 	else
1136 		return TypeProvider::integer(
1137 			max(numberEncodingSize(value), 1u) * 8,
1138 			negative ? IntegerType::Modifier::Signed : IntegerType::Modifier::Unsigned
1139 		);
1140 }
1141 
fixedPointType() const1142 FixedPointType const* RationalNumberType::fixedPointType() const
1143 {
1144 	bool negative = (m_value < 0);
1145 	unsigned fractionalDigits = 0;
1146 	rational value = abs(m_value); // We care about the sign later.
1147 	rational maxValue = negative ?
1148 		rational(bigint(1) << 255, 1):
1149 		rational((bigint(1) << 256) - 1, 1);
1150 
1151 	while (value * 10 <= maxValue && value.denominator() != 1 && fractionalDigits < 80)
1152 	{
1153 		value *= 10;
1154 		fractionalDigits++;
1155 	}
1156 
1157 	if (value > maxValue)
1158 		return nullptr;
1159 
1160 	// This means we round towards zero for positive and negative values.
1161 	bigint v = value.numerator() / value.denominator();
1162 
1163 	if (negative && v != 0)
1164 		// modify value to satisfy bit requirements for negative numbers:
1165 		// add one bit for sign and decrement because negative numbers can be larger
1166 		v = (v - 1) << 1;
1167 
1168 	if (v > u256(-1))
1169 		return nullptr;
1170 
1171 	unsigned totalBits = max(numberEncodingSize(v), 1u) * 8;
1172 	solAssert(totalBits <= 256, "");
1173 
1174 	return TypeProvider::fixedPoint(
1175 		totalBits, fractionalDigits,
1176 		negative ? FixedPointType::Modifier::Signed : FixedPointType::Modifier::Unsigned
1177 	);
1178 }
1179 
StringLiteralType(Literal const & _literal)1180 StringLiteralType::StringLiteralType(Literal const& _literal):
1181 	m_value(_literal.value())
1182 {
1183 }
1184 
StringLiteralType(string _value)1185 StringLiteralType::StringLiteralType(string _value):
1186 	m_value{std::move(_value)}
1187 {
1188 }
1189 
isImplicitlyConvertibleTo(Type const & _convertTo) const1190 BoolResult StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const
1191 {
1192 	if (auto fixedBytes = dynamic_cast<FixedBytesType const*>(&_convertTo))
1193 	{
1194 		if (static_cast<size_t>(fixedBytes->numBytes()) < m_value.size())
1195 			return BoolResult::err("Literal is larger than the type.");
1196 		return true;
1197 	}
1198 	else if (auto arrayType = dynamic_cast<ArrayType const*>(&_convertTo))
1199 	{
1200 		size_t invalidSequence;
1201 		if (arrayType->isString() && !util::validateUTF8(value(), invalidSequence))
1202 			return BoolResult::err(
1203 				"Contains invalid UTF-8 sequence at position " +
1204 				util::toString(invalidSequence) +
1205 				"."
1206 			);
1207 		return
1208 			arrayType->location() != DataLocation::CallData &&
1209 			arrayType->isByteArray() &&
1210 			!(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer());
1211 	}
1212 	else
1213 		return false;
1214 }
1215 
richIdentifier() const1216 string StringLiteralType::richIdentifier() const
1217 {
1218 	// Since we have to return a valid identifier and the string itself may contain
1219 	// anything, we hash it.
1220 	return "t_stringliteral_" + util::toHex(util::keccak256(m_value).asBytes());
1221 }
1222 
operator ==(Type const & _other) const1223 bool StringLiteralType::operator==(Type const& _other) const
1224 {
1225 	if (_other.category() != category())
1226 		return false;
1227 	return m_value == dynamic_cast<StringLiteralType const&>(_other).m_value;
1228 }
1229 
toString(bool) const1230 std::string StringLiteralType::toString(bool) const
1231 {
1232 	auto isPrintableASCII = [](string const& s)
1233 	{
1234 		for (auto c: s)
1235 		{
1236 			if (static_cast<unsigned>(c) <= 0x1f || static_cast<unsigned>(c) >= 0x7f)
1237 				return false;
1238 		}
1239 		return true;
1240 	};
1241 
1242 	return isPrintableASCII(m_value) ?
1243 		("literal_string \"" + m_value + "\"") :
1244 		("literal_string hex\"" + util::toHex(util::asBytes(m_value)) + "\"");
1245 }
1246 
mobileType() const1247 Type const* StringLiteralType::mobileType() const
1248 {
1249 	return TypeProvider::stringMemory();
1250 }
1251 
FixedBytesType(unsigned _bytes)1252 FixedBytesType::FixedBytesType(unsigned _bytes): m_bytes(_bytes)
1253 {
1254 	solAssert(
1255 		m_bytes > 0 && m_bytes <= 32,
1256 		"Invalid byte number for fixed bytes type: " + util::toString(m_bytes)
1257 	);
1258 }
1259 
isImplicitlyConvertibleTo(Type const & _convertTo) const1260 BoolResult FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const
1261 {
1262 	if (_convertTo.category() != category())
1263 		return false;
1264 	FixedBytesType const& convertTo = dynamic_cast<FixedBytesType const&>(_convertTo);
1265 	return convertTo.m_bytes >= m_bytes;
1266 }
1267 
isExplicitlyConvertibleTo(Type const & _convertTo) const1268 BoolResult FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
1269 {
1270 	if (_convertTo.category() == category())
1271 		return true;
1272 	else if (auto integerType = dynamic_cast<IntegerType const*>(&_convertTo))
1273 		return (!integerType->isSigned() && integerType->numBits() == numBytes() * 8);
1274 	else if (auto addressType = dynamic_cast<AddressType const*>(&_convertTo))
1275 		return
1276 			(addressType->stateMutability() != StateMutability::Payable) &&
1277 			(numBytes() == 20);
1278 	else if (auto fixedPointType = dynamic_cast<FixedPointType const*>(&_convertTo))
1279 		return fixedPointType->numBits() == numBytes() * 8;
1280 
1281 	return false;
1282 }
1283 
unaryOperatorResult(Token _operator) const1284 TypeResult FixedBytesType::unaryOperatorResult(Token _operator) const
1285 {
1286 	// "delete" and "~" is okay for FixedBytesType
1287 	if (_operator == Token::Delete)
1288 		return TypeResult{TypeProvider::emptyTuple()};
1289 	else if (_operator == Token::BitNot)
1290 		return this;
1291 
1292 	return nullptr;
1293 }
1294 
binaryOperatorResult(Token _operator,Type const * _other) const1295 TypeResult FixedBytesType::binaryOperatorResult(Token _operator, Type const* _other) const
1296 {
1297 	if (TokenTraits::isShiftOp(_operator))
1298 	{
1299 		if (isValidShiftAndAmountType(_operator, *_other))
1300 			return this;
1301 		else
1302 			return nullptr;
1303 	}
1304 
1305 	auto commonType = dynamic_cast<FixedBytesType const*>(Type::commonType(this, _other));
1306 	if (!commonType)
1307 		return nullptr;
1308 
1309 	// FixedBytes can be compared and have bitwise operators applied to them
1310 	if (TokenTraits::isCompareOp(_operator) || TokenTraits::isBitOp(_operator))
1311 		return TypeResult(commonType);
1312 
1313 	return nullptr;
1314 }
1315 
nativeMembers(ASTNode const *) const1316 MemberList::MemberMap FixedBytesType::nativeMembers(ASTNode const*) const
1317 {
1318 	return MemberList::MemberMap{MemberList::Member{"length", TypeProvider::uint(8)}};
1319 }
1320 
richIdentifier() const1321 string FixedBytesType::richIdentifier() const
1322 {
1323 	return "t_bytes" + to_string(m_bytes);
1324 }
1325 
operator ==(Type const & _other) const1326 bool FixedBytesType::operator==(Type const& _other) const
1327 {
1328 	if (_other.category() != category())
1329 		return false;
1330 	FixedBytesType const& other = dynamic_cast<FixedBytesType const&>(_other);
1331 	return other.m_bytes == m_bytes;
1332 }
1333 
literalValue(Literal const * _literal) const1334 u256 BoolType::literalValue(Literal const* _literal) const
1335 {
1336 	solAssert(_literal, "");
1337 	if (_literal->token() == Token::TrueLiteral)
1338 		return u256(1);
1339 	else if (_literal->token() == Token::FalseLiteral)
1340 		return u256(0);
1341 	else
1342 		solAssert(false, "Bool type constructed from non-boolean literal.");
1343 }
1344 
unaryOperatorResult(Token _operator) const1345 TypeResult BoolType::unaryOperatorResult(Token _operator) const
1346 {
1347 	if (_operator == Token::Delete)
1348 		return TypeProvider::emptyTuple();
1349 	else if (_operator == Token::Not)
1350 		return this;
1351 	else
1352 		return nullptr;
1353 }
1354 
binaryOperatorResult(Token _operator,Type const * _other) const1355 TypeResult BoolType::binaryOperatorResult(Token _operator, Type const* _other) const
1356 {
1357 	if (category() != _other->category())
1358 		return nullptr;
1359 	if (_operator == Token::Equal || _operator == Token::NotEqual || _operator == Token::And || _operator == Token::Or)
1360 		return _other;
1361 	else
1362 		return nullptr;
1363 }
1364 
encodingType() const1365 Type const* ContractType::encodingType() const
1366 {
1367 	if (isSuper())
1368 		return nullptr;
1369 
1370 	if (isPayable())
1371 		return TypeProvider::payableAddress();
1372 	else
1373 		return TypeProvider::address();
1374 }
1375 
isImplicitlyConvertibleTo(Type const & _convertTo) const1376 BoolResult ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const
1377 {
1378 	if (m_super)
1379 		return false;
1380 
1381 	if (*this == _convertTo)
1382 		return true;
1383 	if (_convertTo.category() == Category::Contract)
1384 	{
1385 		auto const& targetContractType = dynamic_cast<ContractType const&>(_convertTo);
1386 		if (targetContractType.isSuper())
1387 			return false;
1388 
1389 		auto const& bases = contractDefinition().annotation().linearizedBaseContracts;
1390 		return find(
1391 			bases.begin(),
1392 			bases.end(),
1393 			&targetContractType.contractDefinition()
1394 		) != bases.end();
1395 	}
1396 	return false;
1397 }
1398 
isExplicitlyConvertibleTo(Type const & _convertTo) const1399 BoolResult ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const
1400 {
1401 	if (m_super)
1402 		return false;
1403 
1404 	if (auto const* addressType = dynamic_cast<AddressType const*>(&_convertTo))
1405 		return isPayable() || (addressType->stateMutability() < StateMutability::Payable);
1406 
1407 	return isImplicitlyConvertibleTo(_convertTo);
1408 }
1409 
isPayable() const1410 bool ContractType::isPayable() const
1411 {
1412 	auto receiveFunction = m_contract.receiveFunction();
1413 	auto fallbackFunction = m_contract.fallbackFunction();
1414 	return receiveFunction || (fallbackFunction && fallbackFunction->isPayable());
1415 }
1416 
unaryOperatorResult(Token _operator) const1417 TypeResult ContractType::unaryOperatorResult(Token _operator) const
1418 {
1419 	if (isSuper())
1420 		return nullptr;
1421 	else if (_operator == Token::Delete)
1422 		return TypeProvider::emptyTuple();
1423 	else
1424 		return nullptr;
1425 }
1426 
fullDecomposition() const1427 vector<Type const*> CompositeType::fullDecomposition() const
1428 {
1429 	vector<Type const*> res = {this};
1430 	unordered_set<string> seen = {richIdentifier()};
1431 	for (size_t k = 0; k < res.size(); ++k)
1432 		if (auto composite = dynamic_cast<CompositeType const*>(res[k]))
1433 			for (Type const* next: composite->decomposition())
1434 				if (seen.count(next->richIdentifier()) == 0)
1435 				{
1436 					seen.insert(next->richIdentifier());
1437 					res.push_back(next);
1438 				}
1439 	return res;
1440 }
1441 
withLocation(DataLocation _location,bool _isPointer) const1442 Type const* ReferenceType::withLocation(DataLocation _location, bool _isPointer) const
1443 {
1444 	return TypeProvider::withLocation(this, _location, _isPointer);
1445 }
1446 
unaryOperatorResult(Token _operator) const1447 TypeResult ReferenceType::unaryOperatorResult(Token _operator) const
1448 {
1449 	if (_operator != Token::Delete)
1450 		return nullptr;
1451 	// delete can be used on everything except calldata references or storage pointers
1452 	// (storage references are ok)
1453 	switch (location())
1454 	{
1455 	case DataLocation::CallData:
1456 		return nullptr;
1457 	case DataLocation::Memory:
1458 		return TypeProvider::emptyTuple();
1459 	case DataLocation::Storage:
1460 		return isPointer() ? nullptr : TypeProvider::emptyTuple();
1461 	}
1462 	return nullptr;
1463 }
1464 
isPointer() const1465 bool ReferenceType::isPointer() const
1466 {
1467 	if (m_location == DataLocation::Storage)
1468 		return m_isPointer;
1469 	else
1470 		return true;
1471 }
1472 
copyForLocationIfReference(Type const * _type) const1473 Type const* ReferenceType::copyForLocationIfReference(Type const* _type) const
1474 {
1475 	return TypeProvider::withLocationIfReference(m_location, _type);
1476 }
1477 
stringForReferencePart() const1478 string ReferenceType::stringForReferencePart() const
1479 {
1480 	switch (m_location)
1481 	{
1482 	case DataLocation::Storage:
1483 		return string("storage ") + (isPointer() ? "pointer" : "ref");
1484 	case DataLocation::CallData:
1485 		return "calldata";
1486 	case DataLocation::Memory:
1487 		return "memory";
1488 	}
1489 	solAssert(false, "");
1490 	return "";
1491 }
1492 
identifierLocationSuffix() const1493 string ReferenceType::identifierLocationSuffix() const
1494 {
1495 	string id;
1496 	switch (location())
1497 	{
1498 	case DataLocation::Storage:
1499 		id += "_storage";
1500 		break;
1501 	case DataLocation::Memory:
1502 		id += "_memory";
1503 		break;
1504 	case DataLocation::CallData:
1505 		id += "_calldata";
1506 		break;
1507 	}
1508 	if (isPointer())
1509 		id += "_ptr";
1510 	return id;
1511 }
1512 
ArrayType(DataLocation _location,bool _isString)1513 ArrayType::ArrayType(DataLocation _location, bool _isString):
1514 	ReferenceType(_location),
1515 	m_arrayKind(_isString ? ArrayKind::String : ArrayKind::Bytes),
1516 	m_baseType{TypeProvider::byte()}
1517 {
1518 }
1519 
clearCache() const1520 void ArrayType::clearCache() const
1521 {
1522 	Type::clearCache();
1523 
1524 	m_interfaceType.reset();
1525 	m_interfaceType_library.reset();
1526 }
1527 
isImplicitlyConvertibleTo(Type const & _convertTo) const1528 BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const
1529 {
1530 	if (_convertTo.category() != category())
1531 		return false;
1532 	auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
1533 	if (convertTo.isByteArray() != isByteArray() || convertTo.isString() != isString())
1534 		return false;
1535 	// memory/calldata to storage can be converted, but only to a direct storage reference
1536 	if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer())
1537 		return false;
1538 	if (convertTo.location() == DataLocation::CallData && location() != convertTo.location())
1539 		return false;
1540 	if (convertTo.location() == DataLocation::Storage && !convertTo.isPointer())
1541 	{
1542 		// Less restrictive conversion, since we need to copy anyway.
1543 		if (!baseType()->isImplicitlyConvertibleTo(*convertTo.baseType()))
1544 			return false;
1545 		if (convertTo.isDynamicallySized())
1546 			return true;
1547 		return !isDynamicallySized() && convertTo.length() >= length();
1548 	}
1549 	else
1550 	{
1551 		// Conversion to storage pointer or to memory, we de not copy element-for-element here, so
1552 		// require that the base type is the same, not only convertible.
1553 		// This disallows assignment of nested dynamic arrays from storage to memory for now.
1554 		if (
1555 			*TypeProvider::withLocationIfReference(location(), baseType()) !=
1556 			*TypeProvider::withLocationIfReference(location(), convertTo.baseType())
1557 		)
1558 			return false;
1559 		if (isDynamicallySized() != convertTo.isDynamicallySized())
1560 			return false;
1561 		// We also require that the size is the same.
1562 		if (!isDynamicallySized() && length() != convertTo.length())
1563 			return false;
1564 		return true;
1565 	}
1566 }
1567 
isExplicitlyConvertibleTo(Type const & _convertTo) const1568 BoolResult ArrayType::isExplicitlyConvertibleTo(Type const& _convertTo) const
1569 {
1570 	if (isImplicitlyConvertibleTo(_convertTo))
1571 		return true;
1572 	// allow conversion bytes <-> string and bytes -> bytesNN
1573 	if (_convertTo.category() != category())
1574 		return isByteArray() && !isString() && _convertTo.category() == Type::Category::FixedBytes;
1575 	auto& convertTo = dynamic_cast<ArrayType const&>(_convertTo);
1576 	if (convertTo.location() != location())
1577 		return false;
1578 	if (!isByteArray() || !convertTo.isByteArray())
1579 		return false;
1580 	return true;
1581 }
1582 
richIdentifier() const1583 string ArrayType::richIdentifier() const
1584 {
1585 	string id;
1586 	if (isString())
1587 		id = "t_string";
1588 	else if (isByteArray())
1589 		id = "t_bytes";
1590 	else
1591 	{
1592 		id = "t_array";
1593 		id += identifierList(baseType());
1594 		if (isDynamicallySized())
1595 			id += "dyn";
1596 		else
1597 			id += length().str();
1598 	}
1599 	id += identifierLocationSuffix();
1600 
1601 	return id;
1602 }
1603 
operator ==(Type const & _other) const1604 bool ArrayType::operator==(Type const& _other) const
1605 {
1606 	if (_other.category() != category())
1607 		return false;
1608 	ArrayType const& other = dynamic_cast<ArrayType const&>(_other);
1609 	if (
1610 		!ReferenceType::operator==(other) ||
1611 		other.isByteArray() != isByteArray() ||
1612 		other.isString() != isString() ||
1613 		other.isDynamicallySized() != isDynamicallySized()
1614 	)
1615 		return false;
1616 	if (*other.baseType() != *baseType())
1617 		return false;
1618 	return isDynamicallySized() || length() == other.length();
1619 }
1620 
validForLocation(DataLocation _loc) const1621 BoolResult ArrayType::validForLocation(DataLocation _loc) const
1622 {
1623 	if (auto arrayBaseType = dynamic_cast<ArrayType const*>(baseType()))
1624 	{
1625 		BoolResult result = arrayBaseType->validForLocation(_loc);
1626 		if (!result)
1627 			return result;
1628 	}
1629 	if (isDynamicallySized())
1630 		return true;
1631 	switch (_loc)
1632 	{
1633 		case DataLocation::Memory:
1634 		{
1635 			bigint size = bigint(length());
1636 			auto type = m_baseType;
1637 			while (auto arrayType = dynamic_cast<ArrayType const*>(type))
1638 			{
1639 				if (arrayType->isDynamicallySized())
1640 					break;
1641 				else
1642 				{
1643 					size *= arrayType->length();
1644 					type = arrayType->baseType();
1645 				}
1646 			}
1647 			if (type->isDynamicallySized())
1648 				size *= type->memoryHeadSize();
1649 			else
1650 				size *= type->memoryDataSize();
1651 			if (size >= numeric_limits<unsigned>::max())
1652 				return BoolResult::err("Type too large for memory.");
1653 			break;
1654 		}
1655 		case DataLocation::CallData:
1656 		{
1657 			if (unlimitedStaticCalldataSize(true) >= numeric_limits<unsigned>::max())
1658 				return BoolResult::err("Type too large for calldata.");
1659 			break;
1660 		}
1661 		case DataLocation::Storage:
1662 			if (storageSizeUpperBound() >= bigint(1) << 256)
1663 				return BoolResult::err("Type too large for storage.");
1664 			break;
1665 	}
1666 	return true;
1667 }
1668 
unlimitedStaticCalldataSize(bool _padded) const1669 bigint ArrayType::unlimitedStaticCalldataSize(bool _padded) const
1670 {
1671 	solAssert(!isDynamicallySized(), "");
1672 	bigint size = bigint(length()) * calldataStride();
1673 	if (_padded)
1674 		size = ((size + 31) / 32) * 32;
1675 	return size;
1676 }
1677 
calldataEncodedSize(bool _padded) const1678 unsigned ArrayType::calldataEncodedSize(bool _padded) const
1679 {
1680 	solAssert(!isDynamicallyEncoded(), "");
1681 	bigint size = unlimitedStaticCalldataSize(_padded);
1682 	solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned.");
1683 	return unsigned(size);
1684 }
1685 
calldataEncodedTailSize() const1686 unsigned ArrayType::calldataEncodedTailSize() const
1687 {
1688 	solAssert(isDynamicallyEncoded(), "");
1689 	if (isDynamicallySized())
1690 		// We do not know the dynamic length itself, but at least the uint256 containing the
1691 		// length must still be present.
1692 		return 32;
1693 	bigint size = unlimitedStaticCalldataSize(false);
1694 	solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned.");
1695 	return unsigned(size);
1696 }
1697 
isDynamicallyEncoded() const1698 bool ArrayType::isDynamicallyEncoded() const
1699 {
1700 	return isDynamicallySized() || baseType()->isDynamicallyEncoded();
1701 }
1702 
storageSizeUpperBound() const1703 bigint ArrayType::storageSizeUpperBound() const
1704 {
1705 	if (isDynamicallySized())
1706 		return 1;
1707 	else
1708 		return length() * baseType()->storageSizeUpperBound();
1709 }
1710 
storageSize() const1711 u256 ArrayType::storageSize() const
1712 {
1713 	if (isDynamicallySized())
1714 		return 1;
1715 
1716 	bigint size;
1717 	unsigned baseBytes = baseType()->storageBytes();
1718 	if (baseBytes == 0)
1719 		size = 1;
1720 	else if (baseBytes < 32)
1721 	{
1722 		unsigned itemsPerSlot = 32 / baseBytes;
1723 		size = (bigint(length()) + (itemsPerSlot - 1)) / itemsPerSlot;
1724 	}
1725 	else
1726 		size = bigint(length()) * baseType()->storageSize();
1727 	solAssert(size < bigint(1) << 256, "Array too large for storage.");
1728 	return max<u256>(1, u256(size));
1729 }
1730 
makeStackItems() const1731 vector<tuple<string, Type const*>> ArrayType::makeStackItems() const
1732 {
1733 	switch (m_location)
1734 	{
1735 		case DataLocation::CallData:
1736 			if (isDynamicallySized())
1737 				return {std::make_tuple("offset", TypeProvider::uint256()), std::make_tuple("length", TypeProvider::uint256())};
1738 			else
1739 				return {std::make_tuple("offset", TypeProvider::uint256())};
1740 		case DataLocation::Memory:
1741 			return {std::make_tuple("mpos", TypeProvider::uint256())};
1742 		case DataLocation::Storage:
1743 			// byte offset inside storage value is omitted
1744 			return {std::make_tuple("slot", TypeProvider::uint256())};
1745 	}
1746 	solAssert(false, "");
1747 }
1748 
toString(bool _short) const1749 string ArrayType::toString(bool _short) const
1750 {
1751 	string ret;
1752 	if (isString())
1753 		ret = "string";
1754 	else if (isByteArray())
1755 		ret = "bytes";
1756 	else
1757 	{
1758 		ret = baseType()->toString(_short) + "[";
1759 		if (!isDynamicallySized())
1760 			ret += length().str();
1761 		ret += "]";
1762 	}
1763 	if (!_short)
1764 		ret += " " + stringForReferencePart();
1765 	return ret;
1766 }
1767 
canonicalName() const1768 string ArrayType::canonicalName() const
1769 {
1770 	string ret;
1771 	if (isString())
1772 		ret = "string";
1773 	else if (isByteArray())
1774 		ret = "bytes";
1775 	else
1776 	{
1777 		ret = baseType()->canonicalName() + "[";
1778 		if (!isDynamicallySized())
1779 			ret += length().str();
1780 		ret += "]";
1781 	}
1782 	return ret;
1783 }
1784 
signatureInExternalFunction(bool _structsByName) const1785 string ArrayType::signatureInExternalFunction(bool _structsByName) const
1786 {
1787 	if (isByteArray())
1788 		return canonicalName();
1789 	else
1790 	{
1791 		solAssert(baseType(), "");
1792 		return
1793 			baseType()->signatureInExternalFunction(_structsByName) +
1794 			"[" +
1795 			(isDynamicallySized() ? "" : length().str()) +
1796 			"]";
1797 	}
1798 }
1799 
nativeMembers(ASTNode const *) const1800 MemberList::MemberMap ArrayType::nativeMembers(ASTNode const*) const
1801 {
1802 	MemberList::MemberMap members;
1803 	if (!isString())
1804 	{
1805 		members.emplace_back("length", TypeProvider::uint256());
1806 		if (isDynamicallySized() && location() == DataLocation::Storage)
1807 		{
1808 			Type const* thisAsPointer = TypeProvider::withLocation(this, location(), true);
1809 			members.emplace_back("push", TypeProvider::function(
1810 				TypePointers{thisAsPointer},
1811 				TypePointers{baseType()},
1812 				strings{string()},
1813 				strings{string()},
1814 				FunctionType::Kind::ArrayPush
1815 			)->asBoundFunction());
1816 			members.emplace_back("push", TypeProvider::function(
1817 				TypePointers{thisAsPointer, baseType()},
1818 				TypePointers{},
1819 				strings{string(),string()},
1820 				strings{},
1821 				FunctionType::Kind::ArrayPush
1822 			)->asBoundFunction());
1823 			members.emplace_back("pop", TypeProvider::function(
1824 				TypePointers{thisAsPointer},
1825 				TypePointers{},
1826 				strings{string()},
1827 				strings{},
1828 				FunctionType::Kind::ArrayPop
1829 			)->asBoundFunction());
1830 		}
1831 	}
1832 	return members;
1833 }
1834 
encodingType() const1835 Type const* ArrayType::encodingType() const
1836 {
1837 	if (location() == DataLocation::Storage)
1838 		return TypeProvider::uint256();
1839 	else
1840 		return TypeProvider::withLocation(this, DataLocation::Memory, true);
1841 }
1842 
decodingType() const1843 Type const* ArrayType::decodingType() const
1844 {
1845 	if (location() == DataLocation::Storage)
1846 		return TypeProvider::uint256();
1847 	else
1848 		return this;
1849 }
1850 
interfaceType(bool _inLibrary) const1851 TypeResult ArrayType::interfaceType(bool _inLibrary) const
1852 {
1853 	if (_inLibrary && m_interfaceType_library.has_value())
1854 		return *m_interfaceType_library;
1855 
1856 	if (!_inLibrary && m_interfaceType.has_value())
1857 		return *m_interfaceType;
1858 
1859 	TypeResult result{nullptr};
1860 	TypeResult baseInterfaceType = m_baseType->interfaceType(_inLibrary);
1861 
1862 	if (!baseInterfaceType.get())
1863 	{
1864 		solAssert(!baseInterfaceType.message().empty(), "Expected detailed error message!");
1865 		result = baseInterfaceType;
1866 	}
1867 	else if (_inLibrary && location() == DataLocation::Storage)
1868 		result = this;
1869 	else if (m_arrayKind != ArrayKind::Ordinary)
1870 		result = TypeProvider::withLocation(this, DataLocation::Memory, true);
1871 	else if (isDynamicallySized())
1872 		result = TypeProvider::array(DataLocation::Memory, baseInterfaceType);
1873 	else
1874 		result = TypeProvider::array(DataLocation::Memory, baseInterfaceType, m_length);
1875 
1876 	if (_inLibrary)
1877 		m_interfaceType_library = result;
1878 	else
1879 		m_interfaceType = result;
1880 
1881 	return result;
1882 }
1883 
finalBaseType(bool _breakIfDynamicArrayType) const1884 Type const* ArrayType::finalBaseType(bool _breakIfDynamicArrayType) const
1885 {
1886 	Type const* finalBaseType = this;
1887 
1888 	while (auto arrayType = dynamic_cast<ArrayType const*>(finalBaseType))
1889 	{
1890 		if (_breakIfDynamicArrayType && arrayType->isDynamicallySized())
1891 			break;
1892 		finalBaseType = arrayType->baseType();
1893 	}
1894 
1895 	return finalBaseType;
1896 }
1897 
memoryDataSize() const1898 u256 ArrayType::memoryDataSize() const
1899 {
1900 	solAssert(!isDynamicallySized(), "");
1901 	solAssert(m_location == DataLocation::Memory, "");
1902 	solAssert(!isByteArray(), "");
1903 	bigint size = bigint(m_length) * m_baseType->memoryHeadSize();
1904 	solAssert(size <= numeric_limits<u256>::max(), "Array size does not fit u256.");
1905 	return u256(size);
1906 }
1907 
copyForLocation(DataLocation _location,bool _isPointer) const1908 std::unique_ptr<ReferenceType> ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const
1909 {
1910 	auto copy = make_unique<ArrayType>(_location);
1911 	if (_location == DataLocation::Storage)
1912 		copy->m_isPointer = _isPointer;
1913 	copy->m_arrayKind = m_arrayKind;
1914 	copy->m_baseType = copy->copyForLocationIfReference(m_baseType);
1915 	copy->m_hasDynamicLength = m_hasDynamicLength;
1916 	copy->m_length = m_length;
1917 	return copy;
1918 }
1919 
isImplicitlyConvertibleTo(Type const & _other) const1920 BoolResult ArraySliceType::isImplicitlyConvertibleTo(Type const& _other) const
1921 {
1922 	return
1923 		(*this) == _other ||
1924 		(
1925 			m_arrayType.dataStoredIn(DataLocation::CallData) &&
1926 			m_arrayType.isDynamicallySized() &&
1927 			m_arrayType.isImplicitlyConvertibleTo(_other)
1928 		);
1929 }
1930 
isExplicitlyConvertibleTo(Type const & _convertTo) const1931 BoolResult ArraySliceType::isExplicitlyConvertibleTo(Type const& _convertTo) const
1932 {
1933 	return
1934 		isImplicitlyConvertibleTo(_convertTo) ||
1935 		m_arrayType.isExplicitlyConvertibleTo(_convertTo);
1936 }
1937 
richIdentifier() const1938 string ArraySliceType::richIdentifier() const
1939 {
1940 	return m_arrayType.richIdentifier() + "_slice";
1941 }
1942 
operator ==(Type const & _other) const1943 bool ArraySliceType::operator==(Type const& _other) const
1944 {
1945 	if (auto const* other = dynamic_cast<ArraySliceType const*>(&_other))
1946 		return m_arrayType == other->m_arrayType;
1947 	return false;
1948 }
1949 
toString(bool _short) const1950 string ArraySliceType::toString(bool _short) const
1951 {
1952 	return m_arrayType.toString(_short) + " slice";
1953 }
1954 
mobileType() const1955 Type const* ArraySliceType::mobileType() const
1956 {
1957 	if (
1958 		m_arrayType.dataStoredIn(DataLocation::CallData) &&
1959 		m_arrayType.isDynamicallySized() &&
1960 		!m_arrayType.baseType()->isDynamicallyEncoded()
1961 	)
1962 		return &m_arrayType;
1963 	else
1964 		return this;
1965 }
1966 
1967 
makeStackItems() const1968 std::vector<std::tuple<std::string, Type const*>> ArraySliceType::makeStackItems() const
1969 {
1970 	return {{"offset", TypeProvider::uint256()}, {"length", TypeProvider::uint256()}};
1971 }
1972 
richIdentifier() const1973 string ContractType::richIdentifier() const
1974 {
1975 	return (m_super ? "t_super" : "t_contract") + parenthesizeUserIdentifier(m_contract.name()) + to_string(m_contract.id());
1976 }
1977 
operator ==(Type const & _other) const1978 bool ContractType::operator==(Type const& _other) const
1979 {
1980 	if (_other.category() != category())
1981 		return false;
1982 	ContractType const& other = dynamic_cast<ContractType const&>(_other);
1983 	return other.m_contract == m_contract && other.m_super == m_super;
1984 }
1985 
toString(bool) const1986 string ContractType::toString(bool) const
1987 {
1988 	return
1989 		string(m_contract.isLibrary() ? "library " : "contract ") +
1990 		string(m_super ? "super " : "") +
1991 		m_contract.name();
1992 }
1993 
canonicalName() const1994 string ContractType::canonicalName() const
1995 {
1996 	return *m_contract.annotation().canonicalName;
1997 }
1998 
nativeMembers(ASTNode const *) const1999 MemberList::MemberMap ContractType::nativeMembers(ASTNode const*) const
2000 {
2001 	MemberList::MemberMap members;
2002 	solAssert(!m_super, "");
2003 	if (!m_contract.isLibrary())
2004 		for (auto const& it: m_contract.interfaceFunctions())
2005 			members.emplace_back(
2006 				&it.second->declaration(),
2007 				it.second->asExternallyCallableFunction(m_contract.isLibrary())
2008 			);
2009 
2010 	return members;
2011 }
2012 
newExpressionType() const2013 FunctionType const* ContractType::newExpressionType() const
2014 {
2015 	if (!m_constructorType)
2016 		m_constructorType = FunctionType::newExpressionType(m_contract);
2017 	return m_constructorType;
2018 }
2019 
stateVariables() const2020 vector<tuple<VariableDeclaration const*, u256, unsigned>> ContractType::stateVariables() const
2021 {
2022 	vector<VariableDeclaration const*> variables;
2023 	for (ContractDefinition const* contract: m_contract.annotation().linearizedBaseContracts | ranges::views::reverse)
2024 		for (VariableDeclaration const* variable: contract->stateVariables())
2025 			if (!(variable->isConstant() || variable->immutable()))
2026 				variables.push_back(variable);
2027 	TypePointers types;
2028 	for (auto variable: variables)
2029 		types.push_back(variable->annotation().type);
2030 	StorageOffsets offsets;
2031 	offsets.computeOffsets(types);
2032 
2033 	vector<tuple<VariableDeclaration const*, u256, unsigned>> variablesAndOffsets;
2034 	for (size_t index = 0; index < variables.size(); ++index)
2035 		if (auto const* offset = offsets.offset(index))
2036 			variablesAndOffsets.emplace_back(variables[index], offset->first, offset->second);
2037 	return variablesAndOffsets;
2038 }
2039 
immutableVariables() const2040 vector<VariableDeclaration const*> ContractType::immutableVariables() const
2041 {
2042 	vector<VariableDeclaration const*> variables;
2043 	for (ContractDefinition const* contract: m_contract.annotation().linearizedBaseContracts | ranges::views::reverse)
2044 		for (VariableDeclaration const* variable: contract->stateVariables())
2045 			if (variable->immutable())
2046 				variables.push_back(variable);
2047 	return variables;
2048 }
2049 
makeStackItems() const2050 vector<tuple<string, Type const*>> ContractType::makeStackItems() const
2051 {
2052 	if (m_super)
2053 		return {};
2054 	else
2055 		return {make_tuple("address", isPayable() ? TypeProvider::payableAddress() : TypeProvider::address())};
2056 }
2057 
clearCache() const2058 void StructType::clearCache() const
2059 {
2060 	Type::clearCache();
2061 
2062 	m_interfaceType.reset();
2063 	m_interfaceType_library.reset();
2064 }
2065 
encodingType() const2066 Type const* StructType::encodingType() const
2067 {
2068 	if (location() != DataLocation::Storage)
2069 		return this;
2070 
2071 	return TypeProvider::uint256();
2072 }
2073 
isImplicitlyConvertibleTo(Type const & _convertTo) const2074 BoolResult StructType::isImplicitlyConvertibleTo(Type const& _convertTo) const
2075 {
2076 	if (_convertTo.category() != category())
2077 		return false;
2078 	auto& convertTo = dynamic_cast<StructType const&>(_convertTo);
2079 	// memory/calldata to storage can be converted, but only to a direct storage reference
2080 	if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer())
2081 		return false;
2082 	if (convertTo.location() == DataLocation::CallData && location() != convertTo.location())
2083 		return false;
2084 	return this->m_struct == convertTo.m_struct;
2085 }
2086 
richIdentifier() const2087 string StructType::richIdentifier() const
2088 {
2089 	return "t_struct" + parenthesizeUserIdentifier(m_struct.name()) + to_string(m_struct.id()) + identifierLocationSuffix();
2090 }
2091 
operator ==(Type const & _other) const2092 bool StructType::operator==(Type const& _other) const
2093 {
2094 	if (_other.category() != category())
2095 		return false;
2096 	StructType const& other = dynamic_cast<StructType const&>(_other);
2097 	return ReferenceType::operator==(other) && other.m_struct == m_struct;
2098 }
2099 
2100 
calldataEncodedSize(bool) const2101 unsigned StructType::calldataEncodedSize(bool) const
2102 {
2103 	solAssert(!isDynamicallyEncoded(), "");
2104 
2105 	unsigned size = 0;
2106 	for (auto const& member: members(nullptr))
2107 	{
2108 		solAssert(!member.type->containsNestedMapping(), "");
2109 		// Struct members are always padded.
2110 		size += member.type->calldataEncodedSize();
2111 	}
2112 	return size;
2113 }
2114 
2115 
calldataEncodedTailSize() const2116 unsigned StructType::calldataEncodedTailSize() const
2117 {
2118 	solAssert(isDynamicallyEncoded(), "");
2119 
2120 	unsigned size = 0;
2121 	for (auto const& member: members(nullptr))
2122 	{
2123 		solAssert(!member.type->containsNestedMapping(), "");
2124 		// Struct members are always padded.
2125 		size += member.type->calldataHeadSize();
2126 	}
2127 	return size;
2128 }
2129 
calldataOffsetOfMember(std::string const & _member) const2130 unsigned StructType::calldataOffsetOfMember(std::string const& _member) const
2131 {
2132 	unsigned offset = 0;
2133 	for (auto const& member: members(nullptr))
2134 	{
2135 		solAssert(!member.type->containsNestedMapping(), "");
2136 		if (member.name == _member)
2137 			return offset;
2138 		// Struct members are always padded.
2139 		offset += member.type->calldataHeadSize();
2140 	}
2141 	solAssert(false, "Struct member not found.");
2142 }
2143 
isDynamicallyEncoded() const2144 bool StructType::isDynamicallyEncoded() const
2145 {
2146 	if (recursive())
2147 		return true;
2148 	solAssert(interfaceType(false).get(), "");
2149 	for (auto t: memoryMemberTypes())
2150 	{
2151 		solAssert(t, "Parameter should have external type.");
2152 		t = t->interfaceType(false);
2153 		if (t->isDynamicallyEncoded())
2154 			return true;
2155 	}
2156 	return false;
2157 }
2158 
memoryDataSize() const2159 u256 StructType::memoryDataSize() const
2160 {
2161 	u256 size;
2162 	for (auto const& t: memoryMemberTypes())
2163 		size += t->memoryHeadSize();
2164 	return size;
2165 }
2166 
storageSizeUpperBound() const2167 bigint StructType::storageSizeUpperBound() const
2168 {
2169 	bigint size = 1;
2170 	for (auto const& member: members(nullptr))
2171 		size += member.type->storageSizeUpperBound();
2172 	return size;
2173 }
2174 
storageSize() const2175 u256 StructType::storageSize() const
2176 {
2177 	return max<u256>(1, members(nullptr).storageSize());
2178 }
2179 
containsNestedMapping() const2180 bool StructType::containsNestedMapping() const
2181 {
2182 	if (!m_struct.annotation().containsNestedMapping.has_value())
2183 	{
2184 		bool hasNestedMapping = false;
2185 
2186 		util::BreadthFirstSearch<StructDefinition const*> breadthFirstSearch{{&m_struct}};
2187 
2188 		breadthFirstSearch.run(
2189 			[&](StructDefinition const* _struct, auto&& _addChild)
2190 			{
2191 				for (auto const& member: _struct->members())
2192 				{
2193 					Type const* memberType = member->annotation().type;
2194 					solAssert(memberType, "");
2195 
2196 					if (auto arrayType = dynamic_cast<ArrayType const*>(memberType))
2197 						memberType = arrayType->finalBaseType(false);
2198 
2199 					if (dynamic_cast<MappingType const*>(memberType))
2200 					{
2201 						hasNestedMapping = true;
2202 						breadthFirstSearch.abort();
2203 					}
2204 					else if (auto structType = dynamic_cast<StructType const*>(memberType))
2205 						_addChild(&structType->structDefinition());
2206 				}
2207 
2208 			});
2209 
2210 		m_struct.annotation().containsNestedMapping = hasNestedMapping;
2211 	}
2212 
2213 	return m_struct.annotation().containsNestedMapping.value();
2214 }
2215 
toString(bool _short) const2216 string StructType::toString(bool _short) const
2217 {
2218 	string ret = "struct " + *m_struct.annotation().canonicalName;
2219 	if (!_short)
2220 		ret += " " + stringForReferencePart();
2221 	return ret;
2222 }
2223 
nativeMembers(ASTNode const *) const2224 MemberList::MemberMap StructType::nativeMembers(ASTNode const*) const
2225 {
2226 	MemberList::MemberMap members;
2227 	for (ASTPointer<VariableDeclaration> const& variable: m_struct.members())
2228 	{
2229 		Type const* type = variable->annotation().type;
2230 		solAssert(type, "");
2231 		solAssert(!(location() != DataLocation::Storage && type->containsNestedMapping()), "");
2232 		members.emplace_back(
2233 			variable.get(),
2234 			copyForLocationIfReference(type)
2235 		);
2236 	}
2237 	return members;
2238 }
2239 
interfaceType(bool _inLibrary) const2240 TypeResult StructType::interfaceType(bool _inLibrary) const
2241 {
2242 	if (!_inLibrary)
2243 	{
2244 		if (!m_interfaceType.has_value())
2245 		{
2246 			if (recursive())
2247 				m_interfaceType = TypeResult::err("Recursive type not allowed for public or external contract functions.");
2248 			else
2249 			{
2250 				TypeResult result{nullptr};
2251 				for (ASTPointer<VariableDeclaration> const& member: m_struct.members())
2252 				{
2253 					if (!member->annotation().type)
2254 					{
2255 						result = TypeResult::err("Invalid type!");
2256 						break;
2257 					}
2258 					auto interfaceType = member->annotation().type->interfaceType(false);
2259 					if (!interfaceType.get())
2260 					{
2261 						solAssert(!interfaceType.message().empty(), "Expected detailed error message!");
2262 						result = interfaceType;
2263 						break;
2264 					}
2265 				}
2266 				if (result.message().empty())
2267 					m_interfaceType = TypeProvider::withLocation(this, DataLocation::Memory, true);
2268 				else
2269 					m_interfaceType = result;
2270 			}
2271 		}
2272 		return *m_interfaceType;
2273 	}
2274 	else if (m_interfaceType_library.has_value())
2275 		return *m_interfaceType_library;
2276 
2277 	TypeResult result{nullptr};
2278 
2279 	if (recursive() && !(_inLibrary && location() == DataLocation::Storage))
2280 		return TypeResult::err(
2281 			"Recursive structs can only be passed as storage pointers to libraries, "
2282 			"not as memory objects to contract functions."
2283 		);
2284 
2285 	util::BreadthFirstSearch<StructDefinition const*> breadthFirstSearch{{&m_struct}};
2286 	breadthFirstSearch.run(
2287 		[&](StructDefinition const* _struct, auto&& _addChild)
2288 		{
2289 			// Check that all members have interface types.
2290 			// Return an error if at least one struct member does not have a type.
2291 			// This might happen, for example, if the type of the member does not exist.
2292 			for (ASTPointer<VariableDeclaration> const& variable: _struct->members())
2293 			{
2294 				// If the struct member does not have a type return false.
2295 				// A TypeError is expected in this case.
2296 				if (!variable->annotation().type)
2297 				{
2298 					result = TypeResult::err("Invalid type!");
2299 					breadthFirstSearch.abort();
2300 					return;
2301 				}
2302 
2303 				Type const* memberType = variable->annotation().type;
2304 
2305 				while (
2306 					memberType->category() == Type::Category::Array ||
2307 					memberType->category() == Type::Category::Mapping
2308 				)
2309 				{
2310 					if (auto arrayType = dynamic_cast<ArrayType const*>(memberType))
2311 						memberType = arrayType->finalBaseType(false);
2312 					else if (auto mappingType = dynamic_cast<MappingType const*>(memberType))
2313 						memberType = mappingType->valueType();
2314 				}
2315 
2316 				if (StructType const* innerStruct = dynamic_cast<StructType const*>(memberType))
2317 					_addChild(&innerStruct->structDefinition());
2318 				else
2319 				{
2320 					auto iType = memberType->interfaceType(_inLibrary);
2321 					if (!iType.get())
2322 					{
2323 						solAssert(!iType.message().empty(), "Expected detailed error message!");
2324 						result = iType;
2325 						breadthFirstSearch.abort();
2326 						return;
2327 					}
2328 				}
2329 			}
2330 		}
2331 	);
2332 
2333 	if (!result.message().empty())
2334 		return result;
2335 
2336 	if (location() == DataLocation::Storage)
2337 		m_interfaceType_library = this;
2338 	else
2339 		m_interfaceType_library = TypeProvider::withLocation(this, DataLocation::Memory, true);
2340 	return *m_interfaceType_library;
2341 }
2342 
validForLocation(DataLocation _loc) const2343 BoolResult StructType::validForLocation(DataLocation _loc) const
2344 {
2345 	for (auto const& member: m_struct.members())
2346 		if (auto referenceType = dynamic_cast<ReferenceType const*>(member->annotation().type))
2347 		{
2348 			BoolResult result = referenceType->validForLocation(_loc);
2349 			if (!result)
2350 				return result;
2351 		}
2352 
2353 	if (
2354 		_loc == DataLocation::Storage &&
2355 		storageSizeUpperBound() >= bigint(1) << 256
2356 	)
2357 		return BoolResult::err("Type too large for storage.");
2358 
2359 	return true;
2360 }
2361 
recursive() const2362 bool StructType::recursive() const
2363 {
2364 	solAssert(m_struct.annotation().recursive.has_value(), "Called StructType::recursive() before DeclarationTypeChecker.");
2365 	return *m_struct.annotation().recursive;
2366 }
2367 
copyForLocation(DataLocation _location,bool _isPointer) const2368 std::unique_ptr<ReferenceType> StructType::copyForLocation(DataLocation _location, bool _isPointer) const
2369 {
2370 	auto copy = make_unique<StructType>(m_struct, _location);
2371 	if (_location == DataLocation::Storage)
2372 		copy->m_isPointer = _isPointer;
2373 	return copy;
2374 }
2375 
signatureInExternalFunction(bool _structsByName) const2376 string StructType::signatureInExternalFunction(bool _structsByName) const
2377 {
2378 	if (_structsByName)
2379 		return canonicalName();
2380 	else
2381 	{
2382 		TypePointers memberTypes = memoryMemberTypes();
2383 		auto memberTypeStrings = memberTypes | ranges::views::transform([&](Type const* _t) -> string
2384 		{
2385 			solAssert(_t, "Parameter should have external type.");
2386 			auto t = _t->interfaceType(_structsByName);
2387 			solAssert(t.get(), "");
2388 			return t.get()->signatureInExternalFunction(_structsByName);
2389 		});
2390 		return "(" + boost::algorithm::join(memberTypeStrings, ",") + ")";
2391 	}
2392 }
2393 
canonicalName() const2394 string StructType::canonicalName() const
2395 {
2396 	return *m_struct.annotation().canonicalName;
2397 }
2398 
constructorType() const2399 FunctionTypePointer StructType::constructorType() const
2400 {
2401 	TypePointers paramTypes;
2402 	strings paramNames;
2403 	solAssert(!containsNestedMapping(), "");
2404 	for (auto const& member: members(nullptr))
2405 	{
2406 		paramNames.push_back(member.name);
2407 		paramTypes.push_back(TypeProvider::withLocationIfReference(DataLocation::Memory, member.type));
2408 	}
2409 	return TypeProvider::function(
2410 		paramTypes,
2411 		TypePointers{TypeProvider::withLocation(this, DataLocation::Memory, false)},
2412 		paramNames,
2413 		strings(1, ""),
2414 		FunctionType::Kind::Internal
2415 	);
2416 }
2417 
storageOffsetsOfMember(string const & _name) const2418 pair<u256, unsigned> const& StructType::storageOffsetsOfMember(string const& _name) const
2419 {
2420 	auto const* offsets = members(nullptr).memberStorageOffset(_name);
2421 	solAssert(offsets, "Storage offset of non-existing member requested.");
2422 	return *offsets;
2423 }
2424 
memoryOffsetOfMember(string const & _name) const2425 u256 StructType::memoryOffsetOfMember(string const& _name) const
2426 {
2427 	u256 offset;
2428 	for (auto const& member: members(nullptr))
2429 		if (member.name == _name)
2430 			return offset;
2431 		else
2432 			offset += member.type->memoryHeadSize();
2433 	solAssert(false, "Member not found in struct.");
2434 	return 0;
2435 }
2436 
memoryMemberTypes() const2437 TypePointers StructType::memoryMemberTypes() const
2438 {
2439 	solAssert(!containsNestedMapping(), "");
2440 	TypePointers types;
2441 	for (ASTPointer<VariableDeclaration> const& variable: m_struct.members())
2442 		types.push_back(TypeProvider::withLocationIfReference(DataLocation::Memory, variable->annotation().type));
2443 
2444 	return types;
2445 }
2446 
makeStackItems() const2447 vector<tuple<string, Type const*>> StructType::makeStackItems() const
2448 {
2449 	switch (m_location)
2450 	{
2451 		case DataLocation::CallData:
2452 			return {std::make_tuple("offset", TypeProvider::uint256())};
2453 		case DataLocation::Memory:
2454 			return {std::make_tuple("mpos", TypeProvider::uint256())};
2455 		case DataLocation::Storage:
2456 			return {std::make_tuple("slot", TypeProvider::uint256())};
2457 	}
2458 	solAssert(false, "");
2459 }
2460 
decomposition() const2461 vector<Type const*> StructType::decomposition() const
2462 {
2463 	vector<Type const*> res;
2464 	for (MemberList::Member const& member: members(nullptr))
2465 		res.push_back(member.type);
2466 	return res;
2467 }
2468 
encodingType() const2469 Type const* EnumType::encodingType() const
2470 {
2471 	solAssert(numberOfMembers() <= 256, "");
2472 	return TypeProvider::uint(8);
2473 }
2474 
unaryOperatorResult(Token _operator) const2475 TypeResult EnumType::unaryOperatorResult(Token _operator) const
2476 {
2477 	return _operator == Token::Delete ? TypeProvider::emptyTuple() : nullptr;
2478 }
2479 
richIdentifier() const2480 string EnumType::richIdentifier() const
2481 {
2482 	return "t_enum" + parenthesizeUserIdentifier(m_enum.name()) + to_string(m_enum.id());
2483 }
2484 
operator ==(Type const & _other) const2485 bool EnumType::operator==(Type const& _other) const
2486 {
2487 	if (_other.category() != category())
2488 		return false;
2489 	EnumType const& other = dynamic_cast<EnumType const&>(_other);
2490 	return other.m_enum == m_enum;
2491 }
2492 
storageBytes() const2493 unsigned EnumType::storageBytes() const
2494 {
2495 	solAssert(numberOfMembers() <= 256, "");
2496 	return 1;
2497 }
2498 
toString(bool) const2499 string EnumType::toString(bool) const
2500 {
2501 	return string("enum ") + *m_enum.annotation().canonicalName;
2502 }
2503 
canonicalName() const2504 string EnumType::canonicalName() const
2505 {
2506 	return *m_enum.annotation().canonicalName;
2507 }
2508 
numberOfMembers() const2509 size_t EnumType::numberOfMembers() const
2510 {
2511 	return m_enum.members().size();
2512 }
2513 
isExplicitlyConvertibleTo(Type const & _convertTo) const2514 BoolResult EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
2515 {
2516 	if (_convertTo == *this)
2517 		return true;
2518 	else if (auto integerType = dynamic_cast<IntegerType const*>(&_convertTo))
2519 		return !integerType->isSigned();
2520 	return false;
2521 }
2522 
memberValue(ASTString const & _member) const2523 unsigned EnumType::memberValue(ASTString const& _member) const
2524 {
2525 	unsigned index = 0;
2526 	for (ASTPointer<EnumValue> const& decl: m_enum.members())
2527 	{
2528 		if (decl->name() == _member)
2529 			return index;
2530 		++index;
2531 	}
2532 	solAssert(false, "Requested unknown enum value " + _member);
2533 }
2534 
underlyingType() const2535 Type const& UserDefinedValueType::underlyingType() const
2536 {
2537 	Type const* type = m_definition.underlyingType()->annotation().type;
2538 	solAssert(type, "");
2539 	solAssert(type->category() != Category::UserDefinedValueType, "");
2540 	return *type;
2541 }
2542 
richIdentifier() const2543 string UserDefinedValueType::richIdentifier() const
2544 {
2545 	return "t_userDefinedValueType" + parenthesizeIdentifier(m_definition.name()) + to_string(m_definition.id());
2546 }
2547 
operator ==(Type const & _other) const2548 bool UserDefinedValueType::operator==(Type const& _other) const
2549 {
2550 	if (_other.category() != category())
2551 		return false;
2552 	UserDefinedValueType const& other = dynamic_cast<UserDefinedValueType const&>(_other);
2553 	return other.definition() == definition();
2554 }
2555 
toString(bool) const2556 string UserDefinedValueType::toString(bool /* _short */) const
2557 {
2558 	return *definition().annotation().canonicalName;
2559 }
2560 
canonicalName() const2561 string UserDefinedValueType::canonicalName() const
2562 {
2563 	return *definition().annotation().canonicalName;
2564 }
2565 
makeStackItems() const2566 vector<tuple<string, Type const*>> UserDefinedValueType::makeStackItems() const
2567 {
2568 	return underlyingType().stackItems();
2569 }
2570 
isImplicitlyConvertibleTo(Type const & _other) const2571 BoolResult TupleType::isImplicitlyConvertibleTo(Type const& _other) const
2572 {
2573 	if (auto tupleType = dynamic_cast<TupleType const*>(&_other))
2574 	{
2575 		TypePointers const& targets = tupleType->components();
2576 		if (targets.empty())
2577 			return components().empty();
2578 		if (components().size() != targets.size())
2579 			return false;
2580 		for (size_t i = 0; i < targets.size(); ++i)
2581 			if (!components()[i] && targets[i])
2582 				return false;
2583 			else if (components()[i] && targets[i] && !components()[i]->isImplicitlyConvertibleTo(*targets[i]))
2584 				return false;
2585 		return true;
2586 	}
2587 	else
2588 		return false;
2589 }
2590 
richIdentifier() const2591 string TupleType::richIdentifier() const
2592 {
2593 	return "t_tuple" + identifierList(components());
2594 }
2595 
operator ==(Type const & _other) const2596 bool TupleType::operator==(Type const& _other) const
2597 {
2598 	if (auto tupleType = dynamic_cast<TupleType const*>(&_other))
2599 		return components() == tupleType->components();
2600 	else
2601 		return false;
2602 }
2603 
toString(bool _short) const2604 string TupleType::toString(bool _short) const
2605 {
2606 	if (components().empty())
2607 		return "tuple()";
2608 	string str = "tuple(";
2609 	for (auto const& t: components())
2610 		str += (t ? t->toString(_short) : "") + ",";
2611 	str.pop_back();
2612 	return str + ")";
2613 }
2614 
storageSize() const2615 u256 TupleType::storageSize() const
2616 {
2617 	solAssert(false, "Storage size of non-storable tuple type requested.");
2618 }
2619 
makeStackItems() const2620 vector<tuple<string, Type const*>> TupleType::makeStackItems() const
2621 {
2622 	vector<tuple<string, Type const*>> slots;
2623 	unsigned i = 1;
2624 	for (auto const& t: components())
2625 	{
2626 		if (t)
2627 			slots.emplace_back("component_" + std::to_string(i), t);
2628 		++i;
2629 	}
2630 	return slots;
2631 }
2632 
mobileType() const2633 Type const* TupleType::mobileType() const
2634 {
2635 	TypePointers mobiles;
2636 	for (auto const& c: components())
2637 	{
2638 		if (c)
2639 		{
2640 			auto mt = c->mobileType();
2641 			if (!mt)
2642 				return nullptr;
2643 			mobiles.push_back(mt);
2644 		}
2645 		else
2646 			mobiles.push_back(nullptr);
2647 	}
2648 	return TypeProvider::tuple(move(mobiles));
2649 }
2650 
FunctionType(FunctionDefinition const & _function,Kind _kind)2651 FunctionType::FunctionType(FunctionDefinition const& _function, Kind _kind):
2652 	m_kind(_kind),
2653 	m_stateMutability(_function.stateMutability()),
2654 	m_declaration(&_function)
2655 {
2656 	solAssert(
2657 		_kind == Kind::Internal || _kind == Kind::External || _kind == Kind::Declaration,
2658 		"Only internal or external function types or function declaration types can be created from function definitions."
2659 	);
2660 	if (_kind == Kind::Internal && m_stateMutability == StateMutability::Payable)
2661 		m_stateMutability = StateMutability::NonPayable;
2662 
2663 	for (ASTPointer<VariableDeclaration> const& var: _function.parameters())
2664 	{
2665 		solAssert(var->annotation().type, "Parameter type is not yet available in the AST.");
2666 		m_parameterNames.push_back(var->name());
2667 		m_parameterTypes.push_back(var->annotation().type);
2668 	}
2669 	for (ASTPointer<VariableDeclaration> const& var: _function.returnParameters())
2670 	{
2671 		solAssert(var->annotation().type, "Return parameter type is not yet available in the AST.");
2672 		m_returnParameterNames.push_back(var->name());
2673 		m_returnParameterTypes.push_back(var->annotation().type);
2674 	}
2675 
2676 	solAssert(
2677 		m_parameterNames.size() == m_parameterTypes.size(),
2678 		"Parameter names list must match parameter types list!"
2679 	);
2680 
2681 	solAssert(
2682 		m_returnParameterNames.size() == m_returnParameterTypes.size(),
2683 		"Return parameter names list must match return parameter types list!"
2684 	);
2685 }
2686 
FunctionType(VariableDeclaration const & _varDecl)2687 FunctionType::FunctionType(VariableDeclaration const& _varDecl):
2688 	m_kind(Kind::External),
2689 	m_stateMutability(StateMutability::View),
2690 	m_declaration(&_varDecl)
2691 {
2692 	auto returnType = _varDecl.annotation().type;
2693 
2694 	while (true)
2695 	{
2696 		if (auto mappingType = dynamic_cast<MappingType const*>(returnType))
2697 		{
2698 			m_parameterTypes.push_back(mappingType->keyType());
2699 			m_parameterNames.emplace_back("");
2700 			returnType = mappingType->valueType();
2701 		}
2702 		else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
2703 		{
2704 			if (arrayType->isByteArray())
2705 				// Return byte arrays as whole.
2706 				break;
2707 			returnType = arrayType->baseType();
2708 			m_parameterNames.emplace_back("");
2709 			m_parameterTypes.push_back(TypeProvider::uint256());
2710 		}
2711 		else
2712 			break;
2713 	}
2714 
2715 	if (auto structType = dynamic_cast<StructType const*>(returnType))
2716 	{
2717 		for (auto const& member: structType->members(nullptr))
2718 		{
2719 			solAssert(member.type, "");
2720 			if (member.type->category() != Category::Mapping)
2721 			{
2722 				if (auto arrayType = dynamic_cast<ArrayType const*>(member.type))
2723 					if (!arrayType->isByteArray())
2724 						continue;
2725 				m_returnParameterTypes.push_back(TypeProvider::withLocationIfReference(
2726 					DataLocation::Memory,
2727 					member.type
2728 				));
2729 				m_returnParameterNames.push_back(member.name);
2730 			}
2731 		}
2732 	}
2733 	else
2734 	{
2735 		m_returnParameterTypes.push_back(TypeProvider::withLocationIfReference(
2736 			DataLocation::Memory,
2737 			returnType
2738 		));
2739 		m_returnParameterNames.emplace_back("");
2740 	}
2741 
2742 	solAssert(
2743 			m_parameterNames.size() == m_parameterTypes.size(),
2744 			"Parameter names list must match parameter types list!"
2745 			);
2746 	solAssert(
2747 			m_returnParameterNames.size() == m_returnParameterTypes.size(),
2748 			"Return parameter names list must match return parameter types list!"
2749 			);
2750 }
2751 
FunctionType(EventDefinition const & _event)2752 FunctionType::FunctionType(EventDefinition const& _event):
2753 	m_kind(Kind::Event),
2754 	m_stateMutability(StateMutability::NonPayable),
2755 	m_declaration(&_event)
2756 {
2757 	for (ASTPointer<VariableDeclaration> const& var: _event.parameters())
2758 	{
2759 		m_parameterNames.push_back(var->name());
2760 		m_parameterTypes.push_back(var->annotation().type);
2761 	}
2762 
2763 	solAssert(
2764 		m_parameterNames.size() == m_parameterTypes.size(),
2765 		"Parameter names list must match parameter types list!"
2766 	);
2767 	solAssert(
2768 		m_returnParameterNames.size() == 0 &&
2769 		m_returnParameterTypes.size() == 0,
2770 		""
2771 	);
2772 }
2773 
FunctionType(ErrorDefinition const & _error)2774 FunctionType::FunctionType(ErrorDefinition const& _error):
2775 	m_kind(Kind::Error),
2776 	m_stateMutability(StateMutability::Pure),
2777 	m_declaration(&_error)
2778 {
2779 	for (ASTPointer<VariableDeclaration> const& var: _error.parameters())
2780 	{
2781 		m_parameterNames.push_back(var->name());
2782 		m_parameterTypes.push_back(var->annotation().type);
2783 	}
2784 
2785 	solAssert(
2786 		m_parameterNames.size() == m_parameterTypes.size(),
2787 		"Parameter names list must match parameter types list!"
2788 	);
2789 	solAssert(
2790 		m_returnParameterNames.size() == 0 &&
2791 		m_returnParameterTypes.size() == 0,
2792 		""
2793 	);
2794 }
2795 
FunctionType(FunctionTypeName const & _typeName)2796 FunctionType::FunctionType(FunctionTypeName const& _typeName):
2797 	m_parameterNames(_typeName.parameterTypes().size(), ""),
2798 	m_returnParameterNames(_typeName.returnParameterTypes().size(), ""),
2799 	m_kind(_typeName.visibility() == Visibility::External ? Kind::External : Kind::Internal),
2800 	m_stateMutability(_typeName.stateMutability())
2801 {
2802 	if (_typeName.isPayable())
2803 		solAssert(m_kind == Kind::External, "Internal payable function type used.");
2804 	for (auto const& t: _typeName.parameterTypes())
2805 	{
2806 		solAssert(t->annotation().type, "Type not set for parameter.");
2807 		m_parameterTypes.push_back(t->annotation().type);
2808 	}
2809 	for (auto const& t: _typeName.returnParameterTypes())
2810 	{
2811 		solAssert(t->annotation().type, "Type not set for return parameter.");
2812 		m_returnParameterTypes.push_back(t->annotation().type);
2813 	}
2814 
2815 	solAssert(
2816 			m_parameterNames.size() == m_parameterTypes.size(),
2817 			"Parameter names list must match parameter types list!"
2818 			);
2819 	solAssert(
2820 			m_returnParameterNames.size() == m_returnParameterTypes.size(),
2821 			"Return parameter names list must match return parameter types list!"
2822 			);
2823 }
2824 
newExpressionType(ContractDefinition const & _contract)2825 FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _contract)
2826 {
2827 	FunctionDefinition const* constructor = _contract.constructor();
2828 	TypePointers parameters;
2829 	strings parameterNames;
2830 	StateMutability stateMutability = StateMutability::NonPayable;
2831 
2832 	solAssert(!_contract.isInterface(), "");
2833 
2834 	if (constructor)
2835 	{
2836 		for (ASTPointer<VariableDeclaration> const& var: constructor->parameters())
2837 		{
2838 			parameterNames.push_back(var->name());
2839 			parameters.push_back(var->annotation().type);
2840 		}
2841 		if (constructor->isPayable())
2842 			stateMutability = StateMutability::Payable;
2843 	}
2844 
2845 	return TypeProvider::function(
2846 		parameters,
2847 		TypePointers{TypeProvider::contract(_contract)},
2848 		parameterNames,
2849 		strings{""},
2850 		Kind::Creation,
2851 		false,
2852 		stateMutability
2853 	);
2854 }
2855 
parameterNames() const2856 vector<string> FunctionType::parameterNames() const
2857 {
2858 	if (!bound())
2859 		return m_parameterNames;
2860 	return vector<string>(m_parameterNames.cbegin() + 1, m_parameterNames.cend());
2861 }
2862 
returnParameterTypesWithoutDynamicTypes() const2863 TypePointers FunctionType::returnParameterTypesWithoutDynamicTypes() const
2864 {
2865 	TypePointers returnParameterTypes = m_returnParameterTypes;
2866 
2867 	if (
2868 		m_kind == Kind::External ||
2869 		m_kind == Kind::DelegateCall ||
2870 		m_kind == Kind::BareCall ||
2871 		m_kind == Kind::BareCallCode ||
2872 		m_kind == Kind::BareDelegateCall ||
2873 		m_kind == Kind::BareStaticCall
2874 	)
2875 		for (auto& param: returnParameterTypes)
2876 		{
2877 			solAssert(param->decodingType(), "");
2878 			if (param->decodingType()->isDynamicallyEncoded())
2879 				param = TypeProvider::inaccessibleDynamic();
2880 		}
2881 
2882 	return returnParameterTypes;
2883 }
2884 
parameterTypes() const2885 TypePointers FunctionType::parameterTypes() const
2886 {
2887 	if (!bound())
2888 		return m_parameterTypes;
2889 	return TypePointers(m_parameterTypes.cbegin() + 1, m_parameterTypes.cend());
2890 }
2891 
parameterTypesIncludingSelf() const2892 TypePointers const& FunctionType::parameterTypesIncludingSelf() const
2893 {
2894 	return m_parameterTypes;
2895 }
2896 
richIdentifier() const2897 string FunctionType::richIdentifier() const
2898 {
2899 	string id = "t_function_";
2900 	switch (m_kind)
2901 	{
2902 	case Kind::Declaration: id += "declaration"; break;
2903 	case Kind::Internal: id += "internal"; break;
2904 	case Kind::External: id += "external"; break;
2905 	case Kind::DelegateCall: id += "delegatecall"; break;
2906 	case Kind::BareCall: id += "barecall"; break;
2907 	case Kind::BareCallCode: id += "barecallcode"; break;
2908 	case Kind::BareDelegateCall: id += "baredelegatecall"; break;
2909 	case Kind::BareStaticCall: id += "barestaticcall"; break;
2910 	case Kind::Creation: id += "creation"; break;
2911 	case Kind::Send: id += "send"; break;
2912 	case Kind::Transfer: id += "transfer"; break;
2913 	case Kind::KECCAK256: id += "keccak256"; break;
2914 	case Kind::Selfdestruct: id += "selfdestruct"; break;
2915 	case Kind::Revert: id += "revert"; break;
2916 	case Kind::ECRecover: id += "ecrecover"; break;
2917 	case Kind::SHA256: id += "sha256"; break;
2918 	case Kind::RIPEMD160: id += "ripemd160"; break;
2919 	case Kind::GasLeft: id += "gasleft"; break;
2920 	case Kind::Event: id += "event"; break;
2921 	case Kind::Error: id += "error"; break;
2922 	case Kind::Wrap: id += "wrap"; break;
2923 	case Kind::Unwrap: id += "unwrap"; break;
2924 	case Kind::SetGas: id += "setgas"; break;
2925 	case Kind::SetValue: id += "setvalue"; break;
2926 	case Kind::BlockHash: id += "blockhash"; break;
2927 	case Kind::AddMod: id += "addmod"; break;
2928 	case Kind::MulMod: id += "mulmod"; break;
2929 	case Kind::ArrayPush: id += "arraypush"; break;
2930 	case Kind::ArrayPop: id += "arraypop"; break;
2931 	case Kind::BytesConcat: id += "bytesconcat"; break;
2932 	case Kind::ObjectCreation: id += "objectcreation"; break;
2933 	case Kind::Assert: id += "assert"; break;
2934 	case Kind::Require: id += "require"; break;
2935 	case Kind::ABIEncode: id += "abiencode"; break;
2936 	case Kind::ABIEncodePacked: id += "abiencodepacked"; break;
2937 	case Kind::ABIEncodeWithSelector: id += "abiencodewithselector"; break;
2938 	case Kind::ABIEncodeCall: id += "abiencodecall"; break;
2939 	case Kind::ABIEncodeWithSignature: id += "abiencodewithsignature"; break;
2940 	case Kind::ABIDecode: id += "abidecode"; break;
2941 	case Kind::MetaType: id += "metatype"; break;
2942 	}
2943 	id += "_" + stateMutabilityToString(m_stateMutability);
2944 	id += identifierList(m_parameterTypes) + "returns" + identifierList(m_returnParameterTypes);
2945 	if (m_gasSet)
2946 		id += "gas";
2947 	if (m_valueSet)
2948 		id += "value";
2949 	if (m_saltSet)
2950 		id += "salt";
2951 	if (bound())
2952 		id += "bound_to" + identifierList(selfType());
2953 	return id;
2954 }
2955 
operator ==(Type const & _other) const2956 bool FunctionType::operator==(Type const& _other) const
2957 {
2958 	if (_other.category() != category())
2959 		return false;
2960 	FunctionType const& other = dynamic_cast<FunctionType const&>(_other);
2961 	if (!equalExcludingStateMutability(other))
2962 		return false;
2963 	if (m_stateMutability != other.stateMutability())
2964 		return false;
2965 	return true;
2966 }
2967 
isExplicitlyConvertibleTo(Type const & _convertTo) const2968 BoolResult FunctionType::isExplicitlyConvertibleTo(Type const& _convertTo) const
2969 {
2970 	if (_convertTo.category() == category())
2971 	{
2972 		auto const& convertToType = dynamic_cast<FunctionType const&>(_convertTo);
2973 		return (m_kind == FunctionType::Kind::Declaration) == (convertToType.kind() == FunctionType::Kind::Declaration);
2974 	}
2975 	return false;
2976 }
2977 
isImplicitlyConvertibleTo(Type const & _convertTo) const2978 BoolResult FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const
2979 {
2980 	if (_convertTo.category() != category())
2981 		return false;
2982 
2983 	FunctionType const& convertTo = dynamic_cast<FunctionType const&>(_convertTo);
2984 
2985 	// These two checks are duplicated in equalExcludingStateMutability, but are added here for error reporting.
2986 	if (convertTo.bound() != bound())
2987 		return BoolResult::err("Bound functions can not be converted to non-bound functions.");
2988 
2989 	if (convertTo.kind() != kind())
2990 		return BoolResult::err("Special functions can not be converted to function types.");
2991 
2992 	if (!equalExcludingStateMutability(convertTo))
2993 		return false;
2994 
2995 	// non-payable should not be convertible to payable
2996 	if (m_stateMutability != StateMutability::Payable && convertTo.stateMutability() == StateMutability::Payable)
2997 		return false;
2998 
2999 	// payable should be convertible to non-payable, because you are free to pay 0 ether
3000 	if (m_stateMutability == StateMutability::Payable && convertTo.stateMutability() == StateMutability::NonPayable)
3001 		return true;
3002 
3003 	// e.g. pure should be convertible to view, but not the other way around.
3004 	if (m_stateMutability > convertTo.stateMutability())
3005 		return false;
3006 
3007 	return true;
3008 }
3009 
unaryOperatorResult(Token _operator) const3010 TypeResult FunctionType::unaryOperatorResult(Token _operator) const
3011 {
3012 	if (_operator == Token::Delete)
3013 		return TypeResult(TypeProvider::emptyTuple());
3014 	return nullptr;
3015 }
3016 
binaryOperatorResult(Token _operator,Type const * _other) const3017 TypeResult FunctionType::binaryOperatorResult(Token _operator, Type const* _other) const
3018 {
3019 	if (_other->category() != category() || !(_operator == Token::Equal || _operator == Token::NotEqual))
3020 		return nullptr;
3021 	FunctionType const& other = dynamic_cast<FunctionType const&>(*_other);
3022 	if (kind() == Kind::Internal && other.kind() == Kind::Internal && sizeOnStack() == 1 && other.sizeOnStack() == 1)
3023 		return commonType(this, _other);
3024 	return nullptr;
3025 }
3026 
canonicalName() const3027 string FunctionType::canonicalName() const
3028 {
3029 	solAssert(m_kind == Kind::External, "");
3030 	return "function";
3031 }
3032 
toString(bool _short) const3033 string FunctionType::toString(bool _short) const
3034 {
3035 	string name = "function ";
3036 	if (m_kind == Kind::Declaration)
3037 	{
3038 		auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(m_declaration);
3039 		solAssert(functionDefinition, "");
3040 		if (auto const* contract = dynamic_cast<ContractDefinition const*>(functionDefinition->scope()))
3041 			name += *contract->annotation().canonicalName + ".";
3042 		name += functionDefinition->name();
3043 	}
3044 	name += '(';
3045 	for (auto it = m_parameterTypes.begin(); it != m_parameterTypes.end(); ++it)
3046 		name += (*it)->toString(_short) + (it + 1 == m_parameterTypes.end() ? "" : ",");
3047 	name += ")";
3048 	if (m_stateMutability != StateMutability::NonPayable)
3049 		name += " " + stateMutabilityToString(m_stateMutability);
3050 	if (m_kind == Kind::External)
3051 		name += " external";
3052 	if (!m_returnParameterTypes.empty())
3053 	{
3054 		name += " returns (";
3055 		for (auto it = m_returnParameterTypes.begin(); it != m_returnParameterTypes.end(); ++it)
3056 			name += (*it)->toString(_short) + (it + 1 == m_returnParameterTypes.end() ? "" : ",");
3057 		name += ")";
3058 	}
3059 	return name;
3060 }
3061 
calldataEncodedSize(bool _padded) const3062 unsigned FunctionType::calldataEncodedSize(bool _padded) const
3063 {
3064 	unsigned size = storageBytes();
3065 	if (_padded)
3066 		size = ((size + 31) / 32) * 32;
3067 	return size;
3068 }
3069 
storageSize() const3070 u256 FunctionType::storageSize() const
3071 {
3072 	if (m_kind == Kind::External || m_kind == Kind::Internal)
3073 		return 1;
3074 	else
3075 		solAssert(false, "Storage size of non-storable function type requested.");
3076 }
3077 
leftAligned() const3078 bool FunctionType::leftAligned() const
3079 {
3080 	return m_kind == Kind::External;
3081 }
3082 
storageBytes() const3083 unsigned FunctionType::storageBytes() const
3084 {
3085 	if (m_kind == Kind::External)
3086 		return 20 + 4;
3087 	else if (m_kind == Kind::Internal)
3088 		return 8; // it should really not be possible to create larger programs
3089 	else
3090 		solAssert(false, "Storage size of non-storable function type requested.");
3091 }
3092 
nameable() const3093 bool FunctionType::nameable() const
3094 {
3095 	return
3096 		(m_kind == Kind::Internal || m_kind == Kind::External) &&
3097 		!m_bound &&
3098 		!m_arbitraryParameters &&
3099 		!m_gasSet &&
3100 		!m_valueSet &&
3101 		!m_saltSet;
3102 }
3103 
makeStackItems() const3104 vector<tuple<string, Type const*>> FunctionType::makeStackItems() const
3105 {
3106 	vector<tuple<string, Type const*>> slots;
3107 	Kind kind = m_kind;
3108 	if (m_kind == Kind::SetGas || m_kind == Kind::SetValue)
3109 	{
3110 		solAssert(m_returnParameterTypes.size() == 1, "");
3111 		kind = dynamic_cast<FunctionType const&>(*m_returnParameterTypes.front()).m_kind;
3112 	}
3113 
3114 	switch (kind)
3115 	{
3116 	case Kind::External:
3117 	case Kind::DelegateCall:
3118 		slots = {
3119 			make_tuple("address", TypeProvider::address()),
3120 			make_tuple("functionSelector", TypeProvider::uint(32))
3121 		};
3122 		break;
3123 	case Kind::BareCall:
3124 	case Kind::BareCallCode:
3125 	case Kind::BareDelegateCall:
3126 	case Kind::BareStaticCall:
3127 	case Kind::Transfer:
3128 	case Kind::Send:
3129 		slots = {make_tuple("address", TypeProvider::address())};
3130 		break;
3131 	case Kind::Internal:
3132 		slots = {make_tuple("functionIdentifier", TypeProvider::uint256())};
3133 		break;
3134 	case Kind::ArrayPush:
3135 	case Kind::ArrayPop:
3136 		solAssert(bound(), "");
3137 		slots = {};
3138 		break;
3139 	default:
3140 		break;
3141 	}
3142 
3143 	if (m_gasSet)
3144 		slots.emplace_back("gas", TypeProvider::uint256());
3145 	if (m_valueSet)
3146 		slots.emplace_back("value", TypeProvider::uint256());
3147 	if (m_saltSet)
3148 		slots.emplace_back("salt", TypeProvider::fixedBytes(32));
3149 	if (bound())
3150 		slots.emplace_back("self", m_parameterTypes.front());
3151 	return slots;
3152 }
3153 
interfaceFunctionType() const3154 FunctionTypePointer FunctionType::interfaceFunctionType() const
3155 {
3156 	// Note that m_declaration might also be a state variable!
3157 	solAssert(m_declaration, "Declaration needed to determine interface function type.");
3158 	bool isLibraryFunction = false;
3159 	if (kind() != Kind::Event && kind() != Kind::Error)
3160 		if (auto const* contract = dynamic_cast<ContractDefinition const*>(m_declaration->scope()))
3161 			isLibraryFunction = contract->isLibrary();
3162 
3163 	util::Result<TypePointers> paramTypes =
3164 		transformParametersToExternal(m_parameterTypes, isLibraryFunction);
3165 
3166 	if (!paramTypes.message().empty())
3167 		return FunctionTypePointer();
3168 
3169 	util::Result<TypePointers> retParamTypes =
3170 		transformParametersToExternal(m_returnParameterTypes, isLibraryFunction);
3171 
3172 	if (!retParamTypes.message().empty())
3173 		return FunctionTypePointer();
3174 
3175 	auto variable = dynamic_cast<VariableDeclaration const*>(m_declaration);
3176 	if (variable && retParamTypes.get().empty())
3177 		return FunctionTypePointer();
3178 
3179 	return TypeProvider::function(
3180 		paramTypes,
3181 		retParamTypes,
3182 		m_parameterNames,
3183 		m_returnParameterNames,
3184 		m_kind,
3185 		m_arbitraryParameters,
3186 		m_stateMutability,
3187 		m_declaration
3188 	);
3189 }
3190 
nativeMembers(ASTNode const * _scope) const3191 MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const
3192 {
3193 	switch (m_kind)
3194 	{
3195 	case Kind::Declaration:
3196 		if (declaration().isPartOfExternalInterface())
3197 			return {{"selector", TypeProvider::fixedBytes(4)}};
3198 		else
3199 			return MemberList::MemberMap();
3200 	case Kind::Internal:
3201 		if (
3202 			auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(m_declaration);
3203 			functionDefinition &&
3204 			_scope &&
3205 			functionDefinition->annotation().contract &&
3206 			_scope != functionDefinition->annotation().contract &&
3207 			functionDefinition->isPartOfExternalInterface()
3208 		)
3209 		{
3210 			auto const* contractScope = dynamic_cast<ContractDefinition const*>(_scope);
3211 			solAssert(contractScope && contractScope->derivesFrom(*functionDefinition->annotation().contract), "");
3212 			return {{"selector", TypeProvider::fixedBytes(4)}};
3213 		}
3214 		else
3215 			return MemberList::MemberMap();
3216 	case Kind::External:
3217 	case Kind::Creation:
3218 	case Kind::BareCall:
3219 	case Kind::BareCallCode:
3220 	case Kind::BareDelegateCall:
3221 	case Kind::BareStaticCall:
3222 	{
3223 		MemberList::MemberMap members;
3224 		if (m_kind == Kind::External)
3225 		{
3226 			members.emplace_back("selector", TypeProvider::fixedBytes(4));
3227 			members.emplace_back("address", TypeProvider::address());
3228 		}
3229 		if (m_kind != Kind::BareDelegateCall)
3230 		{
3231 			if (isPayable())
3232 				members.emplace_back(
3233 					"value",
3234 					TypeProvider::function(
3235 						parseElementaryTypeVector({"uint"}),
3236 						TypePointers{copyAndSetCallOptions(false, true, false)},
3237 						strings(1, ""),
3238 						strings(1, ""),
3239 						Kind::SetValue,
3240 						false,
3241 						StateMutability::Pure,
3242 						nullptr,
3243 						m_gasSet,
3244 						m_valueSet,
3245 						m_saltSet
3246 					)
3247 				);
3248 		}
3249 		if (m_kind != Kind::Creation)
3250 			members.emplace_back(
3251 				"gas",
3252 				TypeProvider::function(
3253 					parseElementaryTypeVector({"uint"}),
3254 					TypePointers{copyAndSetCallOptions(true, false, false)},
3255 					strings(1, ""),
3256 					strings(1, ""),
3257 					Kind::SetGas,
3258 					false,
3259 					StateMutability::Pure,
3260 					nullptr,
3261 					m_gasSet,
3262 					m_valueSet,
3263 					m_saltSet
3264 				)
3265 			);
3266 		return members;
3267 	}
3268 	case Kind::DelegateCall:
3269 	{
3270 		auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(m_declaration);
3271 		solAssert(functionDefinition, "");
3272 		solAssert(functionDefinition->visibility() != Visibility::Private, "");
3273 		if (functionDefinition->visibility() != Visibility::Internal)
3274 		{
3275 			auto const* contract = dynamic_cast<ContractDefinition const*>(m_declaration->scope());
3276 			solAssert(contract, "");
3277 			solAssert(contract->isLibrary(), "");
3278 			return {{"selector", TypeProvider::fixedBytes(4)}};
3279 		}
3280 		return {};
3281 	}
3282 	case Kind::Error:
3283 		return {{"selector", TypeProvider::fixedBytes(4)}};
3284 	default:
3285 		return MemberList::MemberMap();
3286 	}
3287 }
3288 
encodingType() const3289 Type const* FunctionType::encodingType() const
3290 {
3291 	if (m_gasSet || m_valueSet)
3292 		return nullptr;
3293 	// Only external functions can be encoded, internal functions cannot leave code boundaries.
3294 	if (m_kind == Kind::External)
3295 		return this;
3296 	else
3297 		return nullptr;
3298 }
3299 
interfaceType(bool) const3300 TypeResult FunctionType::interfaceType(bool /*_inLibrary*/) const
3301 {
3302 	if (m_kind == Kind::External)
3303 		return this;
3304 	else
3305 		return TypeResult::err("Internal type is not allowed for public or external functions.");
3306 }
3307 
mobileType() const3308 Type const* FunctionType::mobileType() const
3309 {
3310 	if (m_valueSet || m_gasSet || m_saltSet || m_bound)
3311 		return nullptr;
3312 
3313 	// return function without parameter names
3314 	return TypeProvider::function(
3315 		m_parameterTypes,
3316 		m_returnParameterTypes,
3317 		strings(m_parameterTypes.size()),
3318 		strings(m_returnParameterNames.size()),
3319 		m_kind,
3320 		m_arbitraryParameters,
3321 		m_stateMutability,
3322 		m_declaration,
3323 		m_gasSet,
3324 		m_valueSet,
3325 		m_bound,
3326 		m_saltSet
3327 	);
3328 }
3329 
canTakeArguments(FuncCallArguments const & _arguments,Type const * _selfType) const3330 bool FunctionType::canTakeArguments(
3331 	FuncCallArguments const& _arguments,
3332 	Type const* _selfType
3333 ) const
3334 {
3335 	solAssert(!bound() || _selfType, "");
3336 	if (bound() && !_selfType->isImplicitlyConvertibleTo(*selfType()))
3337 		return false;
3338 	TypePointers paramTypes = parameterTypes();
3339 	std::vector<std::string> const paramNames = parameterNames();
3340 
3341 	if (takesArbitraryParameters())
3342 		return true;
3343 	else if (_arguments.numArguments() != paramTypes.size())
3344 		return false;
3345 	else if (!_arguments.hasNamedArguments())
3346 		return equal(
3347 			_arguments.types.cbegin(),
3348 			_arguments.types.cend(),
3349 			paramTypes.cbegin(),
3350 			[](Type const* argumentType, Type const* parameterType)
3351 			{
3352 				return argumentType->isImplicitlyConvertibleTo(*parameterType);
3353 			}
3354 		);
3355 	else if (paramNames.size() != _arguments.numNames())
3356 		return false;
3357 	else
3358 	{
3359 		solAssert(_arguments.numArguments() == _arguments.numNames(), "Expected equal sized type & name vectors");
3360 
3361 		size_t matchedNames = 0;
3362 
3363 		for (size_t a = 0; a < _arguments.names.size(); a++)
3364 			for (size_t p = 0; p < paramNames.size(); p++)
3365 				if (*_arguments.names[a] == paramNames[p])
3366 				{
3367 					matchedNames++;
3368 					if (!_arguments.types[a]->isImplicitlyConvertibleTo(*paramTypes[p]))
3369 						return false;
3370 				}
3371 
3372 		if (matchedNames == _arguments.numNames())
3373 			return true;
3374 
3375 		return false;
3376 	}
3377 }
3378 
hasEqualParameterTypes(FunctionType const & _other) const3379 bool FunctionType::hasEqualParameterTypes(FunctionType const& _other) const
3380 {
3381 	if (m_parameterTypes.size() != _other.m_parameterTypes.size())
3382 		return false;
3383 	return equal(
3384 		m_parameterTypes.cbegin(),
3385 		m_parameterTypes.cend(),
3386 		_other.m_parameterTypes.cbegin(),
3387 		[](Type const* _a, Type const* _b) -> bool { return *_a == *_b; }
3388 	);
3389 }
3390 
hasEqualReturnTypes(FunctionType const & _other) const3391 bool FunctionType::hasEqualReturnTypes(FunctionType const& _other) const
3392 {
3393 	if (m_returnParameterTypes.size() != _other.m_returnParameterTypes.size())
3394 		return false;
3395 	return equal(
3396 		m_returnParameterTypes.cbegin(),
3397 		m_returnParameterTypes.cend(),
3398 		_other.m_returnParameterTypes.cbegin(),
3399 		[](Type const* _a, Type const* _b) -> bool { return *_a == *_b; }
3400 	);
3401 }
3402 
equalExcludingStateMutability(FunctionType const & _other) const3403 bool FunctionType::equalExcludingStateMutability(FunctionType const& _other) const
3404 {
3405 	if (m_kind != _other.m_kind)
3406 		return false;
3407 
3408 	if (!hasEqualParameterTypes(_other) || !hasEqualReturnTypes(_other))
3409 		return false;
3410 
3411 	//@todo this is ugly, but cannot be prevented right now
3412 	if (m_gasSet != _other.m_gasSet || m_valueSet != _other.m_valueSet || m_saltSet != _other.m_saltSet)
3413 		return false;
3414 
3415 	if (bound() != _other.bound())
3416 		return false;
3417 
3418 	solAssert(!bound() || *selfType() == *_other.selfType(), "");
3419 
3420 	return true;
3421 }
3422 
isBareCall() const3423 bool FunctionType::isBareCall() const
3424 {
3425 	switch (m_kind)
3426 	{
3427 	case Kind::BareCall:
3428 	case Kind::BareCallCode:
3429 	case Kind::BareDelegateCall:
3430 	case Kind::BareStaticCall:
3431 	case Kind::ECRecover:
3432 	case Kind::SHA256:
3433 	case Kind::RIPEMD160:
3434 		return true;
3435 	default:
3436 		return false;
3437 	}
3438 }
3439 
externalSignature() const3440 string FunctionType::externalSignature() const
3441 {
3442 	solAssert(m_declaration != nullptr, "External signature of function needs declaration");
3443 	solAssert(!m_declaration->name().empty(), "Fallback function has no signature.");
3444 	switch (kind())
3445 	{
3446 	case Kind::Internal:
3447 	case Kind::External:
3448 	case Kind::DelegateCall:
3449 	case Kind::Event:
3450 	case Kind::Error:
3451 	case Kind::Declaration:
3452 		break;
3453 	default:
3454 		solAssert(false, "Invalid function type for requesting external signature.");
3455 	}
3456 
3457 	// "inLibrary" is only relevant if this is neither an event nor an error.
3458 	bool inLibrary = false;
3459 	if (kind() != Kind::Event && kind() != Kind::Error)
3460 		if (auto const* contract = dynamic_cast<ContractDefinition const*>(m_declaration->scope()))
3461 			inLibrary = contract->isLibrary();
3462 
3463 	auto extParams = transformParametersToExternal(m_parameterTypes, inLibrary);
3464 
3465 	solAssert(extParams.message().empty(), extParams.message());
3466 
3467 	auto typeStrings = extParams.get() | ranges::views::transform([&](Type const* _t) -> string
3468 	{
3469 		string typeName = _t->signatureInExternalFunction(inLibrary);
3470 
3471 		if (inLibrary && _t->dataStoredIn(DataLocation::Storage))
3472 			typeName += " storage";
3473 		return typeName;
3474 	});
3475 	return m_declaration->name() + "(" + boost::algorithm::join(typeStrings, ",") + ")";
3476 }
3477 
externalIdentifier() const3478 u256 FunctionType::externalIdentifier() const
3479 {
3480 	return util::selectorFromSignature32(externalSignature());
3481 }
3482 
externalIdentifierHex() const3483 string FunctionType::externalIdentifierHex() const
3484 {
3485 	return util::FixedHash<4>(util::keccak256(externalSignature())).hex();
3486 }
3487 
isPure() const3488 bool FunctionType::isPure() const
3489 {
3490 	// TODO: replace this with m_stateMutability == StateMutability::Pure once
3491 	//       the callgraph analyzer is in place
3492 	return
3493 		m_kind == Kind::KECCAK256 ||
3494 		m_kind == Kind::ECRecover ||
3495 		m_kind == Kind::SHA256 ||
3496 		m_kind == Kind::RIPEMD160 ||
3497 		m_kind == Kind::AddMod ||
3498 		m_kind == Kind::MulMod ||
3499 		m_kind == Kind::ObjectCreation ||
3500 		m_kind == Kind::ABIEncode ||
3501 		m_kind == Kind::ABIEncodePacked ||
3502 		m_kind == Kind::ABIEncodeWithSelector ||
3503 		m_kind == Kind::ABIEncodeCall ||
3504 		m_kind == Kind::ABIEncodeWithSignature ||
3505 		m_kind == Kind::ABIDecode ||
3506 		m_kind == Kind::MetaType ||
3507 		m_kind == Kind::Wrap ||
3508 		m_kind == Kind::Unwrap;
3509 }
3510 
parseElementaryTypeVector(strings const & _types)3511 TypePointers FunctionType::parseElementaryTypeVector(strings const& _types)
3512 {
3513 	TypePointers pointers;
3514 	pointers.reserve(_types.size());
3515 	for (string const& type: _types)
3516 		pointers.push_back(TypeProvider::fromElementaryTypeName(type));
3517 	return pointers;
3518 }
3519 
copyAndSetCallOptions(bool _setGas,bool _setValue,bool _setSalt) const3520 Type const* FunctionType::copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const
3521 {
3522 	solAssert(m_kind != Kind::Declaration, "");
3523 	return TypeProvider::function(
3524 		m_parameterTypes,
3525 		m_returnParameterTypes,
3526 		m_parameterNames,
3527 		m_returnParameterNames,
3528 		m_kind,
3529 		m_arbitraryParameters,
3530 		m_stateMutability,
3531 		m_declaration,
3532 		m_gasSet || _setGas,
3533 		m_valueSet || _setValue,
3534 		m_saltSet || _setSalt,
3535 		m_bound
3536 	);
3537 }
3538 
asBoundFunction() const3539 FunctionTypePointer FunctionType::asBoundFunction() const
3540 {
3541 	solAssert(!m_parameterTypes.empty(), "");
3542 	solAssert(!m_gasSet, "");
3543 	solAssert(!m_valueSet, "");
3544 	solAssert(!m_saltSet, "");
3545 	return TypeProvider::function(
3546 		m_parameterTypes,
3547 		m_returnParameterTypes,
3548 		m_parameterNames,
3549 		m_returnParameterNames,
3550 		m_kind,
3551 		m_arbitraryParameters,
3552 		m_stateMutability,
3553 		m_declaration,
3554 		m_gasSet,
3555 		m_valueSet,
3556 		m_saltSet,
3557 		true
3558 	);
3559 }
3560 
asExternallyCallableFunction(bool _inLibrary) const3561 FunctionTypePointer FunctionType::asExternallyCallableFunction(bool _inLibrary) const
3562 {
3563 	TypePointers parameterTypes;
3564 	for (auto const& t: m_parameterTypes)
3565 		if (TypeProvider::isReferenceWithLocation(t, DataLocation::CallData))
3566 			parameterTypes.push_back(
3567 				TypeProvider::withLocationIfReference(DataLocation::Memory, t, true)
3568 			);
3569 		else
3570 			parameterTypes.push_back(t);
3571 
3572 	TypePointers returnParameterTypes;
3573 	for (auto const& returnParamType: m_returnParameterTypes)
3574 		if (TypeProvider::isReferenceWithLocation(returnParamType, DataLocation::CallData))
3575 			returnParameterTypes.push_back(
3576 				TypeProvider::withLocationIfReference(DataLocation::Memory, returnParamType, true)
3577 			);
3578 		else
3579 			returnParameterTypes.push_back(returnParamType);
3580 
3581 	Kind kind = m_kind;
3582 	if (_inLibrary)
3583 	{
3584 		solAssert(!!m_declaration, "Declaration has to be available.");
3585 		solAssert(m_declaration->isPublic(), "");
3586 		kind = Kind::DelegateCall;
3587 	}
3588 
3589 	return TypeProvider::function(
3590 		parameterTypes,
3591 		returnParameterTypes,
3592 		m_parameterNames,
3593 		m_returnParameterNames,
3594 		kind,
3595 		m_arbitraryParameters,
3596 		m_stateMutability,
3597 		m_declaration,
3598 		m_gasSet,
3599 		m_valueSet,
3600 		m_saltSet,
3601 		m_bound
3602 	);
3603 }
3604 
selfType() const3605 Type const* FunctionType::selfType() const
3606 {
3607 	solAssert(bound(), "Function is not bound.");
3608 	solAssert(m_parameterTypes.size() > 0, "Function has no self type.");
3609 	return m_parameterTypes.at(0);
3610 }
3611 
documentation() const3612 ASTPointer<StructuredDocumentation> FunctionType::documentation() const
3613 {
3614 	auto function = dynamic_cast<StructurallyDocumented const*>(m_declaration);
3615 	if (function)
3616 		return function->documentation();
3617 
3618 	return ASTPointer<StructuredDocumentation>();
3619 }
3620 
padArguments() const3621 bool FunctionType::padArguments() const
3622 {
3623 	// No padding only for hash functions, low-level calls and the packed encoding function.
3624 	switch (m_kind)
3625 	{
3626 	case Kind::BareCall:
3627 	case Kind::BareCallCode:
3628 	case Kind::BareDelegateCall:
3629 	case Kind::BareStaticCall:
3630 	case Kind::SHA256:
3631 	case Kind::RIPEMD160:
3632 	case Kind::KECCAK256:
3633 	case Kind::ABIEncodePacked:
3634 		return false;
3635 	default:
3636 		return true;
3637 	}
3638 	return true;
3639 }
3640 
encodingType() const3641 Type const* MappingType::encodingType() const
3642 {
3643 	return TypeProvider::integer(256, IntegerType::Modifier::Unsigned);
3644 }
3645 
richIdentifier() const3646 string MappingType::richIdentifier() const
3647 {
3648 	return "t_mapping" + identifierList(m_keyType, m_valueType);
3649 }
3650 
operator ==(Type const & _other) const3651 bool MappingType::operator==(Type const& _other) const
3652 {
3653 	if (_other.category() != category())
3654 		return false;
3655 	MappingType const& other = dynamic_cast<MappingType const&>(_other);
3656 	return *other.m_keyType == *m_keyType && *other.m_valueType == *m_valueType;
3657 }
3658 
toString(bool _short) const3659 string MappingType::toString(bool _short) const
3660 {
3661 	return "mapping(" + keyType()->toString(_short) + " => " + valueType()->toString(_short) + ")";
3662 }
3663 
canonicalName() const3664 string MappingType::canonicalName() const
3665 {
3666 	return "mapping(" + keyType()->canonicalName() + " => " + valueType()->canonicalName() + ")";
3667 }
3668 
interfaceType(bool _inLibrary) const3669 TypeResult MappingType::interfaceType(bool _inLibrary) const
3670 {
3671 	solAssert(keyType()->interfaceType(_inLibrary).get(), "Must be an elementary type!");
3672 
3673 	if (_inLibrary)
3674 	{
3675 		auto iType = valueType()->interfaceType(_inLibrary);
3676 
3677 		if (!iType.get())
3678 		{
3679 			solAssert(!iType.message().empty(), "Expected detailed error message!");
3680 			return iType;
3681 		}
3682 	}
3683 	else
3684 		return TypeResult::err(
3685 			"Types containing (nested) mappings can only be parameters or "
3686 			"return variables of internal or library functions."
3687 		);
3688 
3689 	return this;
3690 }
3691 
richIdentifier() const3692 string TypeType::richIdentifier() const
3693 {
3694 	return "t_type" + identifierList(actualType());
3695 }
3696 
operator ==(Type const & _other) const3697 bool TypeType::operator==(Type const& _other) const
3698 {
3699 	if (_other.category() != category())
3700 		return false;
3701 	TypeType const& other = dynamic_cast<TypeType const&>(_other);
3702 	return *actualType() == *other.actualType();
3703 }
3704 
storageSize() const3705 u256 TypeType::storageSize() const
3706 {
3707 	solAssert(false, "Storage size of non-storable type type requested.");
3708 }
3709 
makeStackItems() const3710 vector<tuple<string, Type const*>> TypeType::makeStackItems() const
3711 {
3712 	if (auto contractType = dynamic_cast<ContractType const*>(m_actualType))
3713 		if (contractType->contractDefinition().isLibrary())
3714 		{
3715 			solAssert(!contractType->isSuper(), "");
3716 			return {make_tuple("address", TypeProvider::address())};
3717 		}
3718 
3719 	return {};
3720 }
3721 
nativeMembers(ASTNode const * _currentScope) const3722 MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) const
3723 {
3724 	MemberList::MemberMap members;
3725 	if (m_actualType->category() == Category::Contract)
3726 	{
3727 		auto contractType = dynamic_cast<ContractType const*>(m_actualType);
3728 		ContractDefinition const& contract = contractType->contractDefinition();
3729 		if (contractType->isSuper())
3730 		{
3731 			// add the most derived of all functions which are visible in derived contracts
3732 			auto bases = contract.annotation().linearizedBaseContracts;
3733 			solAssert(bases.size() >= 1, "linearizedBaseContracts should at least contain the most derived contract.");
3734 			// `sliced(1, ...)` ignores the most derived contract, which should not be searchable from `super`.
3735 			for (ContractDefinition const* base: bases | ranges::views::tail)
3736 				for (FunctionDefinition const* function: base->definedFunctions())
3737 				{
3738 					if (!function->isVisibleInDerivedContracts() || !function->isImplemented())
3739 						continue;
3740 
3741 					auto functionType = TypeProvider::function(*function, FunctionType::Kind::Internal);
3742 					bool functionWithEqualArgumentsFound = false;
3743 					for (auto const& member: members)
3744 					{
3745 						if (member.name != function->name())
3746 							continue;
3747 						auto memberType = dynamic_cast<FunctionType const*>(member.type);
3748 						solAssert(!!memberType, "Override changes type.");
3749 						if (!memberType->hasEqualParameterTypes(*functionType))
3750 							continue;
3751 						functionWithEqualArgumentsFound = true;
3752 						break;
3753 					}
3754 					if (!functionWithEqualArgumentsFound)
3755 						members.emplace_back(function, functionType);
3756 				}
3757 		}
3758 		else
3759 		{
3760 			auto const* contractScope = dynamic_cast<ContractDefinition const*>(_currentScope);
3761 			bool inDerivingScope = contractScope && contractScope->derivesFrom(contract);
3762 
3763 			for (auto const* declaration: contract.declarations())
3764 			{
3765 				if (dynamic_cast<ModifierDefinition const*>(declaration))
3766 					continue;
3767 				if (declaration->name().empty())
3768 					continue;
3769 
3770 				if (!contract.isLibrary() && inDerivingScope && declaration->isVisibleInDerivedContracts())
3771 				{
3772 					if (
3773 						auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(declaration);
3774 						functionDefinition && !functionDefinition->isImplemented()
3775 					)
3776 						members.emplace_back(declaration, declaration->typeViaContractName());
3777 					else
3778 						members.emplace_back(declaration, declaration->type());
3779 				}
3780 				else if (
3781 					(contract.isLibrary() && declaration->isVisibleAsLibraryMember()) ||
3782 					declaration->isVisibleViaContractTypeAccess()
3783 				)
3784 					members.emplace_back(declaration, declaration->typeViaContractName());
3785 			}
3786 		}
3787 	}
3788 	else if (m_actualType->category() == Category::Enum)
3789 	{
3790 		EnumDefinition const& enumDef = dynamic_cast<EnumType const&>(*m_actualType).enumDefinition();
3791 		auto enumType = TypeProvider::enumType(enumDef);
3792 		for (ASTPointer<EnumValue> const& enumValue: enumDef.members())
3793 			members.emplace_back(enumValue.get(), enumType);
3794 	}
3795 	else if (m_actualType->category() == Category::UserDefinedValueType)
3796 	{
3797 		auto& userDefined = dynamic_cast<UserDefinedValueType const&>(*m_actualType);
3798 		members.emplace_back(
3799 			"wrap",
3800 			TypeProvider::function(
3801 				TypePointers{&userDefined.underlyingType()},
3802 				TypePointers{&userDefined},
3803 				strings{string{}},
3804 				strings{string{}},
3805 				FunctionType::Kind::Wrap,
3806 				false, /*_arbitraryParameters */
3807 				StateMutability::Pure
3808 			)
3809 		);
3810 		members.emplace_back(
3811 			"unwrap",
3812 			TypeProvider::function(
3813 				TypePointers{&userDefined},
3814 				TypePointers{&userDefined.underlyingType()},
3815 				strings{string{}},
3816 				strings{string{}},
3817 				FunctionType::Kind::Unwrap,
3818 				false, /* _arbitraryParameters */
3819 				StateMutability::Pure
3820 			)
3821 		);
3822 	}
3823 	else if (
3824 		auto const* arrayType = dynamic_cast<ArrayType const*>(m_actualType);
3825 		arrayType && arrayType->isByteArray()
3826 	)
3827 		members.emplace_back("concat", TypeProvider::function(
3828 			TypePointers{},
3829 			TypePointers{TypeProvider::bytesMemory()},
3830 			strings{},
3831 			strings{string()},
3832 			FunctionType::Kind::BytesConcat,
3833 			/* _arbitraryParameters */ true,
3834 			StateMutability::Pure
3835 		));
3836 
3837 	return members;
3838 }
3839 
isExplicitlyConvertibleTo(Type const & _convertTo) const3840 BoolResult TypeType::isExplicitlyConvertibleTo(Type const& _convertTo) const
3841 {
3842 	if (auto const* address = dynamic_cast<AddressType const*>(&_convertTo))
3843 		if (address->stateMutability() == StateMutability::NonPayable)
3844 			if (auto const* contractType = dynamic_cast<ContractType const*>(m_actualType))
3845 				return contractType->contractDefinition().isLibrary();
3846 	return isImplicitlyConvertibleTo(_convertTo);
3847 }
3848 
ModifierType(ModifierDefinition const & _modifier)3849 ModifierType::ModifierType(ModifierDefinition const& _modifier)
3850 {
3851 	TypePointers params;
3852 	params.reserve(_modifier.parameters().size());
3853 	for (ASTPointer<VariableDeclaration> const& var: _modifier.parameters())
3854 		params.push_back(var->annotation().type);
3855 	swap(params, m_parameterTypes);
3856 }
3857 
storageSize() const3858 u256 ModifierType::storageSize() const
3859 {
3860 	solAssert(false, "Storage size of non-storable type type requested.");
3861 }
3862 
richIdentifier() const3863 string ModifierType::richIdentifier() const
3864 {
3865 	return "t_modifier" + identifierList(m_parameterTypes);
3866 }
3867 
operator ==(Type const & _other) const3868 bool ModifierType::operator==(Type const& _other) const
3869 {
3870 	if (_other.category() != category())
3871 		return false;
3872 	ModifierType const& other = dynamic_cast<ModifierType const&>(_other);
3873 
3874 	if (m_parameterTypes.size() != other.m_parameterTypes.size())
3875 		return false;
3876 	auto typeCompare = [](Type const* _a, Type const* _b) -> bool { return *_a == *_b; };
3877 
3878 	if (!equal(
3879 		m_parameterTypes.cbegin(),
3880 		m_parameterTypes.cend(),
3881 		other.m_parameterTypes.cbegin(),
3882 		typeCompare
3883 	))
3884 		return false;
3885 	return true;
3886 }
3887 
toString(bool _short) const3888 string ModifierType::toString(bool _short) const
3889 {
3890 	string name = "modifier (";
3891 	for (auto it = m_parameterTypes.begin(); it != m_parameterTypes.end(); ++it)
3892 		name += (*it)->toString(_short) + (it + 1 == m_parameterTypes.end() ? "" : ",");
3893 	return name + ")";
3894 }
3895 
richIdentifier() const3896 string ModuleType::richIdentifier() const
3897 {
3898 	return "t_module_" + to_string(m_sourceUnit.id());
3899 }
3900 
operator ==(Type const & _other) const3901 bool ModuleType::operator==(Type const& _other) const
3902 {
3903 	if (_other.category() != category())
3904 		return false;
3905 	return &m_sourceUnit == &dynamic_cast<ModuleType const&>(_other).m_sourceUnit;
3906 }
3907 
nativeMembers(ASTNode const *) const3908 MemberList::MemberMap ModuleType::nativeMembers(ASTNode const*) const
3909 {
3910 	MemberList::MemberMap symbols;
3911 	for (auto const& [name, declarations]: *m_sourceUnit.annotation().exportedSymbols)
3912 		for (Declaration const* symbol: declarations)
3913 			symbols.emplace_back(symbol, symbol->type(), name);
3914 	return symbols;
3915 }
3916 
toString(bool) const3917 string ModuleType::toString(bool) const
3918 {
3919 	return string("module \"") + *m_sourceUnit.annotation().path + string("\"");
3920 }
3921 
richIdentifier() const3922 string MagicType::richIdentifier() const
3923 {
3924 	switch (m_kind)
3925 	{
3926 	case Kind::Block:
3927 		return "t_magic_block";
3928 	case Kind::Message:
3929 		return "t_magic_message";
3930 	case Kind::Transaction:
3931 		return "t_magic_transaction";
3932 	case Kind::ABI:
3933 		return "t_magic_abi";
3934 	case Kind::MetaType:
3935 		solAssert(m_typeArgument, "");
3936 		return "t_magic_meta_type_" + m_typeArgument->richIdentifier();
3937 	}
3938 	return "";
3939 }
3940 
operator ==(Type const & _other) const3941 bool MagicType::operator==(Type const& _other) const
3942 {
3943 	if (_other.category() != category())
3944 		return false;
3945 	MagicType const& other = dynamic_cast<MagicType const&>(_other);
3946 	return other.m_kind == m_kind;
3947 }
3948 
nativeMembers(ASTNode const *) const3949 MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
3950 {
3951 	switch (m_kind)
3952 	{
3953 	case Kind::Block:
3954 		return MemberList::MemberMap({
3955 			{"coinbase", TypeProvider::payableAddress()},
3956 			{"timestamp", TypeProvider::uint256()},
3957 			{"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)},
3958 			{"difficulty", TypeProvider::uint256()},
3959 			{"number", TypeProvider::uint256()},
3960 			{"gaslimit", TypeProvider::uint256()},
3961 			{"chainid", TypeProvider::uint256()},
3962 			{"basefee", TypeProvider::uint256()}
3963 		});
3964 	case Kind::Message:
3965 		return MemberList::MemberMap({
3966 			{"sender", TypeProvider::address()},
3967 			{"gas", TypeProvider::uint256()},
3968 			{"value", TypeProvider::uint256()},
3969 			{"data", TypeProvider::array(DataLocation::CallData)},
3970 			{"sig", TypeProvider::fixedBytes(4)}
3971 		});
3972 	case Kind::Transaction:
3973 		return MemberList::MemberMap({
3974 			{"origin", TypeProvider::address()},
3975 			{"gasprice", TypeProvider::uint256()}
3976 		});
3977 	case Kind::ABI:
3978 		return MemberList::MemberMap({
3979 			{"encode", TypeProvider::function(
3980 				TypePointers{},
3981 				TypePointers{TypeProvider::array(DataLocation::Memory)},
3982 				strings{},
3983 				strings{1, ""},
3984 				FunctionType::Kind::ABIEncode,
3985 				true,
3986 				StateMutability::Pure
3987 			)},
3988 			{"encodePacked", TypeProvider::function(
3989 				TypePointers{},
3990 				TypePointers{TypeProvider::array(DataLocation::Memory)},
3991 				strings{},
3992 				strings{1, ""},
3993 				FunctionType::Kind::ABIEncodePacked,
3994 				true,
3995 				StateMutability::Pure
3996 			)},
3997 			{"encodeWithSelector", TypeProvider::function(
3998 				TypePointers{TypeProvider::fixedBytes(4)},
3999 				TypePointers{TypeProvider::array(DataLocation::Memory)},
4000 				strings{1, ""},
4001 				strings{1, ""},
4002 				FunctionType::Kind::ABIEncodeWithSelector,
4003 				true,
4004 				StateMutability::Pure
4005 			)},
4006 			{"encodeCall", TypeProvider::function(
4007 				TypePointers{},
4008 				TypePointers{TypeProvider::array(DataLocation::Memory)},
4009 				strings{},
4010 				strings{1, ""},
4011 				FunctionType::Kind::ABIEncodeCall,
4012 				true,
4013 				StateMutability::Pure
4014 			)},
4015 			{"encodeWithSignature", TypeProvider::function(
4016 				TypePointers{TypeProvider::array(DataLocation::Memory, true)},
4017 				TypePointers{TypeProvider::array(DataLocation::Memory)},
4018 				strings{1, ""},
4019 				strings{1, ""},
4020 				FunctionType::Kind::ABIEncodeWithSignature,
4021 				true,
4022 				StateMutability::Pure
4023 			)},
4024 			{"decode", TypeProvider::function(
4025 				TypePointers(),
4026 				TypePointers(),
4027 				strings{},
4028 				strings{},
4029 				FunctionType::Kind::ABIDecode,
4030 				true,
4031 				StateMutability::Pure
4032 			)}
4033 		});
4034 	case Kind::MetaType:
4035 	{
4036 		solAssert(
4037 			m_typeArgument && (
4038 					m_typeArgument->category() == Type::Category::Contract ||
4039 					m_typeArgument->category() == Type::Category::Integer ||
4040 					m_typeArgument->category() == Type::Category::Enum
4041 			),
4042 			"Only enums, contracts or integer types supported for now"
4043 		);
4044 
4045 		if (m_typeArgument->category() == Type::Category::Contract)
4046 		{
4047 			ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_typeArgument).contractDefinition();
4048 			if (contract.canBeDeployed())
4049 				return MemberList::MemberMap({
4050 					{"creationCode", TypeProvider::array(DataLocation::Memory)},
4051 					{"runtimeCode", TypeProvider::array(DataLocation::Memory)},
4052 					{"name", TypeProvider::stringMemory()},
4053 				});
4054 			else
4055 				return MemberList::MemberMap({
4056 					{"interfaceId", TypeProvider::fixedBytes(4)},
4057 					{"name", TypeProvider::stringMemory()},
4058 				});
4059 		}
4060 		else if (m_typeArgument->category() == Type::Category::Integer)
4061 		{
4062 			IntegerType const* integerTypePointer = dynamic_cast<IntegerType const*>(m_typeArgument);
4063 			return MemberList::MemberMap({
4064 				{"min", integerTypePointer},
4065 				{"max", integerTypePointer},
4066 			});
4067 		}
4068 		else if (m_typeArgument->category() == Type::Category::Enum)
4069 		{
4070 			EnumType const* enumTypePointer = dynamic_cast<EnumType const*>(m_typeArgument);
4071 			return MemberList::MemberMap({
4072 				{"min", enumTypePointer},
4073 				{"max", enumTypePointer},
4074 			});
4075 		}
4076 	}
4077 	}
4078 	solAssert(false, "Unknown kind of magic.");
4079 	return {};
4080 }
4081 
toString(bool _short) const4082 string MagicType::toString(bool _short) const
4083 {
4084 	switch (m_kind)
4085 	{
4086 	case Kind::Block:
4087 		return "block";
4088 	case Kind::Message:
4089 		return "msg";
4090 	case Kind::Transaction:
4091 		return "tx";
4092 	case Kind::ABI:
4093 		return "abi";
4094 	case Kind::MetaType:
4095 		solAssert(m_typeArgument, "");
4096 		return "type(" + m_typeArgument->toString(_short) + ")";
4097 	}
4098 	solAssert(false, "Unknown kind of magic.");
4099 	return {};
4100 }
4101 
typeArgument() const4102 Type const* MagicType::typeArgument() const
4103 {
4104 	solAssert(m_kind == Kind::MetaType, "");
4105 	solAssert(m_typeArgument, "");
4106 	return m_typeArgument;
4107 }
4108 
decodingType() const4109 Type const* InaccessibleDynamicType::decodingType() const
4110 {
4111 	return TypeProvider::integer(256, IntegerType::Modifier::Unsigned);
4112 }
4113