Python-solidity-parser 无法处理 throw 关键字

Python-solidity-parser failed to handle throw keyword

我尝试使用 python-solidity-parser (https://github.com/ConsenSys/python-solidity-parser)

解析以下代码
pragma solidity ^0.4.13; 
contract someContract { 
      mapping(address => uint) balances; 
     
      function deposit() payable {
            balances[msg.sender] += msg.value; 
      } 
function withdrawOkayish(uint amount) { 
     if(balances[msg.sender] >= amount) { 
          balances[msg.sender] -= amount;    if(!msg.sender.send(amount)) { throw; } 
   } 
 } 
function withdrawBad2(uint amount) { 
    if(balances[msg.sender] >= amount) { 
        balances[msg.sender] -= amount;   
    if(!msg.sender.call.gas(2500000).value(amount)()) { throw; } 
 } 
} 

}

它产生以下输出

{'children': [{'name': 'solidity',
               'type': 'PragmaDirective',
               'value': '^0.4.13'},
              {'baseContracts': [],
               'kind': 'contract',
               'name': 'someContract',
               'subNodes': [{'initialValue': None,
                             'type': 'StateVariableDeclaration',
                             'variables': [{'expression': None,
                                            'isDeclaredConst': False,
                                            'isIndexed': False,
                                            'isStateVar': True,
                                            'name': 'balances',
                                            'type': 'VariableDeclaration',
                                            'typeName': {'keyType': {'name': 'address',
                                                                     'type': 'ElementaryTypeName'},
                                                         'type': 'Mapping',
                                                         'valueType': {'name': 'uint',
                                                                       'type': 'ElementaryTypeName'}},
                                            'visibility': 'default'}]},
                            {'body': {'statements': [{'expression': {'left': {'base': {'name': 'balances',
                                                                                       'type': 'Identifier'},
                                                                              'index': {'expression': {'name': 'msg',
                                                                                                       'type': 'Identifier'},
                                                                                        'memberName': 'sender',
                                                                                        'type': 'MemberAccess'},
                                                                              'type': 'IndexAccess'},
                                                                     'operator': '+=',
                                                                     'right': {'expression': {'name': 'msg',
                                                                                              'type': 'Identifier'},
                                                                               'memberName': 'value',
                                                                               'type': 'MemberAccess'},
                                                                     'type': 'BinaryOperation'},
                                                      'type': 'ExpressionStatement'}],
                                      'type': 'Block'},
                             'isConstructor': False,
                             'modifiers': [],
                             'name': 'deposit',
                             'parameters': {'parameters': [],
                                            'type': 'ParameterList'},
                             'returnParameters': [],
                             'stateMutability': 'payable',
                             'type': 'FunctionDefinition',
                             'visibility': 'default'},
                            {'body': {'statements': [{'FalseBody': None,
                                                      'TrueBody': {'statements': [{'expression': {'left': {'base': {'name': 'balances',
                                                                                                                    'type': 'Identifier'},
                                                                                                           'index': {'expression': {'name': 'msg',
                                                                                                                                    'type': 'Identifier'},
                                                                                                                     'memberName': 'sender',
                                                                                                                     'type': 'MemberAccess'},
                                                                                                           'type': 'IndexAccess'},
                                                                                                  'operator': '-=',
                                                                                                  'right': {'name': 'amount',
                                                                                                            'type': 'Identifier'},
                                                                                                  'type': 'BinaryOperation'},
                                                                                   'type': 'ExpressionStatement'},
                                                                                  {'FalseBody': None,
                                                                                   'TrueBody': {'statements': [';'],
                                                                                                'type': 'Block'},
                                                                                   'condition': {'isPrefix': True,
                                                                                                 'operator': '!',
                                                                                                 'subExpression': {'arguments': [{'name': 'amount',
                                                                                                                                  'type': 'Identifier'}],
                                                                                                                   'expression': {'expression': {'expression': {'name': 'msg',
                                                                                                                                                                'type': 'Identifier'},
                                                                                                                                                 'memberName': 'sender',
                                                                                                                                                 'type': 'MemberAccess'},
                                                                                                                                  'memberName': 'send',
                                                                                                                                  'type': 'MemberAccess'},
                                                                                                                   'names': [],
                                                                                                                   'type': 'FunctionCall'},
                                                                                                 'type': 'UnaryOperation'},
                                                                                   'type': 'IfStatement'}],
                                                                   'type': 'Block'},
                                                      'condition': {'left': {'base': {'name': 'balances',
                                                                                      'type': 'Identifier'},
                                                                             'index': {'expression': {'name': 'msg',
                                                                                                      'type': 'Identifier'},
                                                                                       'memberName': 'sender',
                                                                                       'type': 'MemberAccess'},
                                                                             'type': 'IndexAccess'},
                                                                    'operator': '>=',
                                                                    'right': {'name': 'amount',
                                                                              'type': 'Identifier'},
                                                                    'type': 'BinaryOperation'},
                                                      'type': 'IfStatement'}],
                                      'type': 'Block'},
                             'isConstructor': False,
                             'modifiers': [],
                             'name': 'withdrawOkayish',
                             'parameters': {'parameters': [{'isIndexed': False,
                                                            'isStateVar': False,
                                                            'name': 'amount',
                                                            'storageLocation': None,
                                                            'type': 'Parameter',
                                                            'typeName': {'name': 'uint',
                                                                         'type': 'ElementaryTypeName'}}],
                                            'type': 'ParameterList'},
                             'returnParameters': [],
                             'stateMutability': None,
                             'type': 'FunctionDefinition',
                             'visibility': 'default'},
                            {'body': {'statements': [{'FalseBody': None,
                                                      'TrueBody': {'statements': [{'expression': {'left': {'base': {'name': 'balances',
                                                                                                                    'type': 'Identifier'},
                                                                                                           'index': {'expression': {'name': 'msg',
                                                                                                                                    'type': 'Identifier'},
                                                                                                                     'memberName': 'sender',
                                                                                                                     'type': 'MemberAccess'},
                                                                                                           'type': 'IndexAccess'},
                                                                                                  'operator': '-=',
                                                                                                  'right': {'name': 'amount',
                                                                                                            'type': 'Identifier'},
                                                                                                  'type': 'BinaryOperation'},
                                                                                   'type': 'ExpressionStatement'},
                                                                                  {'FalseBody': None,
                                                                                   'TrueBody': {'statements': [';'],
                                                                                                'type': 'Block'},
                                                                                   'condition': {'isPrefix': True,
                                                                                                 'operator': '!',
                                                                                                 'subExpression': {'arguments': [],
                                                                                                                   'expression': {'arguments': [{'name': 'amount',
                                                                                                                                                 'type': 'Identifier'}],
                                                                                                                                  'expression': {'expression': {'arguments': [{'number': '2500000',
                                                                                                                                                                               'subdenomination': None,
                                                                                                                                                                               'type': 'NumberLiteral'}],
                                                                                                                                                                'expression': {'expression': {'expression': {'expression': {'name': 'msg',
                                                                                                                                                                                                                            'type': 'Identifier'},
                                                                                                                                                                                                             'memberName': 'sender',
                                                                                                                                                                                                             'type': 'MemberAccess'},
                                                                                                                                                                                              'memberName': 'call',
                                                                                                                                                                                              'type': 'MemberAccess'},
                                                                                                                                                                               'memberName': 'gas',
                                                                                                                                                                               'type': 'MemberAccess'},
                                                                                                                                                                'names': [],
                                                                                                                                                                'type': 'FunctionCall'},
                                                                                                                                                 'memberName': 'value',
                                                                                                                                                 'type': 'MemberAccess'},
                                                                                                                                  'names': [],
                                                                                                                                  'type': 'FunctionCall'},
                                                                                                                   'names': [],
                                                                                                                   'type': 'FunctionCall'},
                                                                                                 'type': 'UnaryOperation'},
                                                                                   'type': 'IfStatement'}],
                                                                   'type': 'Block'},
                                                      'condition': {'left': {'base': {'name': 'balances',
                                                                                      'type': 'Identifier'},
                                                                             'index': {'expression': {'name': 'msg',
                                                                                                      'type': 'Identifier'},
                                                                                       'memberName': 'sender',
                                                                                       'type': 'MemberAccess'},
                                                                             'type': 'IndexAccess'},
                                                                    'operator': '>=',
                                                                    'right': {'name': 'amount',
                                                                              'type': 'Identifier'},
                                                                    'type': 'BinaryOperation'},
                                                      'type': 'IfStatement'}],
                                      'type': 'Block'},
                             'isConstructor': False,
                             'modifiers': [],
                             'name': 'withdrawBad2',
                             'parameters': {'parameters': [{'isIndexed': False,
                                                            'isStateVar': False,
                                                            'name': 'amount',
                                                            'storageLocation': None,
                                                            'type': 'Parameter',
                                                            'typeName': {'name': 'uint',
                                                                         'type': 'ElementaryTypeName'}}],
                                            'type': 'ParameterList'},
                             'returnParameters': [],
                             'stateMutability': None,
                             'type': 'FunctionDefinition',
                             'visibility': 'default'}],
               'type': 'ContractDefinition'}],
 'type': 'SourceUnit'}

我发现它不处理 throw 关键字。两个 if case 块都只包含 ';'。 我找不到解决此问题的方法。有什么办法可以解决这个问题吗

在此处创建问题:https://github.com/ConsenSys/python-solidity-parser/issues/11

(仍然...不是 Python 程序员)

我费了好大劲才找到修改。 (例如,在我的系统上,scripts/antlr4.sh(顺便说一句,文档说 script/antlr4,所以...这是一个很好的开始。)没有正确执行)

也就是说,在 solidity_antlr4 目录中有一个 parser.py 源文件。

缺少 visitThrowStatement 方法。

我补充了:

    def visitThrowStatement(self,ctx):
        return Node(ctx=ctx,
                    type='ThrowStatement')

其他 visits* defs.

将我的代码移动到站点包后(告诉你...不是 Python 程序,而且肯定是在这里乱搞,所以我敢肯定这不是实现此更改的正确方法)

我的 运行 python3 -m solidity_parser parse ./samples/so_example.sol > testParse.txt 输出(其中 ./samples/so_example.sol 是您的样本输入)是:

{'children': [{'name': 'solidity',
               'type': 'PragmaDirective',
               'value': '^0.4.13'},
              {'baseContracts': [],
               'kind': 'contract',
               'name': 'someContract',
               'subNodes': [{'initialValue': None,
                             'type': 'StateVariableDeclaration',
                             'variables': [{'expression': None,
                                            'isDeclaredConst': False,
                                            'isIndexed': False,
                                            'isStateVar': True,
                                            'name': 'balances',
                                            'type': 'VariableDeclaration',
                                            'typeName': {'keyType': {'name': 'address',
                                                                     'type': 'ElementaryTypeName'},
                                                         'type': 'Mapping',
                                                         'valueType': {'name': 'uint',
                                                                       'type': 'ElementaryTypeName'}},
                                            'visibility': 'default'}]},
                            {'body': {'statements': [{'expression': {'left': {'base': {'name': 'balances',
                                                                                       'type': 'Identifier'},
                                                                              'index': {'expression': {'name': 'msg',
                                                                                                       'type': 'Identifier'},
                                                                                        'memberName': 'sender',
                                                                                        'type': 'MemberAccess'},
                                                                              'type': 'IndexAccess'},
                                                                     'operator': '+=',
                                                                     'right': {'expression': {'name': 'msg',
                                                                                              'type': 'Identifier'},
                                                                               'memberName': 'value',
                                                                               'type': 'MemberAccess'},
                                                                     'type': 'BinaryOperation'},
                                                      'type': 'ExpressionStatement'}],
                                      'type': 'Block'},
                             'isConstructor': False,
                             'modifiers': [],
                             'name': 'deposit',
                             'parameters': {'parameters': [],
                                            'type': 'ParameterList'},
                             'returnParameters': [],
                             'stateMutability': 'payable',
                             'type': 'FunctionDefinition',
                             'visibility': 'default'},
                            {'body': {'statements': [{'FalseBody': None,
                                                      'TrueBody': {'statements': [{'expression': {'left': {'base': {'name': 'balances',
                                                                                                                    'type': 'Identifier'},
                                                                                                           'index': {'expression': {'name': 'msg',
                                                                                                                                    'type': 'Identifier'},
                                                                                                                     'memberName': 'sender',
                                                                                                                     'type': 'MemberAccess'},
                                                                                                           'type': 'IndexAccess'},
                                                                                                  'operator': '-=',
                                                                                                  'right': {'name': 'amount',
                                                                                                            'type': 'Identifier'},
                                                                                                  'type': 'BinaryOperation'},
                                                                                   'type': 'ExpressionStatement'},
                                                                                  {'FalseBody': None,
                                                                                   'TrueBody': {'statements': [{'type': 'ThrowStatement'}],
                                                                                                'type': 'Block'},
                                                                                   'condition': {'isPrefix': True,
                                                                                                 'operator': '!',
                                                                                                 'subExpression': {'arguments': [{'name': 'amount',
                                                                                                                                  'type': 'Identifier'}],
                                                                                                                   'expression': {'expression': {'expression': {'name': 'msg',
                                                                                                                                                                'type': 'Identifier'},
                                                                                                                                                 'memberName': 'sender',
                                                                                                                                                 'type': 'MemberAccess'},
                                                                                                                                  'memberName': 'send',
                                                                                                                                  'type': 'MemberAccess'},
                                                                                                                   'names': [],
                                                                                                                   'type': 'FunctionCall'},
                                                                                                 'type': 'UnaryOperation'},
                                                                                   'type': 'IfStatement'}],
                                                                   'type': 'Block'},
                                                      'condition': {'left': {'base': {'name': 'balances',
                                                                                      'type': 'Identifier'},
                                                                             'index': {'expression': {'name': 'msg',
                                                                                                      'type': 'Identifier'},
                                                                                       'memberName': 'sender',
                                                                                       'type': 'MemberAccess'},
                                                                             'type': 'IndexAccess'},
                                                                    'operator': '>=',
                                                                    'right': {'name': 'amount',
                                                                              'type': 'Identifier'},
                                                                    'type': 'BinaryOperation'},
                                                      'type': 'IfStatement'}],
                                      'type': 'Block'},
                             'isConstructor': False,
                             'modifiers': [],
                             'name': 'withdrawOkayish',
                             'parameters': {'parameters': [{'isIndexed': False,
                                                            'isStateVar': False,
                                                            'name': 'amount',
                                                            'storageLocation': None,
                                                            'type': 'Parameter',
                                                            'typeName': {'name': 'uint',
                                                                         'type': 'ElementaryTypeName'}}],
                                            'type': 'ParameterList'},
                             'returnParameters': [],
                             'stateMutability': None,
                             'type': 'FunctionDefinition',
                             'visibility': 'default'},
                            {'body': {'statements': [{'FalseBody': None,
                                                      'TrueBody': {'statements': [{'expression': {'left': {'base': {'name': 'balances',
                                                                                                                    'type': 'Identifier'},
                                                                                                           'index': {'expression': {'name': 'msg',
                                                                                                                                    'type': 'Identifier'},
                                                                                                                     'memberName': 'sender',
                                                                                                                     'type': 'MemberAccess'},
                                                                                                           'type': 'IndexAccess'},
                                                                                                  'operator': '-=',
                                                                                                  'right': {'name': 'amount',
                                                                                                            'type': 'Identifier'},
                                                                                                  'type': 'BinaryOperation'},
                                                                                   'type': 'ExpressionStatement'},
                                                                                  {'FalseBody': None,
                                                                                   'TrueBody': {'statements': [{'type': 'ThrowStatement'}],
                                                                                                'type': 'Block'},
                                                                                   'condition': {'isPrefix': True,
                                                                                                 'operator': '!',
                                                                                                 'subExpression': {'arguments': [],
                                                                                                                   'expression': {'arguments': [{'name': 'amount',
                                                                                                                                                 'type': 'Identifier'}],
                                                                                                                                  'expression': {'expression': {'arguments': [{'number': '2500000',
                                                                                                                                                                               'subdenomination': None,
                                                                                                                                                                               'type': 'NumberLiteral'}],
                                                                                                                                                                'expression': {'expression': {'expression': {'expression': {'name': 'msg',
                                                                                                                                                                                                                            'type': 'Identifier'},
                                                                                                                                                                                                             'memberName': 'sender',
                                                                                                                                                                                                             'type': 'MemberAccess'},
                                                                                                                                                                                              'memberName': 'call',
                                                                                                                                                                                              'type': 'MemberAccess'},
                                                                                                                                                                               'memberName': 'gas',
                                                                                                                                                                               'type': 'MemberAccess'},
                                                                                                                                                                'names': [],
                                                                                                                                                                'type': 'FunctionCall'},
                                                                                                                                                 'memberName': 'value',
                                                                                                                                                 'type': 'MemberAccess'},
                                                                                                                                  'names': [],
                                                                                                                                  'type': 'FunctionCall'},
                                                                                                                   'names': [],
                                                                                                                   'type': 'FunctionCall'},
                                                                                                 'type': 'UnaryOperation'},
                                                                                   'type': 'IfStatement'}],
                                                                   'type': 'Block'},
                                                      'condition': {'left': {'base': {'name': 'balances',
                                                                                      'type': 'Identifier'},
                                                                             'index': {'expression': {'name': 'msg',
                                                                                                      'type': 'Identifier'},
                                                                                       'memberName': 'sender',
                                                                                       'type': 'MemberAccess'},
                                                                             'type': 'IndexAccess'},
                                                                    'operator': '>=',
                                                                    'right': {'name': 'amount',
                                                                              'type': 'Identifier'},
                                                                    'type': 'BinaryOperation'},
                                                      'type': 'IfStatement'}],
                                      'type': 'Block'},
                             'isConstructor': False,
                             'modifiers': [],
                             'name': 'withdrawBad2',
                             'parameters': {'parameters': [{'isIndexed': False,
                                                            'isStateVar': False,
                                                            'name': 'amount',
                                                            'storageLocation': None,
                                                            'type': 'Parameter',
                                                            'typeName': {'name': 'uint',
                                                                         'type': 'ElementaryTypeName'}}],
                                            'type': 'ParameterList'},
                             'returnParameters': [],
                             'stateMutability': None,
                             'type': 'FunctionDefinition',
                             'visibility': 'default'}],
               'type': 'ContractDefinition'}],
 'type': 'SourceUnit'}

相关摘录示例:

 'TrueBody': {'statements': [{'type': 'ThrowStatement'}],
                                                                                                'type': 'Block'},

我什至不知道这是否是正确的内容,但它确实表明解决方案将是通过实施 visitThrowStatement 进行重建。

(它不存在,会让我怀疑其他访问者方法也可能丢失。)