From 371e6a480157c1f2eaeb9d3fcab5b8c39614e918 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Mon, 9 Dec 2019 03:26:23 +0300 Subject: [PATCH] Add function selector to FunctionDefinition AST JSON --- Changelog.md | 1 + libsolidity/ast/AST.cpp | 11 +++++++++++ libsolidity/ast/AST.h | 6 ++++++ libsolidity/ast/ASTJsonConverter.cpp | 4 ++++ libsolidity/ast/Types.cpp | 5 +++++ libsolidity/ast/Types.h | 2 ++ 6 files changed, 29 insertions(+) diff --git a/Changelog.md b/Changelog.md index a6d9ab65f..e0d9a9fef 100644 --- a/Changelog.md +++ b/Changelog.md @@ -38,6 +38,7 @@ Language Features: * Introduce ``virtual`` and ``override`` keywords. * Modify ``push(element)`` for dynamic storage arrays such that it does not return the new length anymore. * Yul: Introduce ``leave`` statement that exits the current function. + * JSON AST: Add the function selector of each externally-visible FunctonDefinition to the AST JSON export. Compiler Features: * Allow revert strings to be stripped from the binary using the ``--revert-strings`` option or the ``settings.debug.revertStrings`` setting. diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 34035d536..140fe7a99 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -368,6 +368,11 @@ string FunctionDefinition::externalSignature() const return TypeProvider::function(*this)->externalSignature(); } +string FunctionDefinition::externalIdentifierHex() const +{ + return TypeProvider::function(*this)->externalIdentifierHex(); +} + FunctionDefinitionAnnotation& FunctionDefinition::annotation() const { if (!m_annotation) @@ -596,6 +601,12 @@ set VariableDeclaration::allowedDataLocations() c return set{ Location::Unspecified }; } +string VariableDeclaration::externalIdentifierHex() const +{ + solAssert(isStateVariable() && isPublic(), "Can only be called for public state variables"); + return TypeProvider::function(*this)->externalIdentifierHex(); +} + TypePointer VariableDeclaration::type() const { return annotation().type; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 7ca665890..f761fe7af 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -708,6 +708,9 @@ public: /// arguments separated by commas all enclosed in parentheses without any spaces. std::string externalSignature() const; + /// @returns the external identifier of this function (the hash of the signature) as a hex string. + std::string externalIdentifierHex() const; + ContractDefinition::ContractKind inContractKind() const; TypePointer type() const override; @@ -807,6 +810,9 @@ public: /// @returns a set of allowed storage locations for the variable. std::set allowedDataLocations() const; + /// @returns the external identifier of this variable (the hash of the signature) as a hex string (works only for public state variables). + std::string externalIdentifierHex() const; + TypePointer type() const override; /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 798b71b88..b7b8e9cbc 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -362,6 +362,8 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node) make_pair("implemented", _node.isImplemented()), make_pair("scope", idOrNull(_node.scope())) }; + if (_node.isPartOfExternalInterface()) + attributes.emplace_back("functionSelector", _node.externalIdentifierHex()); if (!_node.annotation().baseFunctions.empty()) attributes.emplace_back(make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true))); if (m_legacy) @@ -384,6 +386,8 @@ bool ASTJsonConverter::visit(VariableDeclaration const& _node) make_pair("scope", idOrNull(_node.scope())), make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }; + if (_node.isStateVariable() && _node.isPublic()) + attributes.emplace_back("functionSelector", _node.externalIdentifierHex()); if (m_inEvent) attributes.emplace_back("indexed", _node.isIndexed()); if (!_node.annotation().baseFunctions.empty()) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 2eada7e5d..e414efb2d 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3191,6 +3191,11 @@ u256 FunctionType::externalIdentifier() const return FixedHash<4>::Arith(FixedHash<4>(dev::keccak256(externalSignature()))); } +string FunctionType::externalIdentifierHex() const +{ + return FixedHash<4>(dev::keccak256(externalSignature())).hex(); +} + bool FunctionType::isPure() const { // TODO: replace this with m_stateMutability == StateMutability::Pure once diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 588e8b8cf..3bc2aa0ae 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1190,6 +1190,8 @@ public: std::string externalSignature() const; /// @returns the external identifier of this function (the hash of the signature). u256 externalIdentifier() const; + /// @returns the external identifier of this function (the hash of the signature) as a hex string. + std::string externalIdentifierHex() const; Declaration const& declaration() const { solAssert(m_declaration, "Requested declaration from a FunctionType that has none");