sbip-sg / solc-json-parser

A Powerful AST Parser for Solidity
12 stars 1 forks source link

Support literal #53

Closed YoHoSo closed 1 year ago

cassc commented 1 year ago

When I tried to get the literals just from a base contract, it looks like all literals are returned:

ast = SolidityAst(f'{contracts_root}/dev/rubic.sol')
print(f'literals: {ast.get_literals("Initializable", only_value=True)}')
{'number': {Literal(token_type='number', sub_type='int_const 0', str_value='0', hex_value='30'),
  Literal(token_type='number', sub_type='int_const 0', str_value='0x00', hex_value='30783030'),
  Literal(token_type='number', sub_type='int_const 1', str_value='1', hex_value='31'),
  Literal(token_type='number', sub_type='int_const 10', str_value='10', hex_value='3130'),
  Literal(token_type='number', sub_type='int_const 1000000', str_value='1e6', hex_value='316536'),
  Literal(token_type='number', sub_type='int_const 15', str_value='0xf', hex_value='307866'),
  Literal(token_type='number', sub_type='int_const 2', str_value='2', hex_value='32'),
 ....
 'other': set()}
YoHoSo commented 1 year ago

oh, ok, just want literals from only the given contract. I will update it

YoHoSo commented 1 year ago

When I tried to get the literals just from a base contract, it looks like all literals are returned:

ast = SolidityAst(f'{contracts_root}/dev/rubic.sol')
print(f'literals: {ast.get_literals("Initializable", only_value=True)}')
{'number': {Literal(token_type='number', sub_type='int_const 0', str_value='0', hex_value='30'),
  Literal(token_type='number', sub_type='int_const 0', str_value='0x00', hex_value='30783030'),
  Literal(token_type='number', sub_type='int_const 1', str_value='1', hex_value='31'),
  Literal(token_type='number', sub_type='int_const 10', str_value='10', hex_value='3130'),
  Literal(token_type='number', sub_type='int_const 1000000', str_value='1e6', hex_value='316536'),
  Literal(token_type='number', sub_type='int_const 15', str_value='0xf', hex_value='307866'),
  Literal(token_type='number', sub_type='int_const 2', str_value='2', hex_value='32'),
 ....
 'other': set()}

I don't seem to find the problem. I can't reproduce your result. Using your example, this is what I will get. Since the only_value is set to True, it should not return the Literal obejct.

ast = SolidityAst(f'.{contracts_root}/dev/rubic.sol')
pprint(ast.get_literals("Initializable", only_value=True))
image
YoHoSo commented 1 year ago

Give this contract, we will output the following literals.

contract Test{
    bool public    c = true;
    uint24[2][5]   x = [[uint24(0x1), 1], [0xffffff, 2], [uint24(0xff), 3], [uint24(0xffff), 4], [0xffffff, 2]];
    int256 public a = -123333;
    uint256 public aa = 0;
    uint256 public ab = 0;

    string public  b = unicode"Hello 😃"; // work only above 0.7.0
    string public  d = "Hello";
    string public  e = "ac43fe";
    bytes          foo = hex"00112233" hex"44556677"; // work only above 0.6.0
    address public f = 0x1234567890123456789012345678901234567890;
    string public  g = '123';

    bytes public  ca = hex"11";
    bytes1 public cb = 0x11;
    bytes public  cd = '0x11';
    uint256 umax = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    function test(uint input) public payable {
        if (msg.value != 12 ether)
            return;
        if (input < 1234 && input > 0x123)
            return;
        if (msg.sender != 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4)
            return;
        string memory test = "my_test_string";

    }

Output literals with only the value:

{'address': {'0x1234567890123456789012345678901234567890',
             '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4'},
 'number': {0,
            1,
            2,
            3,
            4,
            5,
            17,
            255,
            291,
            1234,
            65535,
            123333,
            16777215,
            12000000000000000000,
            115792089237316195423570985008687907853269984665640564039457584007913129639935},
 'other': set(),
 'string': {'\x00\x11"3DUfw',
            '\x11',
            '0x11',
            '123',
            'Hello',
            'Hello 😃',
            'ac43fe',
            'my_test_string'}}
cassc commented 1 year ago

Hi @YoungHS-NUS , for ast.get_literals('Initializable', True), I still find 0123456789abcdef in the results set, is this exepcted? Can you add a test case using this contract?

ast = SolidityAst(file, solc_options={'optimize': True, 'optimize_runs': 200})
ast.get_literals('Initializable', True)
# ==>
{'number': {0, 1, 2, 3, 4, 8, 10, 15, 20, 32, 48, 49, 50, 1000000},
 'string': {'',
  ' is missing role ',
  '0',
  '0123456789abcdef',
  '0x00',
  'AccessControl: account ',
  'AccessControl: can only renounce roles for self',
  'Address: call to non-contract',
  'Address: insufficient balance',
  'Address: insufficient balance for call',
  'Address: low-level call failed',
  'Address: low-level call with value failed',
  'Address: low-level static call failed',
  'Address: static call to non-contract',
  'Address: unable to send value, recipient may have reverted',
  'Initializable: contract is already initialized',
  'Initializable: contract is initializing',
  'Initializable: contract is not initializing',
  'MANAGER_ROLE',
  'Pausable: not paused',
  'Pausable: paused',
  'ReentrancyGuard: reentrant call',
  'SafeERC20: ERC20 operation did not succeed',
  'SafeERC20: approve from non-zero to non-zero allowance',
  'SafeERC20: decreased allowance below zero',
  'SafeERC20: low-level call failed',
  'SafeERC20: permit did not succeed',
  'Strings: hex length insufficient',
  'x'},
 'address': set(),
 'other': set()}
YoHoSo commented 1 year ago

Hi @YoungHS-NUS , for ast.get_literals('Initializable', True), I still find 0123456789abcdef in the results set, is this exepcted? Can you add a test case using this contract?

ast = SolidityAst(file, solc_options={'optimize': True, 'optimize_runs': 200})
ast.get_literals('Initializable', True)
# ==>
{'number': {0, 1, 2, 3, 4, 8, 10, 15, 20, 32, 48, 49, 50, 1000000},
 'string': {'',
  ' is missing role ',
  '0',
  '0123456789abcdef',
  '0x00',
  'AccessControl: account ',
  'AccessControl: can only renounce roles for self',
  'Address: call to non-contract',
  'Address: insufficient balance',
  'Address: insufficient balance for call',
  'Address: low-level call failed',
  'Address: low-level call with value failed',
  'Address: low-level static call failed',
  'Address: static call to non-contract',
  'Address: unable to send value, recipient may have reverted',
  'Initializable: contract is already initialized',
  'Initializable: contract is initializing',
  'Initializable: contract is not initializing',
  'MANAGER_ROLE',
  'Pausable: not paused',
  'Pausable: paused',
  'ReentrancyGuard: reentrant call',
  'SafeERC20: ERC20 operation did not succeed',
  'SafeERC20: approve from non-zero to non-zero allowance',
  'SafeERC20: decreased allowance below zero',
  'SafeERC20: low-level call failed',
  'SafeERC20: permit did not succeed',
  'Strings: hex length insufficient',
  'x'},
 'address': set(),
 'other': set()}

Oh, I finally see your point now. I was testing with the inheritance so I was not able to find the problem. Working on it now.

YoHoSo commented 1 year ago

Hi @YoungHS-NUS , for ast.get_literals('Initializable', True), I still find 0123456789abcdef in the results set, is this exepcted? Can you add a test case using this contract?

ast = SolidityAst(file, solc_options={'optimize': True, 'optimize_runs': 200})
ast.get_literals('Initializable', True)
# ==>
{'number': {0, 1, 2, 3, 4, 8, 10, 15, 20, 32, 48, 49, 50, 1000000},
 'string': {'',
  ' is missing role ',
  '0',
  '0123456789abcdef',
  '0x00',
  'AccessControl: account ',
  'AccessControl: can only renounce roles for self',
  'Address: call to non-contract',
  'Address: insufficient balance',
  'Address: insufficient balance for call',
  'Address: low-level call failed',
  'Address: low-level call with value failed',
  'Address: low-level static call failed',
  'Address: static call to non-contract',
  'Address: unable to send value, recipient may have reverted',
  'Initializable: contract is already initialized',
  'Initializable: contract is initializing',
  'Initializable: contract is not initializing',
  'MANAGER_ROLE',
  'Pausable: not paused',
  'Pausable: paused',
  'ReentrancyGuard: reentrant call',
  'SafeERC20: ERC20 operation did not succeed',
  'SafeERC20: approve from non-zero to non-zero allowance',
  'SafeERC20: decreased allowance below zero',
  'SafeERC20: low-level call failed',
  'SafeERC20: permit did not succeed',
  'Strings: hex length insufficient',
  'x'},
 'address': set(),
 'other': set()}

After update, the output will be:

{
'address': set(),
'number': {1},
'other': set(),
'string': {
            'Initializable: contract is already initialized',
            'Initializable: contract is initializing',
            'Initializable: contract is not initializing'
}
}