The current implementation of ethereum.ABI does not properly differentiate between 'dynamic' and 'static' types. In particular, it incorrectly treats fixed-size arrays of non-dynamic elements as dynamic types and it treats tuples with a dynamic element as non-dynamic types.
Fixing this completely requires adding new grammar rules to the YACC grammar in abitypes.py and making the corresponding changes to abi.py.
This a simple example where the invalid serialization leads to wrong results:
from manticore.ethereum import ManticoreEVM, ABI
from manticore.core.smtlib.visitors import to_constant
m = ManticoreEVM(procs=4) # initiate the blockchain
source_code = '''
pragma solidity ^0.4.24;
contract Trivial {
function f(uint a) public returns (uint) {
return a;
}
function f1(uint[1] a) public returns (uint) {
return a[0];
}
}
'''
creator_account = m.create_account(balance=1000)
contract = m.solidity_create_contract(source_code, owner=creator_account)
# Correctly prints 123.
contract.f(123)
print(ABI.deserialize('uint', to_constant(m.world.transactions[-1].return_data)))
# Incorrectly prints 32 (the offset of the data of the incorrectly dynamically encoded
# array from the start of the encoded arguments).
contract.f1([123])
print(ABI.deserialize('uint', to_constant(m.world.transactions[-1].return_data)))
The current implementation of
ethereum.ABI
does not properly differentiate between 'dynamic' and 'static' types. In particular, it incorrectly treats fixed-size arrays of non-dynamic elements as dynamic types and it treats tuples with a dynamic element as non-dynamic types.Fixing this completely requires adding new grammar rules to the YACC grammar in
abitypes.py
and making the corresponding changes toabi.py
.This a simple example where the invalid serialization leads to wrong results: