2626#include < libsolidity/ast/AST.h>
2727#include < libsolidity/ast/TypeProvider.h>
2828#include < liblangutil/ErrorReporter.h>
29+ #include < libsolutil/Keccak256.h>
30+ #include < libsolutil/StringUtils.h>
31+ #include < libsolutil/FixedHash.h>
2932
3033#include < limits>
3134
3235using namespace solidity ;
3336using namespace solidity ::frontend;
3437using namespace solidity ::langutil;
38+ using namespace solidity ::util;
3539
36- using TypedRational = ConstantEvaluator::TypedRational ;
40+ using TypedValue = ConstantEvaluator::TypedValue ;
3741
3842namespace
3943{
@@ -231,45 +235,67 @@ std::optional<rational> ConstantEvaluator::evaluateUnaryOperator(Token _operator
231235namespace
232236{
233237
234- std::optional<TypedRational> convertType (rational const & _value, Type const & _type)
238+ TypedValue convertType (rational const & _value, Type const & _type)
235239{
236240 if (_type.category () == Type::Category::RationalNumber)
237- return TypedRational {TypeProvider::rationalNumber (_value), _value};
241+ return TypedValue {TypeProvider::rationalNumber (_value), _value};
238242 else if (auto const * integerType = dynamic_cast <IntegerType const *>(&_type))
239243 {
240244 if (_value > integerType->maxValue () || _value < integerType->minValue ())
241- return std:: nullopt ;
245+ return TypedValue{} ;
242246 else
243- return TypedRational {&_type, _value.numerator () / _value.denominator ()};
247+ return TypedValue {&_type, _value.numerator () / _value.denominator ()};
244248 }
245249 else
246- return std::nullopt ;
250+ return TypedValue{};
251+ }
252+
253+ TypedValue convertType (std::string const & _value, Type const & _type)
254+ {
255+ if (
256+ _type.category () != Type::Category::StringLiteral &&
257+ _type.category () != Type::Category::Array
258+ )
259+ return TypedValue{};
260+ return TypedValue{&_type, _value};
247261}
248262
249- std::optional<TypedRational> convertType (std::optional<TypedRational> const & _value, Type const & _type)
263+ TypedValue convertType (TypedValue const & _value, Type const & _type)
250264{
251- return _value ? convertType (_value->value , _type) : std::nullopt ;
265+ return std::visit (util::GenericVisitor{
266+ [&](std::string const & value) {
267+ return convertType (value, _type);
268+ },
269+ [&](rational const & value) {
270+ return convertType (value, _type);
271+ },
272+ [&](std::monostate const &) {
273+ return TypedValue{};
274+ }
275+ }, _value.value );
252276}
253277
254- std::optional<TypedRational> constantToTypedValue (Type const & _type)
278+ TypedValue constantToTypedValue (Type const & _type)
255279{
256280 if (_type.category () == Type::Category::RationalNumber)
257- return TypedRational{&_type, dynamic_cast <RationalNumberType const &>(_type).value ()};
258- else
259- return std::nullopt ;
281+ return TypedValue{&_type, dynamic_cast <RationalNumberType const &>(_type).value ()};
282+ else if (_type.category () == Type::Category::StringLiteral)
283+ return TypedValue{&_type, dynamic_cast <StringLiteralType const &>(_type).value ()};
284+
285+ return TypedValue{};
260286}
261287
262288}
263289
264- std::optional<TypedRational> ConstantEvaluator::evaluate (
290+ TypedValue ConstantEvaluator::evaluate (
265291 langutil::ErrorReporter& _errorReporter,
266292 Expression const & _expr
267293)
268294{
269295 return ConstantEvaluator{_errorReporter}.evaluate (_expr);
270296}
271297
272- std::optional<TypedRational> ConstantEvaluator::tryEvaluate (Expression const & _expr)
298+ TypedValue ConstantEvaluator::tryEvaluate (Expression const & _expr)
273299{
274300 ErrorList errorList;
275301 ErrorReporter errorReporter (errorList);
@@ -279,12 +305,12 @@ std::optional<TypedRational> ConstantEvaluator::tryEvaluate(Expression const& _e
279305 }
280306 catch (FatalError const &)
281307 {
282- return std:: nullopt ;
308+ return TypedValue{} ;
283309 }
284310}
285311
286312
287- std::optional<TypedRational> ConstantEvaluator::evaluate (ASTNode const & _node)
313+ TypedValue ConstantEvaluator::evaluate (ASTNode const & _node)
288314{
289315 if (!m_values.count (&_node))
290316 {
@@ -293,7 +319,7 @@ std::optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
293319 solAssert (varDecl->isConstant (), " " );
294320 // In some circumstances, we do not yet have a type for the variable.
295321 if (!varDecl->value () || !varDecl->type ())
296- m_values[&_node] = std:: nullopt ;
322+ m_values[&_node] = TypedValue{} ;
297323 else
298324 {
299325 m_depth++;
@@ -311,29 +337,29 @@ std::optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
311337 {
312338 expression->accept (*this );
313339 if (!m_values.count (&_node))
314- m_values[&_node] = std:: nullopt ;
340+ m_values[&_node] = TypedValue{} ;
315341 }
316342 }
317343 return m_values.at (&_node);
318344}
319345
320346void ConstantEvaluator::endVisit (UnaryOperation const & _operation)
321347{
322- std::optional<TypedRational> value = evaluate (_operation.subExpression ());
323- if (!value)
348+ TypedValue value = evaluate (_operation.subExpression ());
349+ if (!value. type )
324350 return ;
325351
326- Type const * resultType = value-> type ->unaryOperatorResult (_operation.getOperator ());
352+ Type const * resultType = value. type ->unaryOperatorResult (_operation.getOperator ());
327353 if (!resultType)
328354 return ;
329355 value = convertType (value, *resultType);
330- if (!value)
356+ if (!std::holds_alternative<rational>( value. value ) )
331357 return ;
332358
333- if (std::optional<rational> result = evaluateUnaryOperator (_operation.getOperator (), value-> value ))
359+ if (std::optional<rational> result = evaluateUnaryOperator (_operation.getOperator (), std::get<rational>( value. value ) ))
334360 {
335- std::optional<TypedRational> convertedValue = convertType (*result, *resultType);
336- if (!convertedValue)
361+ TypedValue convertedValue = convertType (*result, *resultType);
362+ if (!convertedValue. type )
337363 m_errorReporter.fatalTypeError (
338364 3667_error,
339365 _operation.location (),
@@ -345,17 +371,17 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
345371
346372void ConstantEvaluator::endVisit (BinaryOperation const & _operation)
347373{
348- std::optional<TypedRational> left = evaluate (_operation.leftExpression ());
349- std::optional<TypedRational> right = evaluate (_operation.rightExpression ());
350- if (!left || !right)
374+ TypedValue left = evaluate (_operation.leftExpression ());
375+ TypedValue right = evaluate (_operation.rightExpression ());
376+ if (!left. type || !right. type )
351377 return ;
352378
353379 // If this is implemented in the future: Comparison operators have a "binaryOperatorResult"
354380 // that is non-bool, but the result has to be bool.
355381 if (TokenTraits::isCompareOp (_operation.getOperator ()))
356382 return ;
357383
358- Type const * resultType = left-> type ->binaryOperatorResult (_operation.getOperator (), right-> type );
384+ Type const * resultType = left. type ->binaryOperatorResult (_operation.getOperator (), right. type );
359385 if (!resultType)
360386 {
361387 m_errorReporter.fatalTypeError (
@@ -364,22 +390,29 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
364390 " Operator " +
365391 std::string (TokenTraits::toString (_operation.getOperator ())) +
366392 " not compatible with types " +
367- left-> type ->toString () +
393+ left. type ->toString () +
368394 " and " +
369- right-> type ->toString ()
395+ right. type ->toString ()
370396 );
371397 return ;
372398 }
373399
374400 left = convertType (left, *resultType);
375401 right = convertType (right, *resultType);
376- if (!left || !right)
402+ if (
403+ !std::holds_alternative<rational>(left.value ) ||
404+ !std::holds_alternative<rational>(right.value )
405+ )
377406 return ;
378407
379- if (std::optional<rational> value = evaluateBinaryOperator (_operation.getOperator (), left->value , right->value ))
408+ if (std::optional<rational> value = evaluateBinaryOperator (
409+ _operation.getOperator (),
410+ std::get<rational>(left.value ),
411+ std::get<rational>(right.value )
412+ ))
380413 {
381- std::optional<TypedRational> convertedValue = convertType (*value, *resultType);
382- if (!convertedValue)
414+ TypedValue convertedValue = convertType (*value, *resultType);
415+ if (!convertedValue. type )
383416 m_errorReporter.fatalTypeError (
384417 2643_error,
385418 _operation.location (),
@@ -407,3 +440,33 @@ void ConstantEvaluator::endVisit(TupleExpression const& _tuple)
407440 if (!_tuple.isInlineArray () && _tuple.components ().size () == 1 )
408441 m_values[&_tuple] = evaluate (*_tuple.components ().front ());
409442}
443+
444+ void ConstantEvaluator::endVisit (FunctionCall const & _functionCall)
445+ {
446+ auto const * builtinFunction = dynamic_cast <MagicVariableDeclaration const *>(ASTNode::referencedDeclaration (_functionCall.expression ()));
447+ if (!builtinFunction)
448+ return ;
449+
450+ auto const * functionType = builtinFunction->functionType (true );
451+ solAssert (functionType);
452+ switch (functionType->kind ())
453+ {
454+ case FunctionType::Kind::ERC7201 :
455+ {
456+ solAssert (_functionCall.arguments ().size () == 1 );
457+ auto stringArg = evaluate (*(_functionCall.arguments ()[0 ].get ()));
458+ if (!std::holds_alternative<std::string>(stringArg.value ))
459+ return ;
460+
461+ h256 innerKeccak = keccak256 (std::get<std::string>(stringArg.value ));
462+ h256 outerKeccak = keccak256 (h256 (u256 (innerKeccak) - 1 ));
463+ outerKeccak.data ()[31 ] = 0 ;
464+ u256 slot = outerKeccak;
465+ solAssert (functionType->returnParameterTypes ().size () == 1 );
466+ m_values[&_functionCall] = TypedValue{functionType->returnParameterTypes ()[0 ], rational{slot}};
467+ break ;
468+ }
469+ default :
470+ break ;
471+ }
472+ }
0 commit comments