1717from eth_abi import (
1818 encoding ,
1919)
20+ from eth_abi .base import (
21+ parse_type_str ,
22+ )
23+ from eth_abi .exceptions import (
24+ ValueOutOfBounds ,
25+ )
2026from eth_abi .grammar import (
2127 ABIType ,
2228 TupleType ,
@@ -129,19 +135,6 @@ def filter_by_argument_name(argument_names, contract_abi):
129135 ]
130136
131137
132- def length_of_bytes_type (abi_type ):
133- if not is_bytes_type (abi_type ):
134- raise ValueError (
135- f"Cannot parse length of nonbytes abi-type: { abi_type } "
136- )
137-
138- byte_length = re .search ('(\d{1,2})' , abi_type )
139- if not byte_length :
140- return None
141- else :
142- return int (byte_length .group (0 ))
143-
144-
145138class AddressEncoder (encoding .AddressEncoder ):
146139 @classmethod
147140 def validate_value (cls , value ):
@@ -173,7 +166,6 @@ def validate_value(self, value):
173166class StrictAcceptsHexStrMixin :
174167 def validate_value (self , value ):
175168 if is_text (value ) and value [:2 ] != '0x' :
176- print ('in strict accepts hexstr mixin' )
177169 self .invalidate_value (
178170 value ,
179171 msg = 'hex string must be prefixed with 0x'
@@ -194,15 +186,11 @@ class BytesEncoder(AcceptsHexStrMixin, encoding.BytesEncoder):
194186 pass
195187
196188
197- class StrictBytesEncoder (StrictAcceptsHexStrMixin , encoding .PackedBytesEncoder ):
198- pass
199-
200-
201189class ByteStringEncoder (AcceptsHexStrMixin , encoding .ByteStringEncoder ):
202190 pass
203191
204192
205- class StrictByteStringEncoder (StrictAcceptsHexStrMixin , encoding .PackedByteStringEncoder ):
193+ class StrictByteStringEncoder (StrictAcceptsHexStrMixin , encoding .ByteStringEncoder ):
206194 pass
207195
208196
@@ -221,6 +209,82 @@ def validate_value(cls, value):
221209 super ().validate_value (value )
222210
223211
212+ class ExactLengthBytesEncoder (encoding .BaseEncoder ):
213+ is_big_endian = False
214+ value_bit_size = None
215+ data_byte_size = None
216+ encode_fn = None
217+
218+ def validate (self ):
219+ super ().validate ()
220+
221+ if self .value_bit_size is None :
222+ raise ValueError ("`value_bit_size` may not be none" )
223+ if self .data_byte_size is None :
224+ raise ValueError ("`data_byte_size` may not be none" )
225+ if self .encode_fn is None :
226+ raise ValueError ("`encode_fn` may not be none" )
227+ if self .is_big_endian is None :
228+ raise ValueError ("`is_big_endian` may not be none" )
229+
230+ if self .value_bit_size % 8 != 0 :
231+ raise ValueError (
232+ "Invalid value bit size: {0}. Must be a multiple of 8" .format (
233+ self .value_bit_size ,
234+ )
235+ )
236+
237+ if self .value_bit_size > self .data_byte_size * 8 :
238+ raise ValueError ("Value byte size exceeds data size" )
239+
240+ def encode (self , value ):
241+ self .validate_value (value )
242+ return self .encode_fn (value )
243+
244+ def validate_value (self , value ):
245+ if not is_bytes (value ) and not is_text (value ):
246+ self .invalidate_value (value )
247+
248+ if is_text (value ) and value [:2 ] != '0x' :
249+ self .invalidate_value (
250+ value ,
251+ msg = 'hex string must be prefixed with 0x'
252+ )
253+ elif is_text (value ):
254+ try :
255+ value = decode_hex (value )
256+ except binascii .Error :
257+ self .invalidate_value (
258+ value ,
259+ msg = 'invalid hex string' ,
260+ )
261+
262+ byte_size = self .value_bit_size // 8
263+ if len (value ) > byte_size :
264+ self .invalidate_value (
265+ value ,
266+ exc = ValueOutOfBounds ,
267+ msg = "exceeds total byte size for bytes{} encoding" .format (byte_size ),
268+ )
269+ elif len (value ) < byte_size :
270+ self .invalidate_value (
271+ value ,
272+ exc = ValueOutOfBounds ,
273+ msg = "less than total byte size for bytes{} encoding" .format (byte_size ),
274+ )
275+
276+ @staticmethod
277+ def encode_fn (value ):
278+ return value
279+
280+ @parse_type_str ('bytes' )
281+ def from_type_str (cls , abi_type , registry ):
282+ return cls (
283+ value_bit_size = abi_type .sub * 8 ,
284+ data_byte_size = abi_type .sub ,
285+ )
286+
287+
224288def filter_by_encodability (w3 , args , kwargs , contract_abi ):
225289 return [
226290 function_abi
0 commit comments