From c661d63f6b37c63fe1b2b4df5d9214a4d9b2b61e Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:56:26 +0000 Subject: [PATCH 1/4] make abi decoder methods static --- crypto/utils/abi_decoder.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/crypto/utils/abi_decoder.py b/crypto/utils/abi_decoder.py index 71082071..53466a4d 100644 --- a/crypto/utils/abi_decoder.py +++ b/crypto/utils/abi_decoder.py @@ -64,32 +64,36 @@ def decode_parameter(self, bytes_data, offset, param): if match: signed = match.group(1) == 'int' bits = int(match.group(2)) - return self.decode_number(bytes_data, offset, bits, signed) + return self.decode_number(bytes_data, offset, signed) if type_ == 'tuple': return self.decode_tuple(bytes_data, offset, param) raise Exception('Unsupported type: ' + type_) - def decode_address(self, bytes_data, offset): + @staticmethod + def decode_address(bytes_data, offset): data = bytes_data[offset:offset+32] address_bytes = data[12:32] address = '0x' + address_bytes.hex() address = get_checksum_address(address) return address, 32 - def decode_bool(self, bytes_data, offset): + @staticmethod + def decode_bool(bytes_data, offset): data = bytes_data[offset:offset+32] value = int.from_bytes(data, byteorder='big') != 0 return value, 32 - def decode_number(self, bytes_data, offset, bits, signed): + @staticmethod + def decode_number(bytes_data, offset, signed): data = bytes_data[offset:offset+32] value = int.from_bytes(data, byteorder='big', signed=signed) return value, 32 - def decode_string(self, bytes_data, offset): - data_offset = self.read_uint(bytes_data, offset) + @classmethod + def decode_string(cls, bytes_data, offset): + data_offset = cls.read_uint(bytes_data, offset) string_offset = offset + data_offset - length = self.read_uint(bytes_data, string_offset) + length = cls.read_uint(bytes_data, string_offset) string_data = bytes_data[string_offset+32:string_offset+32+length] value = string_data.decode('utf-8') return value, 32 @@ -140,6 +144,7 @@ def decode_tuple(self, bytes_data, offset, param): values[name] = value return values, 32 - def read_uint(self, bytes_data, offset): + @staticmethod + def read_uint(bytes_data, offset): data = bytes_data[offset:offset+32] return int.from_bytes(data, byteorder='big') From 7a1b1cdb5226ec04b2cf9db9e63f6646d8e77f4e Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:56:52 +0000 Subject: [PATCH 2/4] argument decoder --- crypto/utils/abi/argument_decoder.py | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 crypto/utils/abi/argument_decoder.py diff --git a/crypto/utils/abi/argument_decoder.py b/crypto/utils/abi/argument_decoder.py new file mode 100644 index 00000000..eecab9c9 --- /dev/null +++ b/crypto/utils/abi/argument_decoder.py @@ -0,0 +1,33 @@ +import binascii +from crypto.utils.abi_decoder import AbiDecoder + +class ArgumentDecoder: + def __init__(self, hex_string: str): + try: + self.bytes = binascii.unhexlify(hex_string) + except binascii.Error: + self.bytes = b'' + + def decode_string(self) -> str: + value, _ = AbiDecoder.decode_string(self.bytes, 0) + + return value + + def decode_address(self) -> str: + value, _ = AbiDecoder.decode_address(self.bytes, 0) + + return value + + def decode_unsigned_int(self) -> int: + value, _ = AbiDecoder.decode_number(self.bytes, 0, False) + + return value + + def decode_signed_int(self) -> int: + value, _ = AbiDecoder.decode_number(self.bytes, 0, True) + + return value + + def decode_bool(self) -> bool: + value, _ = AbiDecoder.decode_bool(self.bytes, 0) + return value From 23a7fb2d808e9420c2efc9f18103d7a751684ae0 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:57:07 +0000 Subject: [PATCH 3/4] test --- tests/utils/abi/test_argument_decoder.py | 54 ++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/utils/abi/test_argument_decoder.py diff --git a/tests/utils/abi/test_argument_decoder.py b/tests/utils/abi/test_argument_decoder.py new file mode 100644 index 00000000..11fffe60 --- /dev/null +++ b/tests/utils/abi/test_argument_decoder.py @@ -0,0 +1,54 @@ +from crypto.utils.abi.argument_decoder import ArgumentDecoder + + +# def test_decode_vote_payload(): +# decoder = ArgumentDecoder() +# function_name = 'vote' +# args = ['0x512F366D524157BcF734546eB29a6d687B762255'] +# data = '0x6dd7d8ea000000000000000000000000512f366d524157bcf734546eb29a6d687b762255' + +# decoded_data = decoder.decode_function_data(data) + +# assert decoded_data == +# 'functionName': function_name, +# 'args': args, + +def test_it_should_decode_address(): + payload = '000000000000000000000000512F366D524157BcF734546eB29a6d687B762255' + expected = '0x512F366D524157BcF734546eB29a6d687B762255' + + decoder = ArgumentDecoder(payload) + + assert decoder.decode_address() == expected + +def test_it_should_decode_unsigned_int(): + payload = '000000000000000000000000000000000000000000000000016345785d8a0000' + expected = 100000000000000000 + + decoder = ArgumentDecoder(payload) + + assert decoder.decode_unsigned_int() == expected + +def test_it_should_decode_signed_int(): + payload = '000000000000000000000000000000000000000000000000016345785d8a0000' + expected = 100000000000000000 + + decoder = ArgumentDecoder(payload) + + assert decoder.decode_signed_int() == expected + +def test_it_should_decode_bool_as_true(): + payload = '0000000000000000000000000000000000000000000000000000000000000001' + expected = True + + decoder = ArgumentDecoder(payload) + + assert decoder.decode_bool() == expected + +def test_it_should_decode_bool_as_false(): + payload = '0000000000000000000000000000000000000000000000000000000000000000' + expected = False + + decoder = ArgumentDecoder(payload) + + assert decoder.decode_bool() == expected From d38abd0b7fdbfa303b957435edd4da42fd16cb33 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:46:54 +0000 Subject: [PATCH 4/4] remove commented code --- tests/utils/abi/test_argument_decoder.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/utils/abi/test_argument_decoder.py b/tests/utils/abi/test_argument_decoder.py index 11fffe60..4feacbdc 100644 --- a/tests/utils/abi/test_argument_decoder.py +++ b/tests/utils/abi/test_argument_decoder.py @@ -1,18 +1,6 @@ from crypto.utils.abi.argument_decoder import ArgumentDecoder -# def test_decode_vote_payload(): -# decoder = ArgumentDecoder() -# function_name = 'vote' -# args = ['0x512F366D524157BcF734546eB29a6d687B762255'] -# data = '0x6dd7d8ea000000000000000000000000512f366d524157bcf734546eb29a6d687b762255' - -# decoded_data = decoder.decode_function_data(data) - -# assert decoded_data == -# 'functionName': function_name, -# 'args': args, - def test_it_should_decode_address(): payload = '000000000000000000000000512F366D524157BcF734546eB29a6d687B762255' expected = '0x512F366D524157BcF734546eB29a6d687B762255'