@@ -32,6 +32,10 @@ type AllowanceResponse struct {
32
32
Expires json.RawMessage `json:"expires"`
33
33
}
34
34
35
+ func getOwnerEventKey (contractAddr string , tokenID string ) string {
36
+ return fmt .Sprintf ("%s-%s" , contractAddr , tokenID )
37
+ }
38
+
35
39
func (app * App ) AddCosmosEventsToEVMReceiptIfApplicable (ctx sdk.Context , tx sdk.Tx , checksum [32 ]byte , response sdk.DeliverTxHookInput ) {
36
40
// hooks will only be called if DeliverTx is successful
37
41
wasmEvents := GetEventsOfType (response , wasmtypes .WasmModuleEventType )
@@ -43,6 +47,26 @@ func (app *App) AddCosmosEventsToEVMReceiptIfApplicable(ctx sdk.Context, tx sdk.
43
47
// additional gas consumption from EVM receipt generation and event translation
44
48
wasmToEvmEventGasLimit := app .EvmKeeper .GetDeliverTxHookWasmGasLimit (ctx .WithGasMeter (sdk .NewInfiniteGasMeter (1 , 1 )))
45
49
wasmToEvmEventCtx := ctx .WithGasMeter (sdk .NewGasMeterWithMultiplier (ctx , wasmToEvmEventGasLimit ))
50
+ // unfortunately CW721 transfer events differ from ERC721 transfer events
51
+ // in that CW721 include sender (which can be different than owner) whereas
52
+ // ERC721 always include owner. The following logic refer to the owner
53
+ // event emitted before the transfer and use that instead to populate the
54
+ // synthetic ERC721 event.
55
+ ownerEvents := GetEventsOfType (response , wasmtypes .EventTypeCW721PreTransferOwner )
56
+ ownerEventsMap := map [string ][]abci.Event {}
57
+ for _ , ownerEvent := range ownerEvents {
58
+ if len (ownerEvent .Attributes ) != 3 {
59
+ ctx .Logger ().Error ("received owner event with number of attributes != 3" )
60
+ continue
61
+ }
62
+ ownerEventKey := getOwnerEventKey (string (ownerEvent .Attributes [0 ].Value ), string (ownerEvent .Attributes [1 ].Value ))
63
+ if events , ok := ownerEventsMap [ownerEventKey ]; ok {
64
+ ownerEventsMap [ownerEventKey ] = append (events , ownerEvent )
65
+ } else {
66
+ ownerEventsMap [ownerEventKey ] = []abci.Event {ownerEvent }
67
+ }
68
+ }
69
+ cw721TransferCounterMap := map [string ]int {}
46
70
for _ , wasmEvent := range wasmEvents {
47
71
contractAddr , found := GetAttributeValue (wasmEvent , wasmtypes .AttributeKeyContractAddr )
48
72
if ! found {
@@ -60,7 +84,7 @@ func (app *App) AddCosmosEventsToEVMReceiptIfApplicable(ctx sdk.Context, tx sdk.
60
84
// check if there is a ERC721 pointer to contract Addr
61
85
pointerAddr , _ , exists = app .EvmKeeper .GetERC721CW721Pointer (wasmToEvmEventCtx , contractAddr )
62
86
if exists {
63
- log , eligible := app .translateCW721Event (wasmToEvmEventCtx , wasmEvent , pointerAddr , contractAddr , response )
87
+ log , eligible := app .translateCW721Event (wasmToEvmEventCtx , wasmEvent , pointerAddr , contractAddr , ownerEventsMap , cw721TransferCounterMap )
64
88
if eligible {
65
89
log .Index = uint (len (logs ))
66
90
logs = append (logs , log )
@@ -173,7 +197,8 @@ func (app *App) translateCW20Event(ctx sdk.Context, wasmEvent abci.Event, pointe
173
197
return nil , false
174
198
}
175
199
176
- func (app * App ) translateCW721Event (ctx sdk.Context , wasmEvent abci.Event , pointerAddr common.Address , contractAddr string , response sdk.DeliverTxHookInput ) (* ethtypes.Log , bool ) {
200
+ func (app * App ) translateCW721Event (ctx sdk.Context , wasmEvent abci.Event , pointerAddr common.Address , contractAddr string ,
201
+ ownerEventsMap map [string ][]abci.Event , cw721TransferCounterMap map [string ]int ) (* ethtypes.Log , bool ) {
177
202
action , found := GetAttributeValue (wasmEvent , "action" )
178
203
if ! found {
179
204
return nil , false
@@ -184,32 +209,30 @@ func (app *App) translateCW721Event(ctx sdk.Context, wasmEvent abci.Event, point
184
209
tokenID := GetTokenIDAttribute (wasmEvent )
185
210
if tokenID == nil {
186
211
return nil , false
212
+ } else {
213
+ ctx .Logger ().Error ("Translate CW721 error: null token ID" )
187
214
}
188
- sender := common.Hash {}
189
- // unfortunately CW721 transfer events differ from ERC721 transfer events
190
- // in that CW721 include sender (which can be different than owner) whereas
191
- // ERC721 always include owner. The following logic refer to the owner
192
- // event emitted before the transfer and use that instead to populate the
193
- // synthetic ERC721 event.
194
- ownerEvents := GetEventsOfType (response , wasmtypes .EventTypeCW721PreTransferOwner )
195
- for _ , ownerEvent := range ownerEvents {
196
- if len (ownerEvent .Attributes ) != 3 ||
197
- string (ownerEvent .Attributes [0 ].Key ) != wasmtypes .AttributeKeyContractAddr ||
198
- string (ownerEvent .Attributes [0 ].Value ) != contractAddr {
199
- continue
200
- }
201
- tokenIDStr , _ := GetAttributeValue (wasmEvent , "token_id" )
202
- if string (ownerEvent .Attributes [1 ].Key ) != wasmtypes .AttributeKeyTokenId ||
203
- string (ownerEvent .Attributes [1 ].Value ) != tokenIDStr ||
204
- string (ownerEvent .Attributes [2 ].Key ) != wasmtypes .AttributeKeyOwner {
205
- continue
206
- }
207
- ownerAcc , err := sdk .AccAddressFromBech32 (string (ownerEvent .Attributes [2 ].Value ))
208
- if err != nil {
209
- continue
215
+ sender := app .GetEvmAddressAttribute (ctx , wasmEvent , "sender" )
216
+ ownerEventKey := getOwnerEventKey (contractAddr , tokenID .String ())
217
+ var currentCounter int
218
+ if c , ok := cw721TransferCounterMap [ownerEventKey ]; ok {
219
+ currentCounter = c
220
+ }
221
+ cw721TransferCounterMap [ownerEventKey ] = currentCounter + 1
222
+ if ownerEvents , ok := ownerEventsMap [ownerEventKey ]; ok {
223
+ if len (ownerEvents ) > currentCounter {
224
+ ownerSeiAddrStr := string (ownerEvents [currentCounter ].Attributes [2 ].Value )
225
+ if ownerSeiAddr , err := sdk .AccAddressFromBech32 (ownerSeiAddrStr ); err == nil {
226
+ ownerEvmAddr := app .EvmKeeper .GetEVMAddressOrDefault (ctx , ownerSeiAddr )
227
+ sender = common .BytesToHash (ownerEvmAddr [:])
228
+ } else {
229
+ ctx .Logger ().Error ("Translate CW721 error: invalid bech32 owner" , "error" , err , "address" , ownerSeiAddrStr )
230
+ }
231
+ } else {
232
+ ctx .Logger ().Error ("Translate CW721 error: insufficient owner events" , "key" , ownerEventKey , "counter" , currentCounter , "events" , len (ownerEvents ))
210
233
}
211
- owner := app . EvmKeeper . GetEVMAddressOrDefault ( ctx , ownerAcc )
212
- sender = common . BytesToHash ( owner [:] )
234
+ } else {
235
+ ctx . Logger (). Error ( "Translate CW721 error: owner event not found" , "key" , ownerEventKey )
213
236
}
214
237
topics = []common.Hash {
215
238
ERC721TransferTopic ,
0 commit comments