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