diff --git a/app/receipt.go b/app/receipt.go index 02a987c8ec..625d2008a3 100644 --- a/app/receipt.go +++ b/app/receipt.go @@ -3,9 +3,6 @@ package app import ( "encoding/json" "fmt" - "math" - "math/big" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" sdk "github.com/cosmos/cosmos-sdk/types" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" @@ -15,6 +12,9 @@ import ( evmkeeper "github.com/sei-protocol/sei-chain/x/evm/keeper" evmtypes "github.com/sei-protocol/sei-chain/x/evm/types" abci "github.com/tendermint/tendermint/abci/types" + "math" + "math/big" + "strings" ) const ShellEVMTxType = math.MaxUint32 @@ -32,6 +32,15 @@ type AllowanceResponse struct { Expires json.RawMessage `json:"expires"` } +func shouldIncludeLog(log *ethtypes.Log) bool { + for _, topic := range log.Topics { + if strings.Contains(topic.String(), "cw721_pretransfer_owner") { + return false + } + } + return true +} + func (app *App) AddCosmosEventsToEVMReceiptIfApplicable(ctx sdk.Context, tx sdk.Tx, checksum [32]byte, response sdk.DeliverTxHookInput) { // hooks will only be called if DeliverTx is successful wasmEvents := GetEventsOfType(response, wasmtypes.WasmModuleEventType) @@ -60,7 +69,7 @@ func (app *App) AddCosmosEventsToEVMReceiptIfApplicable(ctx sdk.Context, tx sdk. // check if there is a ERC721 pointer to contract Addr pointerAddr, _, exists = app.EvmKeeper.GetERC721CW721Pointer(wasmToEvmEventCtx, contractAddr) if exists { - log, eligible := app.translateCW721Event(wasmToEvmEventCtx, wasmEvent, pointerAddr, contractAddr) + log, eligible := app.translateCW721Event(wasmToEvmEventCtx, wasmEvent, pointerAddr, contractAddr, response) if eligible { log.Index = uint(len(logs)) logs = append(logs, log) @@ -81,7 +90,16 @@ func (app *App) AddCosmosEventsToEVMReceiptIfApplicable(ctx sdk.Context, tx sdk. for i, l := range r.Logs { l.Index = uint32(i) } - bloom = ethtypes.CreateBloom(ethtypes.Receipts{ðtypes.Receipt{Logs: evmkeeper.GetLogsForTx(r)}}) + + // For now filter out cw721_pretransfer_owner until next upgrade + filteredLogs := make([]*ethtypes.Log, 0, len(r.Logs)) + for _, log := range evmkeeper.GetLogsForTx(r) { + if shouldIncludeLog(log) { + filteredLogs = append(filteredLogs, log) + } + } + + bloom = ethtypes.CreateBloom(ethtypes.Receipts{ðtypes.Receipt{Logs: filteredLogs}}) r.LogsBloom = bloom[:] _ = app.EvmKeeper.SetTransientReceipt(wasmToEvmEventCtx, txHash, r) } else { @@ -173,7 +191,7 @@ func (app *App) translateCW20Event(ctx sdk.Context, wasmEvent abci.Event, pointe return nil, false } -func (app *App) translateCW721Event(ctx sdk.Context, wasmEvent abci.Event, pointerAddr common.Address, contractAddr string) (*ethtypes.Log, bool) { +func (app *App) translateCW721Event(ctx sdk.Context, wasmEvent abci.Event, pointerAddr common.Address, contractAddr string, response sdk.DeliverTxHookInput) (*ethtypes.Log, bool) { action, found := GetAttributeValue(wasmEvent, "action") if !found { return nil, false @@ -185,9 +203,32 @@ func (app *App) translateCW721Event(ctx sdk.Context, wasmEvent abci.Event, point if tokenID == nil { return nil, false } + sender := app.GetEvmAddressAttribute(ctx, wasmEvent, "sender") + ownerEvents := GetEventsOfType(response, wasmtypes.EventTypeCW721PreTransferOwner) + for _, ownerEvent := range ownerEvents { + if len(ownerEvent.Attributes) != 3 { + continue + } + if string(ownerEvent.Attributes[0].Key) != wasmtypes.AttributeKeyContractAddr || string(ownerEvent.Attributes[0].Value) != contractAddr { + continue + } + tokenIDStr, _ := GetAttributeValue(wasmEvent, "token_id") + if string(ownerEvent.Attributes[1].Key) != wasmtypes.AttributeKeyTokenId || string(ownerEvent.Attributes[1].Value) != tokenIDStr { + continue + } + if string(ownerEvent.Attributes[2].Key) != wasmtypes.AttributeKeyOwner { + continue + } + ownerAcc, err := sdk.AccAddressFromBech32(string(ownerEvent.Attributes[2].Value)) + if err != nil { + continue + } + owner := app.EvmKeeper.GetEVMAddressOrDefault(ctx, ownerAcc) + sender = common.BytesToHash(owner[:]) + } topics = []common.Hash{ ERC721TransferTopic, - app.GetEvmAddressAttribute(ctx, wasmEvent, "sender"), + sender, app.GetEvmAddressAttribute(ctx, wasmEvent, "recipient"), common.BigToHash(tokenID), } diff --git a/app/receipt_test.go b/app/receipt_test.go index bfdff291b8..efe3ce3b95 100644 --- a/app/receipt_test.go +++ b/app/receipt_test.go @@ -168,7 +168,8 @@ func TestEvmEventsForCw721(t *testing.T) { amt := sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(1000000000000))) k.BankKeeper().MintCoins(ctx, "evm", amt) k.BankKeeper().SendCoinsFromModuleToAccount(ctx, "evm", creator, amt) - recipient, _ := testkeeper.MockAddressPair() + privKeyRecipient := testkeeper.MockPrivateKey() + recipient, _ := testkeeper.PrivateKeyToAddresses(privKeyRecipient) payload := []byte(fmt.Sprintf("{\"mint\":{\"token_id\":\"1\",\"owner\":\"%s\"}}", recipient.String())) msg := &wasmtypes.MsgExecuteContract{ Sender: creator.String(), @@ -320,10 +321,12 @@ func TestEvmEventsForCw721(t *testing.T) { require.True(t, found) require.Equal(t, common.HexToHash("0x1").Bytes(), receipt.Logs[0].Data) - // revoke all - payload = []byte(fmt.Sprintf("{\"revoke_all\":{\"operator\":\"%s\"}}", recipient.String())) + // burn on behalf + payload = []byte("{\"burn\":{\"token_id\":\"2\"}}") + k.BankKeeper().MintCoins(ctx, "evm", amt) + k.BankKeeper().SendCoinsFromModuleToAccount(ctx, "evm", recipient, amt) msg = &wasmtypes.MsgExecuteContract{ - Sender: creator.String(), + Sender: recipient.String(), Contract: contractAddr.String(), Msg: payload, } @@ -331,7 +334,7 @@ func TestEvmEventsForCw721(t *testing.T) { txBuilder.SetMsgs(msg) txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(1000000)))) txBuilder.SetGasLimit(300000) - tx = signTx(txBuilder, privKey, k.AccountKeeper().GetAccount(ctx, creator)) + tx = signTx(txBuilder, privKeyRecipient, k.AccountKeeper().GetAccount(ctx, recipient)) txbz, err = testkeeper.EVMTestApp.GetTxConfig().TxEncoder()(tx) require.Nil(t, err) sum = sha256.Sum256(txbz) @@ -342,12 +345,17 @@ func TestEvmEventsForCw721(t *testing.T) { require.Equal(t, 1, len(receipt.Logs)) require.NotEmpty(t, receipt.LogsBloom) require.Equal(t, mockPointerAddr.Hex(), receipt.Logs[0].Address) - _, found = testkeeper.EVMTestApp.EvmKeeper.GetEVMTxDeferredInfo(ctx) - require.True(t, found) + require.Equal(t, uint32(0), receipt.Logs[0].Index) + ownerHash := receipt.Logs[0].Topics[1] + // make sure that the owner is set correctly to the creator, not the spender. + creatorEvmAddr := testkeeper.EVMTestApp.EvmKeeper.GetEVMAddressOrDefault(ctx, creator) + require.Equal(t, common.BytesToHash(creatorEvmAddr[:]).Hex(), ownerHash) + tokenIdHash = receipt.Logs[0].Topics[3] + require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000002", tokenIdHash) require.Equal(t, common.HexToHash("0x0").Bytes(), receipt.Logs[0].Data) - // burn - payload = []byte("{\"burn\":{\"token_id\":\"2\"}}") + // revoke all + payload = []byte(fmt.Sprintf("{\"revoke_all\":{\"operator\":\"%s\"}}", recipient.String())) msg = &wasmtypes.MsgExecuteContract{ Sender: creator.String(), Contract: contractAddr.String(), @@ -370,8 +378,6 @@ func TestEvmEventsForCw721(t *testing.T) { require.Equal(t, mockPointerAddr.Hex(), receipt.Logs[0].Address) _, found = testkeeper.EVMTestApp.EvmKeeper.GetEVMTxDeferredInfo(ctx) require.True(t, found) - tokenIdHash = receipt.Logs[0].Topics[3] - require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000002", tokenIdHash) require.Equal(t, common.HexToHash("0x0").Bytes(), receipt.Logs[0].Data) } diff --git a/go.mod b/go.mod index 42a6047536..150153237a 100644 --- a/go.mod +++ b/go.mod @@ -344,7 +344,7 @@ require ( ) replace ( - github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.2.4 + github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.2.6-erc721 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.44 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.2.0 diff --git a/go.sum b/go.sum index 05415a6bab..504ed8e389 100644 --- a/go.sum +++ b/go.sum @@ -1359,8 +1359,8 @@ github.com/sei-protocol/sei-tendermint v0.4.3 h1:/Nx3Q309B4N61P3e6ScYiVuHgBRdapc github.com/sei-protocol/sei-tendermint v0.4.3/go.mod h1:4LSlJdhl3nf3OmohliwRNUFLOB1XWlrmSodrIP7fLh4= github.com/sei-protocol/sei-tm-db v0.0.5 h1:3WONKdSXEqdZZeLuWYfK5hP37TJpfaUa13vAyAlvaQY= github.com/sei-protocol/sei-tm-db v0.0.5/go.mod h1:Cpa6rGyczgthq7/0pI31jys2Fw0Nfrc+/jKdP1prVqY= -github.com/sei-protocol/sei-wasmd v0.2.4 h1:W++xiJ1P57BhBW8TGk8vfPRJlWXr1vp2kQCvSc8Qpaw= -github.com/sei-protocol/sei-wasmd v0.2.4/go.mod h1:fKHnK3Nms+BZeGvXeIC3SEzUDfkB7/tYOf95kVOhiO4= +github.com/sei-protocol/sei-wasmd v0.2.6-erc721 h1:sCCNxZ1yxJOhIG6AP0Y2NNIcrYHuuqw8CfIH7gmq8uk= +github.com/sei-protocol/sei-wasmd v0.2.6-erc721/go.mod h1:fKHnK3Nms+BZeGvXeIC3SEzUDfkB7/tYOf95kVOhiO4= github.com/sei-protocol/tm-db v0.0.4 h1:7Y4EU62Xzzg6wKAHEotm7SXQR0aPLcGhKHkh3qd0tnk= github.com/sei-protocol/tm-db v0.0.4/go.mod h1:PWsIWOTwdwC7Ow/GUvx8HgUJTO691pBuorIQD8JvwAs= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=