@@ -178,9 +178,9 @@ map<string, Builtin> SemanticTest::makeBuiltins()
178
178
};
179
179
}
180
180
181
-
182
181
vector<SideEffectHook> SemanticTest::makeSideEffectHooks () const
183
182
{
183
+ using namespace std ::placeholders;
184
184
return {
185
185
[](FunctionCall const & _call) -> vector<string>
186
186
{
@@ -192,7 +192,111 @@ vector<SideEffectHook> SemanticTest::makeSideEffectHooks() const
192
192
return result;
193
193
}
194
194
return {};
195
- }};
195
+ },
196
+ bind (&SemanticTest::eventSideEffectHook, this , _1)
197
+ };
198
+ }
199
+
200
+ string SemanticTest::formatEventParameter (optional<AnnotatedEventSignature> _signature, bool _indexed, size_t _index, bytes const & _data)
201
+ {
202
+ auto isPrintableASCII = [](bytes const & s)
203
+ {
204
+ bool zeroes = true ;
205
+ for (auto c: s)
206
+ {
207
+ if (static_cast <unsigned >(c) != 0x00 )
208
+ {
209
+ zeroes = false ;
210
+ if (static_cast <unsigned >(c) <= 0x1f || static_cast <unsigned >(c) >= 0x7f )
211
+ return false ;
212
+ } else
213
+ break ;
214
+ }
215
+ return !zeroes;
216
+ };
217
+
218
+ ABIType abiType (ABIType::Type::Hex);
219
+ if (isPrintableASCII (_data))
220
+ abiType = ABIType (ABIType::Type::String);
221
+ if (_signature.has_value ())
222
+ {
223
+ vector<string> const & types = _indexed ? _signature->indexedTypes : _signature->nonIndexedTypes ;
224
+ if (_index < types.size ())
225
+ {
226
+ if (types.at (_index) == " bool" )
227
+ abiType = ABIType (ABIType::Type::Boolean );
228
+ }
229
+ }
230
+ return BytesUtils::formatBytes (_data, abiType);
231
+ }
232
+
233
+ vector<string> SemanticTest::eventSideEffectHook (FunctionCall const &) const
234
+ {
235
+ vector<string> sideEffects;
236
+ vector<LogRecord> recordedLogs = ExecutionFramework::recordedLogs ();
237
+ for (LogRecord const & log : recordedLogs)
238
+ {
239
+ optional<AnnotatedEventSignature> eventSignature;
240
+ if (!log .topics .empty ())
241
+ eventSignature = matchEvent (log .topics [0 ]);
242
+ stringstream sideEffect;
243
+ sideEffect << " emit " ;
244
+ if (eventSignature.has_value ())
245
+ sideEffect << eventSignature.value ().signature ;
246
+ else
247
+ sideEffect << " <anonymous>" ;
248
+
249
+ if (m_contractAddress != log .creator )
250
+ sideEffect << " from 0x" << log .creator ;
251
+
252
+ vector<string> eventStrings;
253
+ size_t index {0 };
254
+ for (h256 const & topic: log .topics )
255
+ {
256
+ if (!eventSignature.has_value () || index != 0 )
257
+ eventStrings.push_back (" #" + formatEventParameter (eventSignature, true , index , topic.asBytes ()));
258
+ ++index ;
259
+ }
260
+
261
+ soltestAssert (log .data .size () % 32 == 0 , " " );
262
+ for (size_t index = 0 ; index < log .data .size () / 32 ; ++index )
263
+ {
264
+ auto begin = log .data .begin () + static_cast <long >(index * 32 );
265
+ bytes const & data = bytes{begin, begin + 32 };
266
+ eventStrings.emplace_back (formatEventParameter (eventSignature, false , index , data));
267
+ }
268
+
269
+ if (!eventStrings.empty ())
270
+ sideEffect << " : " ;
271
+ sideEffect << joinHumanReadable (eventStrings);
272
+ sideEffects.emplace_back (sideEffect.str ());
273
+ }
274
+ return sideEffects;
275
+ }
276
+
277
+ optional<AnnotatedEventSignature> SemanticTest::matchEvent (util::h256 const & hash) const
278
+ {
279
+ optional<AnnotatedEventSignature> result;
280
+ for (string& contractName: m_compiler.contractNames ())
281
+ {
282
+ ContractDefinition const & contract = m_compiler.contractDefinition (contractName);
283
+ for (EventDefinition const * event: contract.events ())
284
+ {
285
+ FunctionTypePointer eventFunctionType = event->functionType (true );
286
+ if (!event->isAnonymous () && keccak256 (eventFunctionType->externalSignature ()) == hash)
287
+ {
288
+ AnnotatedEventSignature eventInfo;
289
+ eventInfo.signature = eventFunctionType->externalSignature ();
290
+ for (auto const & param: event->parameters ())
291
+ if (param->isIndexed ())
292
+ eventInfo.indexedTypes .emplace_back (param->type ()->toString (true ));
293
+ else
294
+ eventInfo.nonIndexedTypes .emplace_back (param->type ()->toString (true ));
295
+ result = eventInfo;
296
+ }
297
+ }
298
+ }
299
+ return result;
196
300
}
197
301
198
302
TestCase::TestResult SemanticTest::run (ostream& _stream, string const & _linePrefix, bool _formatted)
0 commit comments