Skip to content

Commit a13a275

Browse files
authored
Add logic to handle single nft claim (#2412)
## Describe your changes and provide context Previously, `MsgClaimSpecific.Assets.Denom` is unused if the asset type is CW721. This PR will make the claiming logic happens to only one NFT if `Denom` is specified for a CW721 claim. ## Testing performed to validate your change unit test
1 parent a9f46dd commit a13a275

3 files changed

Lines changed: 53 additions & 16 deletions

File tree

precompiles/solo/solo.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -195,21 +195,25 @@ func (p PrecompileExecutor) ClaimSpecific(ctx sdk.Context, caller common.Address
195195
}
196196
case asset.IsCW721():
197197
allTokens := []string{}
198-
startAfter := ""
199-
for {
200-
res, err := p.wasmViewKeeper.QuerySmartSafe(ctx, contractAddr, CW721TokensQueryPayload(sender, startAfter))
201-
if err != nil {
202-
return nil, 0, fmt.Errorf("failed to query CW721 contract %s for all tokens: %w", contractAddr.String(), err)
203-
}
204-
tokens, err := ParseCW721TokensQueryResponse(res)
205-
if err != nil {
206-
return nil, 0, fmt.Errorf("failed to parse CW20 contract %s balance response: %w", contractAddr.String(), err)
207-
}
208-
if len(tokens) == 0 {
209-
break
198+
if token := asset.GetDenom(); token != "" {
199+
allTokens = append(allTokens, token)
200+
} else {
201+
startAfter := ""
202+
for {
203+
res, err := p.wasmViewKeeper.QuerySmartSafe(ctx, contractAddr, CW721TokensQueryPayload(sender, startAfter))
204+
if err != nil {
205+
return nil, 0, fmt.Errorf("failed to query CW721 contract %s for all tokens: %w", contractAddr.String(), err)
206+
}
207+
tokens, err := ParseCW721TokensQueryResponse(res)
208+
if err != nil {
209+
return nil, 0, fmt.Errorf("failed to parse CW20 contract %s balance response: %w", contractAddr.String(), err)
210+
}
211+
if len(tokens) == 0 {
212+
break
213+
}
214+
allTokens = append(allTokens, tokens...)
215+
startAfter = tokens[len(tokens)-1]
210216
}
211-
allTokens = append(allTokens, tokens...)
212-
startAfter = tokens[len(tokens)-1]
213217
}
214218
for _, token := range allTokens {
215219
_, err := p.wasmKeeper.Execute(ctx, contractAddr, sender, CW721TransferPayload(callerSeiAddr, token), sdk.NewCoins())

precompiles/solo/solo_test.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func TestClaimSpecificCW721(t *testing.T) {
177177
k.AccountKeeper().SetAccount(origCtx, acc)
178178
contractAddr := setupCW721Contract(origCtx, claimeeKey, *wKeeper)
179179
ctx, _ := origCtx.CacheContext()
180-
ctx = ctx.WithGasMeter(sdk.NewGasMeter(2000000, 1, 1))
180+
ctx = ctx.WithGasMeter(sdk.NewGasMeter(3000000, 1, 1))
181181
_, remainingGas, err := p.ClaimSpecific(ctx, claimer, &method, []interface{}{signClaimMsg(t, evmtypes.NewMsgClaimSpecific(claimee, claimer, &evmtypes.Asset{AssetType: evmtypes.AssetType_TYPECW721, ContractAddress: contractAddr.String()}), claimee, claimer, acc, claimeeKey)}, false)
182182
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeterWithMultiplier(ctx))
183183
require.NoError(t, err)
@@ -187,6 +187,36 @@ func TestClaimSpecificCW721(t *testing.T) {
187187
}
188188
}
189189

190+
func TestClaimSingleCW721(t *testing.T) {
191+
k := &testkeeper.EVMTestApp.EvmKeeper
192+
origCtx := testkeeper.EVMTestApp.GetContextForDeliverTx(nil).WithChainID("sei-test").WithBlockTime(time.Now())
193+
txConfig := testkeeper.EVMTestApp.GetTxConfig()
194+
a := pcommon.MustGetABI(solo.F, "abi.json")
195+
method := a.Methods["claimSpecific"]
196+
wKeeper := wasmkeeper.NewDefaultPermissionKeeper(testkeeper.EVMTestApp.WasmKeeper)
197+
p := solo.NewExecutor(a, k, k.BankKeeper(), k.AccountKeeper(), wKeeper, testkeeper.EVMTestApp.WasmKeeper, txConfig)
198+
claimeeKey := testkeeper.MockPrivateKey()
199+
claimee, _ := testkeeper.PrivateKeyToAddresses(claimeeKey)
200+
claimerKey := testkeeper.MockPrivateKey()
201+
_, claimer := testkeeper.PrivateKeyToAddresses(claimerKey)
202+
acc := authtypes.NewBaseAccount(claimee, claimeeKey.PubKey(), 10, 0)
203+
k.AccountKeeper().SetAccount(origCtx, acc)
204+
contractAddr := setupCW721Contract(origCtx, claimeeKey, *wKeeper)
205+
ctx, _ := origCtx.CacheContext()
206+
ctx = ctx.WithGasMeter(sdk.NewGasMeter(2000000, 1, 1))
207+
_, remainingGas, err := p.ClaimSpecific(ctx, claimer, &method, []interface{}{signClaimMsg(t, evmtypes.NewMsgClaimSpecific(claimee, claimer, &evmtypes.Asset{AssetType: evmtypes.AssetType_TYPECW721, ContractAddress: contractAddr.String(), Denom: "5"}), claimee, claimer, acc, claimeeKey)}, false)
208+
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeterWithMultiplier(ctx))
209+
require.NoError(t, err)
210+
require.Equal(t, uint64(1838040), remainingGas)
211+
for i := 0; i < 15; i++ {
212+
if i == 5 {
213+
require.Equal(t, k.GetSeiAddressOrDefault(ctx, claimer).String(), queryCW721Owner(ctx, testkeeper.EVMTestApp.WasmKeeper, contractAddr, fmt.Sprintf("%d", i)))
214+
} else {
215+
require.Equal(t, claimee.String(), queryCW721Owner(ctx, testkeeper.EVMTestApp.WasmKeeper, contractAddr, fmt.Sprintf("%d", i)))
216+
}
217+
}
218+
}
219+
190220
func TestClaimSpecificNative(t *testing.T) {
191221
k := &testkeeper.EVMTestApp.EvmKeeper
192222
origCtx := testkeeper.EVMTestApp.GetContextForDeliverTx(nil).WithChainID("sei-test").WithBlockTime(time.Now())

sei-wasmd/x/wasm/keeper/keeper.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,10 @@ func (k Keeper) emitCW721OwnerBeforeTransferIfApplicable(ctx sdk.Context, contra
11411141
if err != nil {
11421142
return
11431143
}
1144-
resBz, err := k.QuerySmart(ctx.WithGasMeter(sdk.NewInfiniteGasMeterWithMultiplier(ctx)), contractAddress, ownerQueryBz)
1144+
if ctx.IsTracing() && ctx.ChainID() == "pacific-1" && strings.Compare(ctx.ClosestUpgradeName(), "v6.3.0") < 0 {
1145+
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeterWithMultiplier(ctx))
1146+
}
1147+
resBz, err := k.QuerySmart(ctx, contractAddress, ownerQueryBz)
11451148
if err != nil {
11461149
return
11471150
}

0 commit comments

Comments
 (0)