@@ -64,43 +64,91 @@ string Contract::SetupContractData(const char* func, ...)
6464 }
6565 }
6666
67+ vector<string> abiBlocks;
68+ vector<bool > isDynamic;
69+ int dynamicStartPointer = 0 ;
70+
6771 va_list args;
6872 va_start (args, func);
6973 for ( int i = 0 ; i < paramCount; ++i ) {
7074 if (strstr (params[i].c_str (), " uint" ) != NULL && strstr (params[i].c_str (), " []" ) != NULL )
7175 {
7276 // value array
7377 string output = GenerateBytesForUIntArray (va_arg (args, vector<uint32_t > *));
74- ret = ret + output;
78+ abiBlocks.push_back (output);
79+ isDynamic.push_back (false );
80+ dynamicStartPointer += 0x20 ;
7581 }
7682 else if (strncmp (params[i].c_str (), " uint" , sizeof (" uint" )) == 0 || strncmp (params[i].c_str (), " uint256" , sizeof (" uint256" )) == 0 )
7783 {
7884 string output = GenerateBytesForUint (va_arg (args, uint256_t *));
79- ret = ret + output;
85+ abiBlocks.push_back (output);
86+ isDynamic.push_back (false );
87+ dynamicStartPointer += 0x20 ;
8088 }
8189 else if (strncmp (params[i].c_str (), " int" , sizeof (" int" )) == 0 || strncmp (params[i].c_str (), " bool" , sizeof (" bool" )) == 0 )
8290 {
8391 string output = GenerateBytesForInt (va_arg (args, int32_t ));
84- ret = ret + string (output);
92+ abiBlocks.push_back (output);
93+ isDynamic.push_back (false );
94+ dynamicStartPointer += 0x20 ;
8595 }
8696 else if (strncmp (params[i].c_str (), " address" , sizeof (" address" )) == 0 )
8797 {
8898 string output = GenerateBytesForAddress (va_arg (args, string *));
89- ret = ret + string (output);
99+ abiBlocks.push_back (output);
100+ isDynamic.push_back (false );
101+ dynamicStartPointer += 0x20 ;
90102 }
91103 else if (strncmp (params[i].c_str (), " string" , sizeof (" string" )) == 0 )
92104 {
93105 string output = GenerateBytesForString (va_arg (args, string *));
94- ret = ret + string (output);
106+ abiBlocks.push_back (output);
107+ isDynamic.push_back (true );
108+ dynamicStartPointer += 0x20 ;
95109 }
96110 else if (strncmp (params[i].c_str (), " bytes" , sizeof (" bytes" )) == 0 ) // if sending bytes, take the value in hex
97111 {
98112 string output = GenerateBytesForHexBytes (va_arg (args, string *));
99- ret = ret + string (output);
113+ abiBlocks.push_back (output);
114+ isDynamic.push_back (true );
115+ dynamicStartPointer += 0x20 ;
116+ }
117+ else if (strncmp (params[i].c_str (), " struct" , sizeof (" struct" )) == 0 ) // if sending bytes, take the value in hex
118+ {
119+ string output = GenerateBytesForStruct (va_arg (args, string *));
120+ abiBlocks.push_back (output);
121+ isDynamic.push_back (true );
122+ dynamicStartPointer += 0x20 ;
100123 }
101124 }
102125 va_end (args);
103126
127+ uint256_t abiOffet = uint256_t (dynamicStartPointer);
128+ // now build output - parse 1, standard params
129+ for ( int i = 0 ; i < paramCount; ++i )
130+ {
131+ if (isDynamic[i])
132+ {
133+ ret = ret + abiOffet.str (16 , 64 );
134+ string *outputHex = &abiBlocks[i];
135+ abiOffet += outputHex->size () / 2 ;
136+ }
137+ else
138+ {
139+ ret = ret + abiBlocks[i];
140+ }
141+ }
142+
143+ // parse 2: add dynamic params
144+ for ( int i = 0 ; i < paramCount; ++i )
145+ {
146+ if (isDynamic[i])
147+ {
148+ ret = ret + abiBlocks[i];
149+ }
150+ }
151+
104152 return ret;
105153}
106154
@@ -137,6 +185,15 @@ string Contract::SendTransaction(uint32_t nonceVal, unsigned long long gasPriceV
137185 return web3->EthSendSignedTransaction (¶mStr, param.size ());
138186}
139187
188+ /* *
189+ * Utility functions
190+ **/
191+
192+ void Contract::ReplaceFunction (std::string ¶m, const char * func)
193+ {
194+ param = GenerateContractBytes (func) + param.substr (10 );
195+ }
196+
140197/* *
141198 * Private functions
142199 **/
@@ -217,18 +274,26 @@ string Contract::GenerateBytesForHexBytes(const string *value)
217274 else if (value->at (1 ) == ' x' ) cleaned = value->substr (2 );
218275 string digitsStr = Util::intToHex (cleaned.length () / 2 ); // bytes length will be hex length / 2
219276 string lengthDesignator = string (64 - digitsStr.length (), ' 0' ) + digitsStr;
220- // write designator. TODO: This should be done for multiple inputs not just single inputs
221- lengthDesignator = " 0000000000000000000000000000000000000000000000000000000000000020" + lengthDesignator;
222277 cleaned = lengthDesignator + cleaned;
223278 size_t digits = cleaned.length () % 64 ;
224- return cleaned + string (64 - digits, ' 0' );
279+ return cleaned + (digits > 0 ? string (64 - digits, ' 0' ) : " " );
280+ }
281+
282+ string Contract::GenerateBytesForStruct (const string *value)
283+ {
284+ // struct has no length params: not required
285+ string cleaned = *value;
286+ if (value->at (0 ) == ' x' ) cleaned = value->substr (1 );
287+ else if (value->at (1 ) == ' x' ) cleaned = value->substr (2 );
288+ size_t digits = cleaned.length () % 64 ;
289+ return cleaned + (digits > 0 ? string (64 - digits, ' 0' ) : " " );
225290}
226291
227292string Contract::GenerateBytesForBytes (const char *value, const int len)
228293{
229294 string bytesStr = Util::ConvertBytesToHex ((const uint8_t *)value, len).substr (2 ); // clean hex prefix;
230- size_t digits = bytesStr.length ();
231- return bytesStr + string (64 - digits, ' 0' );
295+ size_t digits = bytesStr.length () % 64 ;
296+ return bytesStr + (digits > 0 ? string (64 - digits, ' 0' ) : " " );
232297}
233298
234299vector<uint8_t > Contract::RlpEncode (
0 commit comments