3232import  static  org .ethereum .util .ByteUtil .toHexString ;
3333
3434public  abstract  class  SolidityType  {
35+     private  final  static  int  Int32Size  = 32 ;
3536    protected  String  name ;
3637
3738    public  SolidityType (String  name ) {
@@ -56,7 +57,7 @@ public String getCanonicalName() {
5657
5758    @ JsonCreator 
5859    public  static  SolidityType  getType (String  typeName ) {
59-         if  (typeName .contains ( "[ " )) return  ArrayType .getType (typeName );
60+         if  (typeName .endsWith ( "] " )) return  ArrayType .getType (typeName );
6061        if  ("bool" .equals (typeName )) return  new  BoolType ();
6162        if  (typeName .startsWith ("int" )) return  new  IntType (typeName );
6263        if  (typeName .startsWith ("uint" )) return  new  UnsignedIntType (typeName );
@@ -86,7 +87,7 @@ public Object decode(byte[] encoded) {
8687     * which is effectively the int offset to dynamic data 
8788     */ 
8889    public  int  getFixedSize () {
89-         return  32 ;
90+         return  Int32Size ;
9091    }
9192
9293    public  boolean  isDynamicType () {
@@ -101,8 +102,8 @@ public String toString() {
101102
102103    public  static  abstract  class  ArrayType  extends  SolidityType  {
103104        public  static  ArrayType  getType (String  typeName ) {
104-             int  idx1  = typeName .indexOf ("[" );
105-             int  idx2  = typeName .indexOf ("]" ,  idx1 );
105+             int  idx1  = typeName .lastIndexOf ("[" );
106+             int  idx2  = typeName .lastIndexOf ("]" );
106107            if  (idx1  + 1  == idx2 ) {
107108                return  new  DynamicArrayType (typeName );
108109            } else  {
@@ -114,11 +115,7 @@ public static ArrayType getType(String typeName) {
114115
115116        public  ArrayType (String  name ) {
116117            super (name );
117-             int  idx  = name .indexOf ("[" );
118-             String  st  = name .substring (0 , idx );
119-             int  idx2  = name .indexOf ("]" , idx );
120-             String  subDim  = idx2  + 1  == name .length () ? ""  : name .substring (idx2  + 1 );
121-             elementType  = SolidityType .getType (st  + subDim );
118+             elementType  = SolidityType .getType (name .substring (0 , name .lastIndexOf ("[" )));
122119        }
123120
124121        @ Override 
@@ -135,23 +132,42 @@ public byte[] encode(Object value) {
135132                throw  new  RuntimeException ("List value expected for type "  + getName ());
136133            }
137134        }
138-         
139-         @ Override 
140-         public  String  getCanonicalName () {
141-             return  getArrayCanonicalName ("" );
142-         }
143135
144-         String  getArrayCanonicalName (String  parentDimStr ) {
145-             String  myDimStr  = parentDimStr  + getCanonicalDimension ();
146-             if  (getElementType () instanceof  ArrayType ) {
147-                 return  ((ArrayType ) getElementType ()).
148-                         getArrayCanonicalName (myDimStr );
136+         protected  byte [] encodeTuple (List  l ) {
137+             byte [][] elems ;
138+             if  (elementType .isDynamicType ()) {
139+                 elems  = new  byte [l .size () * 2 ][];
140+                 int  offset  = l .size () * Int32Size ;
141+                 for  (int  i  = 0 ; i  < l .size (); i ++) {
142+                     elems [i ] = IntType .encodeInt (offset );
143+                     byte [] encoded  = elementType .encode (l .get (i ));
144+                     elems [l .size () + i ] = encoded ;
145+                     offset  += Int32Size  * ((encoded .length  - 1 ) / Int32Size  + 1 );
146+                 }
149147            } else  {
150-                 return  getElementType ().getCanonicalName () + myDimStr ;
148+                 elems  = new  byte [l .size ()][];
149+                 for  (int  i  = 0 ; i  < l .size (); i ++) {
150+                     elems [i ] = elementType .encode (l .get (i ));
151+                 }
151152            }
153+             return  ByteUtil .merge (elems );
154+         }
155+ 
156+         public  Object [] decodeTuple (byte [] encoded , int  origOffset , int  len ) {
157+             int  offset  = origOffset ;
158+             Object [] ret  = new  Object [len ];
159+ 
160+             for  (int  i  = 0 ; i  < len ; i ++) {
161+                 if  (elementType .isDynamicType ()) {
162+                     ret [i ] = elementType .decode (encoded , origOffset  + IntType .decodeInt (encoded , offset ).intValue ());
163+                 } else  {
164+                     ret [i ] = elementType .decode (encoded , offset );
165+                 }
166+                 offset  += elementType .getFixedSize ();
167+             }
168+             return  ret ;
152169        }
153170
154-         protected  abstract  String  getCanonicalDimension ();
155171
156172        public  SolidityType  getElementType () {
157173            return  elementType ;
@@ -165,52 +181,40 @@ public static class StaticArrayType extends ArrayType {
165181
166182        public  StaticArrayType (String  name ) {
167183            super (name );
168-             int  idx1  = name .indexOf ("[" );
169-             int  idx2  = name .indexOf ("]" ,  idx1 );
184+             int  idx1  = name .lastIndexOf ("[" );
185+             int  idx2  = name .lastIndexOf ("]" );
170186            String  dim  = name .substring (idx1  + 1 , idx2 );
171187            size  = Integer .parseInt (dim );
172188        }
173189
174190        @ Override 
175191        public  String  getCanonicalName () {
176-             if  (elementType  instanceof  ArrayType ) {
177-                 String  elementTypeName  = elementType .getCanonicalName ();
178-                 int  idx1  = elementTypeName .indexOf ("[" );
179-                 return  elementTypeName .substring (0 , idx1 ) + "["  + size  + "]"  + elementTypeName .substring (idx1 );
180-             } else  {
181-                 return  elementType .getCanonicalName () + "["  + size  + "]" ;
182-             }
183-         }
184-         
185-         @ Override 
186-         protected  String  getCanonicalDimension () {
187-             return  "["  + size  + "]" ;
192+             return  getElementType ().getCanonicalName () + "["  + size  + "]" ;
188193        }
189194
190195        @ Override 
191196        public  byte [] encodeList (List  l ) {
192197            if  (l .size () != size ) throw  new  RuntimeException ("List size ("  + l .size () + ") != "  + size  + " for type "  + getName ());
193-             byte [][] elems  = new  byte [size ][];
194-             for  (int  i  = 0 ; i  < l .size (); i ++) {
195-                 elems [i ] = elementType .encode (l .get (i ));
196-             }
197-             return  ByteUtil .merge (elems );
198+             return  encodeTuple (l );
198199        }
199200
200201        @ Override 
201202        public  Object [] decode (byte [] encoded , int  offset ) {
202-             Object [] result  = new  Object [size ];
203-             for  (int  i  = 0 ; i  < size ; i ++) {
204-                 result [i ] = elementType .decode (encoded , offset  + i  * elementType .getFixedSize ());
205-             }
206- 
207-             return  result ;
203+             return  decodeTuple (encoded , offset , size );
208204        }
209205
210206        @ Override 
211207        public  int  getFixedSize () {
212-             // return negative if elementType is dynamic 
213-             return  elementType .getFixedSize () * size ;
208+             if  (isDynamicType ()) {
209+                 return  Int32Size ;
210+             } else  {
211+                 return  elementType .getFixedSize () * size ;
212+             }
213+         }
214+ 
215+         @ Override 
216+         public  boolean  isDynamicType () {
217+             return  getElementType ().isDynamicType () && size  > 0 ;
214218        }
215219    }
216220
@@ -221,60 +225,18 @@ public DynamicArrayType(String name) {
221225
222226        @ Override 
223227        public  String  getCanonicalName () {
224-             if  (elementType  instanceof  ArrayType ) {
225-                 String  elementTypeName  = elementType .getCanonicalName ();
226-                 int  idx1  = elementTypeName .indexOf ("[" );
227-                 return  elementTypeName .substring (0 , idx1 ) + "[]"  + elementTypeName .substring (idx1 );
228-             } else  {
229-                 return  elementType .getCanonicalName () + "[]" ;
230-             }
231-         }
232-         
233-         @ Override 
234-         protected  String  getCanonicalDimension () {
235-             return  "[]" ;
228+             return  elementType .getCanonicalName () + "[]" ;
236229        }
237230
238231        @ Override 
239232        public  byte [] encodeList (List  l ) {
240-             byte [][] elems ;
241-             if  (elementType .isDynamicType ()) {
242-                 elems  = new  byte [l .size () * 2  + 1 ][];
243-                 elems [0 ] = IntType .encodeInt (l .size ());
244-                 int  offset  = l .size () * 32 ;
245-                 for  (int  i  = 0 ; i  < l .size (); i ++) {
246-                     elems [i  + 1 ] = IntType .encodeInt (offset );
247-                     byte [] encoded  = elementType .encode (l .get (i ));
248-                     elems [l .size () + i  + 1 ] = encoded ;
249-                     offset  += 32  * ((encoded .length  - 1 ) / 32  + 1 );
250-                 }
251-             } else  {
252-                 elems  = new  byte [l .size () + 1 ][];
253-                 elems [0 ] = IntType .encodeInt (l .size ());
254- 
255-                 for  (int  i  = 0 ; i  < l .size (); i ++) {
256-                     elems [i  + 1 ] = elementType .encode (l .get (i ));
257-                 }
258-             }
259-             return  ByteUtil .merge (elems );
233+             return  ByteUtil .merge (IntType .encodeInt (l .size ()), encodeTuple (l ));
260234        }
261235
262236        @ Override 
263237        public  Object  decode (byte [] encoded , int  origOffset ) {
264238            int  len  = IntType .decodeInt (encoded , origOffset ).intValue ();
265-             origOffset  += 32 ;
266-             int  offset  = origOffset ;
267-             Object [] ret  = new  Object [len ];
268- 
269-             for  (int  i  = 0 ; i  < len ; i ++) {
270-                 if  (elementType .isDynamicType ()) {
271-                     ret [i ] = elementType .decode (encoded , origOffset  + IntType .decodeInt (encoded , offset ).intValue ());
272-                 } else  {
273-                     ret [i ] = elementType .decode (encoded , offset );
274-                 }
275-                 offset  += elementType .getFixedSize ();
276-             }
277-             return  ret ;
239+             return  decodeTuple (encoded , origOffset  + Int32Size , len );
278240        }
279241
280242        @ Override 
@@ -302,7 +264,7 @@ public byte[] encode(Object value) {
302264            } else  {
303265                throw  new  RuntimeException ("byte[] or String value is expected for type 'bytes'" );
304266            }
305-             byte [] ret  = new  byte [((bb .length  - 1 ) / 32  + 1 ) * 32 ]; // padding 32 bytes 
267+             byte [] ret  = new  byte [((bb .length  - 1 ) / Int32Size  + 1 ) * Int32Size ]; // padding 32 bytes 
306268            System .arraycopy (bb , 0 , ret , 0 , bb .length );
307269
308270            return  ByteUtil .merge (IntType .encodeInt (bb .length ), ret );
@@ -312,7 +274,7 @@ public byte[] encode(Object value) {
312274        public  Object  decode (byte [] encoded , int  offset ) {
313275            int  len  = IntType .decodeInt (encoded , offset ).intValue ();
314276            if  (len  == 0 ) return  new  byte [0 ];
315-             offset  += 32 ;
277+             offset  += Int32Size ;
316278            return  Arrays .copyOfRange (encoded , offset , offset  + len );
317279        }
318280
@@ -350,14 +312,14 @@ public byte[] encode(Object value) {
350312                BigInteger  bigInt  = new  BigInteger (value .toString ());
351313                return  IntType .encodeInt (bigInt );
352314            } else  if  (value  instanceof  String ) {
353-                 byte [] ret  = new  byte [32 ];
315+                 byte [] ret  = new  byte [Int32Size ];
354316                byte [] bytes  = ((String ) value ).getBytes (StandardCharsets .UTF_8 );
355317                System .arraycopy (bytes , 0 , ret , 0 , bytes .length );
356318                return  ret ;
357319            } else  if  (value  instanceof  byte []) {
358320                byte [] bytes  = (byte []) value ;
359-                 byte [] ret  = new  byte [32 ];
360-                 System .arraycopy (bytes , 0 , ret , 32  - bytes .length , bytes .length );
321+                 byte [] ret  = new  byte [Int32Size ];
322+                 System .arraycopy (bytes , 0 , ret , Int32Size  - bytes .length , bytes .length );
361323                return  ret ;
362324            }
363325
@@ -370,7 +332,7 @@ public Object decode(byte[] encoded, int offset) {
370332        }
371333
372334        public  static  byte [] decodeBytes32 (byte [] encoded , int  offset ) {
373-             return  Arrays .copyOfRange (encoded , offset , offset  + 32 );
335+             return  Arrays .copyOfRange (encoded , offset , offset  + Int32Size );
374336        }
375337    }
376338
@@ -443,13 +405,13 @@ public String getCanonicalName() {
443405            return  super .getCanonicalName ();
444406        }
445407        public  static  BigInteger  decodeInt (byte [] encoded , int  offset ) {
446-             return  new  BigInteger (Arrays .copyOfRange (encoded , offset , offset  + 32 ));
408+             return  new  BigInteger (Arrays .copyOfRange (encoded , offset , offset  + Int32Size ));
447409        }
448410        public  static  byte [] encodeInt (int  i ) {
449411            return  encodeInt (new  BigInteger (""  + i ));
450412        }
451413        public  static  byte [] encodeInt (BigInteger  bigInt ) {
452-             return  ByteUtil .bigIntegerToBytesSigned (bigInt , 32 );
414+             return  ByteUtil .bigIntegerToBytesSigned (bigInt , Int32Size );
453415        }
454416        @ Override 
455417        public  Object  decode (byte [] encoded , int  offset ) {
@@ -473,7 +435,7 @@ public String getCanonicalName() {
473435            return  super .getCanonicalName ();
474436        }
475437        public  static  BigInteger  decodeInt (byte [] encoded , int  offset ) {
476-             return  new  BigInteger (1 , Arrays .copyOfRange (encoded , offset , offset  + 32 ));
438+             return  new  BigInteger (1 , Arrays .copyOfRange (encoded , offset , offset  + Int32Size ));
477439        }
478440        public  static  byte [] encodeInt (int  i ) {
479441            return  encodeInt (new  BigInteger (""  + i ));
@@ -482,7 +444,7 @@ public static byte[] encodeInt(BigInteger bigInt) {
482444            if  (bigInt .signum () == -1 ) {
483445                throw  new  RuntimeException ("Wrong value for uint type: "  + bigInt );
484446            }
485-             return  ByteUtil .bigIntegerToBytes (bigInt , 32 );
447+             return  ByteUtil .bigIntegerToBytes (bigInt , Int32Size );
486448        }
487449        @ Override 
488450        public  byte [] encode (Object  value ) {
0 commit comments