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  * Component that verifies overloads, abstract contracts, function clashes and others
20  * checks at contract or function level.
21  */
22 
23 #include <libsolidity/analysis/ContractLevelChecker.h>
24 
25 #include <libsolidity/ast/AST.h>
26 #include <libsolidity/ast/TypeProvider.h>
27 #include <libsolidity/analysis/TypeChecker.h>
28 #include <libsolutil/FunctionSelector.h>
29 #include <liblangutil/ErrorReporter.h>
30 
31 #include <range/v3/view/reverse.hpp>
32 
33 using namespace std;
34 using namespace solidity;
35 using namespace solidity::langutil;
36 using namespace solidity::frontend;
37 
38 namespace
39 {
40 
41 template <class T, class B>
hasEqualParameters(T const & _a,B const & _b)42 bool hasEqualParameters(T const& _a, B const& _b)
43 {
44 	return FunctionType(_a).asExternallyCallableFunction(false)->hasEqualParameterTypes(
45 		*FunctionType(_b).asExternallyCallableFunction(false)
46 	);
47 }
48 
49 template<typename T>
filterDeclarations(map<ASTString,vector<Declaration const * >> const & _declarations)50 map<ASTString, vector<T const*>> filterDeclarations(
51 	map<ASTString, vector<Declaration const*>> const& _declarations)
52 {
53 	map<ASTString, vector<T const*>> filteredDeclarations;
54 	for (auto const& [name, overloads]: _declarations)
55 		for (auto const* declaration: overloads)
56 			if (auto typedDeclaration = dynamic_cast<T const*>(declaration))
57 				filteredDeclarations[name].push_back(typedDeclaration);
58 	return filteredDeclarations;
59 }
60 
61 }
62 
check(SourceUnit const & _sourceUnit)63 bool ContractLevelChecker::check(SourceUnit const& _sourceUnit)
64 {
65 	bool noErrors = true;
66 	findDuplicateDefinitions(
67 		filterDeclarations<FunctionDefinition>(*_sourceUnit.annotation().exportedSymbols)
68 	);
69 	// This check flags duplicate free events when free events become
70 	// a Solidity feature
71 	findDuplicateDefinitions(
72 		filterDeclarations<EventDefinition>(*_sourceUnit.annotation().exportedSymbols)
73 	);
74 	if (Error::containsErrors(m_errorReporter.errors()))
75 		noErrors = false;
76 	for (ASTPointer<ASTNode> const& node: _sourceUnit.nodes())
77 		if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
78 			if (!check(*contract))
79 				noErrors = false;
80 	return noErrors;
81 }
82 
check(ContractDefinition const & _contract)83 bool ContractLevelChecker::check(ContractDefinition const& _contract)
84 {
85 	_contract.annotation().unimplementedDeclarations = std::vector<Declaration const*>();
86 
87 	checkDuplicateFunctions(_contract);
88 	checkDuplicateEvents(_contract);
89 	checkReceiveFunction(_contract);
90 	m_overrideChecker.check(_contract);
91 	checkBaseConstructorArguments(_contract);
92 	checkAbstractDefinitions(_contract);
93 	checkExternalTypeClashes(_contract);
94 	checkHashCollisions(_contract);
95 	checkLibraryRequirements(_contract);
96 	checkBaseABICompatibility(_contract);
97 	checkPayableFallbackWithoutReceive(_contract);
98 	checkStorageSize(_contract);
99 
100 	return !Error::containsErrors(m_errorReporter.errors());
101 }
102 
checkDuplicateFunctions(ContractDefinition const & _contract)103 void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _contract)
104 {
105 	/// Checks that two functions with the same name defined in this contract have different
106 	/// argument types and that there is at most one constructor.
107 	map<string, vector<FunctionDefinition const*>> functions;
108 	FunctionDefinition const* constructor = nullptr;
109 	FunctionDefinition const* fallback = nullptr;
110 	FunctionDefinition const* receive = nullptr;
111 	for (FunctionDefinition const* function: _contract.definedFunctions())
112 		if (function->isConstructor())
113 		{
114 			if (constructor)
115 				m_errorReporter.declarationError(
116 					7997_error,
117 					function->location(),
118 					SecondarySourceLocation().append("Another declaration is here:", constructor->location()),
119 					"More than one constructor defined."
120 				);
121 			constructor = function;
122 		}
123 		else if (function->isFallback())
124 		{
125 			if (fallback)
126 				m_errorReporter.declarationError(
127 					7301_error,
128 					function->location(),
129 					SecondarySourceLocation().append("Another declaration is here:", fallback->location()),
130 					"Only one fallback function is allowed."
131 				);
132 			fallback = function;
133 		}
134 		else if (function->isReceive())
135 		{
136 			if (receive)
137 				m_errorReporter.declarationError(
138 					4046_error,
139 					function->location(),
140 					SecondarySourceLocation().append("Another declaration is here:", receive->location()),
141 					"Only one receive function is allowed."
142 				);
143 			receive = function;
144 		}
145 		else
146 		{
147 			solAssert(!function->name().empty(), "");
148 			functions[function->name()].push_back(function);
149 		}
150 
151 	findDuplicateDefinitions(functions);
152 }
153 
checkDuplicateEvents(ContractDefinition const & _contract)154 void ContractLevelChecker::checkDuplicateEvents(ContractDefinition const& _contract)
155 {
156 	/// Checks that two events with the same name defined in this contract have different
157 	/// argument types
158 	map<string, vector<EventDefinition const*>> events;
159 	for (auto const* contract: _contract.annotation().linearizedBaseContracts)
160 		for (EventDefinition const* event: contract->events())
161 			events[event->name()].push_back(event);
162 
163 	findDuplicateDefinitions(events);
164 }
165 
checkReceiveFunction(ContractDefinition const & _contract)166 void ContractLevelChecker::checkReceiveFunction(ContractDefinition const& _contract)
167 {
168 	for (FunctionDefinition const* function: _contract.definedFunctions())
169 	{
170 		solAssert(function, "");
171 		if (function->isReceive())
172 		{
173 			if (function->libraryFunction())
174 				m_errorReporter.declarationError(4549_error, function->location(), "Libraries cannot have receive ether functions.");
175 
176 			if (function->stateMutability() != StateMutability::Payable)
177 				m_errorReporter.declarationError(
178 					7793_error,
179 					function->location(),
180 					"Receive ether function must be payable, but is \"" +
181 					stateMutabilityToString(function->stateMutability()) +
182 					"\"."
183 				);
184 			if (function->visibility() != Visibility::External)
185 				m_errorReporter.declarationError(4095_error, function->location(), "Receive ether function must be defined as \"external\".");
186 
187 			if (!function->returnParameters().empty())
188 				m_errorReporter.fatalDeclarationError(6899_error, function->returnParameterList()->location(), "Receive ether function cannot return values.");
189 			if (!function->parameters().empty())
190 				m_errorReporter.fatalDeclarationError(6857_error, function->parameterList().location(), "Receive ether function cannot take parameters.");
191 		}
192 	}
193 }
194 
195 template <class T>
findDuplicateDefinitions(map<string,vector<T>> const & _definitions)196 void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const& _definitions)
197 {
198 	for (auto const& it: _definitions)
199 	{
200 		vector<T> const& overloads = it.second;
201 		set<size_t> reported;
202 		for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
203 		{
204 			SecondarySourceLocation ssl;
205 
206 			for (size_t j = i + 1; j < overloads.size(); ++j)
207 				if (hasEqualParameters(*overloads[i], *overloads[j]))
208 				{
209 					solAssert(
210 						(
211 							dynamic_cast<ContractDefinition const*>(overloads[i]->scope()) &&
212 							dynamic_cast<ContractDefinition const*>(overloads[j]->scope()) &&
213 							overloads[i]->name() == overloads[j]->name()
214 						) ||
215 						(
216 							dynamic_cast<SourceUnit const*>(overloads[i]->scope()) &&
217 							dynamic_cast<SourceUnit const*>(overloads[j]->scope())
218 						),
219 						"Override is neither a namesake function/event in contract scope nor "
220 						"a free function/event (alias)."
221 					);
222 					ssl.append("Other declaration is here:", overloads[j]->location());
223 					reported.insert(j);
224 				}
225 
226 			if (ssl.infos.size() > 0)
227 			{
228 				ErrorId error;
229 				string message;
230 				if constexpr (is_same_v<T, FunctionDefinition const*>)
231 				{
232 					error = 1686_error;
233 					message = "Function with same name and parameter types defined twice.";
234 				}
235 				else
236 				{
237 					static_assert(is_same_v<T, EventDefinition const*>, "Expected \"FunctionDefinition const*\" or \"EventDefinition const*\"");
238 					error = 5883_error;
239 					message = "Event with same name and parameter types defined twice.";
240 				}
241 
242 				ssl.limitSize(message);
243 
244 				m_errorReporter.declarationError(
245 					error,
246 					overloads[i]->location(),
247 					ssl,
248 					message
249 				);
250 			}
251 		}
252 	}
253 }
254 
checkAbstractDefinitions(ContractDefinition const & _contract)255 void ContractLevelChecker::checkAbstractDefinitions(ContractDefinition const& _contract)
256 {
257 	// Collects functions, static variable getters and modifiers. If they
258 	// override (unimplemented) base class ones, they are replaced.
259 	set<OverrideProxy, OverrideProxy::CompareBySignature> proxies;
260 
261 	auto registerProxy = [&proxies](OverrideProxy const& _overrideProxy)
262 	{
263 		// Overwrite an existing proxy, if it exists.
264 		if (!_overrideProxy.unimplemented())
265 			proxies.erase(_overrideProxy);
266 
267 		proxies.insert(_overrideProxy);
268 	};
269 
270 	// Search from base to derived, collect all functions and modifiers and
271 	// update proxies.
272 	for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts | ranges::views::reverse)
273 	{
274 		for (VariableDeclaration const* v: contract->stateVariables())
275 			if (v->isPartOfExternalInterface())
276 				registerProxy(OverrideProxy(v));
277 
278 		for (FunctionDefinition const* function: contract->definedFunctions())
279 			if (!function->isConstructor())
280 				registerProxy(OverrideProxy(function));
281 
282 		for (ModifierDefinition const* modifier: contract->functionModifiers())
283 			registerProxy(OverrideProxy(modifier));
284 	}
285 
286 	// Set to not fully implemented if at least one flag is false.
287 	// Note that `_contract.annotation().unimplementedDeclarations` has already been
288 	// pre-filled by `checkBaseConstructorArguments`.
289 	//
290 	for (auto const& proxy: proxies)
291 		if (proxy.unimplemented())
292 			_contract.annotation().unimplementedDeclarations->push_back(proxy.declaration());
293 
294 	if (_contract.abstract())
295 	{
296 		if (_contract.contractKind() == ContractKind::Interface)
297 			m_errorReporter.typeError(9348_error, _contract.location(), "Interfaces do not need the \"abstract\" keyword, they are abstract implicitly.");
298 		else if (_contract.contractKind() == ContractKind::Library)
299 			m_errorReporter.typeError(9571_error, _contract.location(), "Libraries cannot be abstract.");
300 		else
301 			solAssert(_contract.contractKind() == ContractKind::Contract, "");
302 	}
303 
304 	// For libraries, we emit errors on function-level, so this is fine as long as we do
305 	// not have inheritance for libraries.
306 	if (
307 		_contract.contractKind() == ContractKind::Contract &&
308 		!_contract.abstract() &&
309 		!_contract.annotation().unimplementedDeclarations->empty()
310 	)
311 	{
312 		SecondarySourceLocation ssl;
313 		for (auto declaration: *_contract.annotation().unimplementedDeclarations)
314 			ssl.append("Missing implementation: ", declaration->location());
315 		m_errorReporter.typeError(
316 			3656_error,
317 			_contract.location(),
318 			ssl,
319 			"Contract \"" + *_contract.annotation().canonicalName + "\" should be marked as abstract."
320 		);
321 	}
322 }
323 
324 
checkBaseConstructorArguments(ContractDefinition const & _contract)325 void ContractLevelChecker::checkBaseConstructorArguments(ContractDefinition const& _contract)
326 {
327 	vector<ContractDefinition const*> const& bases = _contract.annotation().linearizedBaseContracts;
328 
329 	// Determine the arguments that are used for the base constructors.
330 	for (ContractDefinition const* contract: bases)
331 	{
332 		if (FunctionDefinition const* constructor = contract->constructor())
333 			for (auto const& modifier: constructor->modifiers())
334 				if (auto baseContract = dynamic_cast<ContractDefinition const*>(
335 					modifier->name().annotation().referencedDeclaration
336 				))
337 				{
338 					if (modifier->arguments())
339 					{
340 						if (baseContract->constructor())
341 							annotateBaseConstructorArguments(_contract, baseContract->constructor(), modifier.get());
342 					}
343 					else
344 						m_errorReporter.declarationError(
345 							1563_error,
346 							modifier->location(),
347 							"Modifier-style base constructor call without arguments."
348 						);
349 				}
350 
351 		for (ASTPointer<InheritanceSpecifier> const& base: contract->baseContracts())
352 		{
353 			ContractDefinition const* baseContract = dynamic_cast<ContractDefinition const*>(
354 				base->name().annotation().referencedDeclaration
355 			);
356 			solAssert(baseContract, "");
357 
358 			if (baseContract->constructor() && base->arguments() && !base->arguments()->empty())
359 				annotateBaseConstructorArguments(_contract, baseContract->constructor(), base.get());
360 		}
361 	}
362 
363 	// check that we get arguments for all base constructors that need it.
364 	// If not mark the contract as abstract (not fully implemented)
365 	for (ContractDefinition const* contract: bases)
366 		if (FunctionDefinition const* constructor = contract->constructor())
367 			if (contract != &_contract && !constructor->parameters().empty())
368 				if (!_contract.annotation().baseConstructorArguments.count(constructor))
369 					_contract.annotation().unimplementedDeclarations->push_back(constructor);
370 }
371 
annotateBaseConstructorArguments(ContractDefinition const & _currentContract,FunctionDefinition const * _baseConstructor,ASTNode const * _argumentNode)372 void ContractLevelChecker::annotateBaseConstructorArguments(
373 	ContractDefinition const& _currentContract,
374 	FunctionDefinition const* _baseConstructor,
375 	ASTNode const* _argumentNode
376 )
377 {
378 	solAssert(_baseConstructor, "");
379 	solAssert(_argumentNode, "");
380 
381 	auto insertionResult = _currentContract.annotation().baseConstructorArguments.insert(
382 		std::make_pair(_baseConstructor, _argumentNode)
383 	);
384 	if (!insertionResult.second)
385 	{
386 		ASTNode const* previousNode = insertionResult.first->second;
387 
388 		SourceLocation const* mainLocation = nullptr;
389 		SecondarySourceLocation ssl;
390 
391 		if (
392 			_currentContract.location().contains(previousNode->location()) ||
393 			_currentContract.location().contains(_argumentNode->location())
394 		)
395 		{
396 			mainLocation = &previousNode->location();
397 			ssl.append("Second constructor call is here:", _argumentNode->location());
398 		}
399 		else
400 		{
401 			mainLocation = &_currentContract.location();
402 			ssl.append("First constructor call is here:", _argumentNode->location());
403 			ssl.append("Second constructor call is here:", previousNode->location());
404 		}
405 
406 		m_errorReporter.declarationError(
407 			3364_error,
408 			*mainLocation,
409 			ssl,
410 			"Base constructor arguments given twice."
411 		);
412 	}
413 
414 }
415 
checkExternalTypeClashes(ContractDefinition const & _contract)416 void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _contract)
417 {
418 	map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
419 	for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
420 	{
421 		for (FunctionDefinition const* f: contract->definedFunctions())
422 			if (f->isPartOfExternalInterface())
423 			{
424 				auto functionType = TypeProvider::function(*f);
425 				// under non error circumstances this should be true
426 				if (functionType->interfaceFunctionType())
427 					externalDeclarations[functionType->externalSignature()].emplace_back(
428 						f, functionType->asExternallyCallableFunction(false)
429 					);
430 			}
431 		for (VariableDeclaration const* v: contract->stateVariables())
432 			if (v->isPartOfExternalInterface())
433 			{
434 				auto functionType = TypeProvider::function(*v);
435 				// under non error circumstances this should be true
436 				if (functionType->interfaceFunctionType())
437 					externalDeclarations[functionType->externalSignature()].emplace_back(
438 						v, functionType->asExternallyCallableFunction(false)
439 					);
440 			}
441 	}
442 	for (auto const& it: externalDeclarations)
443 		for (size_t i = 0; i < it.second.size(); ++i)
444 			for (size_t j = i + 1; j < it.second.size(); ++j)
445 				if (!it.second[i].second->hasEqualParameterTypes(*it.second[j].second))
446 					m_errorReporter.typeError(
447 						9914_error,
448 						it.second[j].first->location(),
449 						"Function overload clash during conversion to external types for arguments."
450 					);
451 }
452 
checkHashCollisions(ContractDefinition const & _contract)453 void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contract)
454 {
455 	set<util::FixedHash<4>> hashes;
456 	for (auto const& it: _contract.interfaceFunctionList())
457 	{
458 		util::FixedHash<4> const& hash = it.first;
459 		if (hashes.count(hash))
460 			m_errorReporter.fatalTypeError(
461 				1860_error,
462 				_contract.location(),
463 				string("Function signature hash collision for ") + it.second->externalSignature()
464 			);
465 		hashes.insert(hash);
466 	}
467 }
468 
checkLibraryRequirements(ContractDefinition const & _contract)469 void ContractLevelChecker::checkLibraryRequirements(ContractDefinition const& _contract)
470 {
471 	if (!_contract.isLibrary())
472 		return;
473 
474 	if (!_contract.baseContracts().empty())
475 		m_errorReporter.typeError(9469_error, _contract.location(), "Library is not allowed to inherit.");
476 
477 	for (auto const& var: _contract.stateVariables())
478 		if (!var->isConstant())
479 			m_errorReporter.typeError(9957_error, var->location(), "Library cannot have non-constant state variables");
480 }
481 
checkBaseABICompatibility(ContractDefinition const & _contract)482 void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _contract)
483 {
484 	if (*_contract.sourceUnit().annotation().useABICoderV2)
485 		return;
486 
487 	if (_contract.isLibrary())
488 	{
489 		solAssert(
490 			_contract.baseContracts().empty() || m_errorReporter.hasErrors(),
491 			"Library is not allowed to inherit"
492 		);
493 		return;
494 	}
495 
496 	SecondarySourceLocation errors;
497 
498 	// interfaceFunctionList contains all inherited functions as well
499 	for (auto const& func: _contract.interfaceFunctionList())
500 	{
501 		solAssert(func.second->hasDeclaration(), "Function has no declaration?!");
502 
503 		if (!*func.second->declaration().sourceUnit().annotation().useABICoderV2)
504 			continue;
505 
506 		auto const& currentLoc = func.second->declaration().location();
507 
508 		for (Type const* paramType: func.second->parameterTypes() + func.second->returnParameterTypes())
509 			if (!TypeChecker::typeSupportedByOldABIEncoder(*paramType, false))
510 			{
511 				errors.append("Type only supported by ABIEncoderV2", currentLoc);
512 				break;
513 			}
514 	}
515 
516 	if (!errors.infos.empty())
517 		m_errorReporter.fatalTypeError(
518 			6594_error,
519 			_contract.location(),
520 			errors,
521 			std::string("Contract \"") +
522 			_contract.name() +
523 			"\" does not use ABI coder v2 but wants to inherit from a contract " +
524 			"which uses types that require it. " +
525 			"Use \"pragma abicoder v2;\" for the inheriting contract as well to enable the feature."
526 		);
527 
528 }
529 
checkPayableFallbackWithoutReceive(ContractDefinition const & _contract)530 void ContractLevelChecker::checkPayableFallbackWithoutReceive(ContractDefinition const& _contract)
531 {
532 	if (auto const* fallback = _contract.fallbackFunction())
533 		if (fallback->isPayable() && !_contract.interfaceFunctionList().empty() && !_contract.receiveFunction())
534 			m_errorReporter.warning(
535 				3628_error,
536 				_contract.location(),
537 				"This contract has a payable fallback function, but no receive ether function. Consider adding a receive ether function.",
538 				SecondarySourceLocation{}.append("The payable fallback function is defined here.", fallback->location())
539 			);
540 }
541 
checkStorageSize(ContractDefinition const & _contract)542 void ContractLevelChecker::checkStorageSize(ContractDefinition const& _contract)
543 {
544 	bigint size = 0;
545 	for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts | ranges::views::reverse)
546 		for (VariableDeclaration const* variable: contract->stateVariables())
547 			if (!(variable->isConstant() || variable->immutable()))
548 			{
549 				size += variable->annotation().type->storageSizeUpperBound();
550 				if (size >= bigint(1) << 256)
551 				{
552 					m_errorReporter.typeError(7676_error, _contract.location(), "Contract requires too much storage.");
553 					break;
554 				}
555 			}
556 }
557