Browse Source

Polkadot: Bugfix codegen for empty events (#1637)

Slight oversight from #1632: Previously, events always contained at least a
single byte of data (empty events would have the discriminant/index of
the event enum). However now, the data field for empty events is
actually empty, leading the ABI encoder to panic. So in codegen we check if we
have to encode data first and pass a pointer to an empty buffer if not.
Cyrill Leutwiler 1 year ago
parent
commit
05a67069f7

+ 4 - 0
integration/polkadot/events.sol

@@ -10,6 +10,8 @@ contract Events {
     event ThisEventTopicShouldGetHashed(address indexed caller);
     event Event(bool indexed something);
 
+    event Empty();
+
     function emit_event() public {
         emit foo1(254, "hello there");
 
@@ -18,5 +20,7 @@ contract Events {
         emit ThisEventTopicShouldGetHashed(msg.sender);
 
         emit Event(true);
+
+        emit Empty();
     }
 }

+ 8 - 1
integration/polkadot/events.spec.ts

@@ -29,7 +29,7 @@ describe('Deploy events contract and test event data, docs and topics', () => {
         let res0: any = await transaction(tx, alice);
         let events: DecodedEvent[] = res0.contractEvents;
 
-        expect(events.length).toEqual(4);
+        expect(events.length).toEqual(5);
 
         expect(events[0].event.identifier).toBe("Events::foo1");
         expect(events[0].event.docs).toEqual(["Ladida tada"]);
@@ -63,5 +63,12 @@ describe('Deploy events contract and test event data, docs and topics', () => {
         expect(field_topic.length).toBe(1);
         event_topic = await conn.query.system.eventTopics("0xc2bc7a077121efada8bc6a0af16c1e886406e8c2d1716979cb1b92098d8b49bc");
         expect(event_topic.length).toBe(1);
+
+        // The 5th event yields no data and the following event topic:
+        // - blake2x256 sum of its signature: 'Empty()'
+
+        event_topic = await conn.query.system.eventTopics("0x2c54a2a9a9aa474af5d6e2bb2e5a35b84051acaf95b233f98f96860d36f2b81b");
+        expect(event_topic.length).toBe(1);
+        expect(events[4].args.map(a => a.toJSON())).toEqual([]);
     });
 });

+ 15 - 2
src/codegen/events/polkadot.rs

@@ -147,8 +147,21 @@ impl EventEmitter for PolkadotEventEmitter<'_> {
             .args
             .iter()
             .map(|e| expression(e, cfg, contract_no, Some(func), self.ns, vartab, opt))
-            .collect();
-        let encoded_data = abi_encode(&loc, data, self.ns, vartab, cfg, false).0;
+            .collect::<Vec<_>>();
+        let encoded_data = data
+            .is_empty()
+            .then(|| Expression::AllocDynamicBytes {
+                loc,
+                ty: Type::DynamicBytes,
+                size: Expression::NumberLiteral {
+                    loc,
+                    ty: Type::Uint(32),
+                    value: 0.into(),
+                }
+                .into(),
+                initializer: Vec::new().into(),
+            })
+            .unwrap_or_else(|| abi_encode(&loc, data, self.ns, vartab, cfg, false).0);
 
         cfg.add(
             vartab,