Files
wasmd/tests/e2e/grants_test.go
Alexander Peters 5c39daee99 Contract authz - redesign (#1077)
* Add contract authz proto

* Implement contract autorization

* Register contract authz

* Add contract-authz tests

* Consume gas for contract authz

* Add contract authz cli

* Update cli usage

* Model spike

* Add max funds limit

* Redesign authz model

* Start e2e test

* Full e2e test

* Test filter and limits

* Test accept

* Fix description

* No linter warning

Co-authored-by: Giancarlos Salas <me@giansalex.dev>
2022-11-11 13:39:16 +01:00

117 lines
4.4 KiB
Go

package e2e_test
import (
"fmt"
"testing"
"time"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/authz"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/CosmWasm/wasmd/x/wasm/ibctesting"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
func TestGrants(t *testing.T) {
// Given a contract by address A
// And a grant for address B by A created
// When B sends an execute with tokens from A
// Then the grant is executed as defined
// And
// - balance A reduced (on success)
// - balance B not touched
chain := ibctesting.NewCoordinator(t, 1).GetChain(ibctesting.GetChainID(0))
codeID := chain.StoreCodeFile("../../x/wasm/keeper/testdata/reflect_1_1.wasm").CodeID
contractAddr := chain.InstantiateContract(codeID, []byte(`{}`))
require.NotEmpty(t, contractAddr)
granterAddr := chain.SenderAccount.GetAddress()
granteePrivKey := secp256k1.GenPrivKey()
granteeAddr := sdk.AccAddress(granteePrivKey.PubKey().Address().Bytes())
otherPrivKey := secp256k1.GenPrivKey()
otherAddr := sdk.AccAddress(otherPrivKey.PubKey().Address().Bytes())
chain.Fund(granteeAddr, sdk.NewInt(1_000_000))
chain.Fund(otherAddr, sdk.NewInt(1_000_000))
assert.Equal(t, sdk.NewInt(1_000_000), chain.Balance(granteeAddr, sdk.DefaultBondDenom).Amount)
myAmount := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2_000_000))
specs := map[string]struct {
limit types.ContractAuthzLimitX
filter types.ContractAuthzFilterX
transferAmount sdk.Coin
senderKey cryptotypes.PrivKey
expErr *sdkerrors.Error
}{
"in limits and filter": {
limit: types.NewMaxFundsLimit(myAmount),
filter: types.NewAllowAllMessagesFilter(),
transferAmount: myAmount,
senderKey: granteePrivKey,
},
"exceed limits": {
limit: types.NewMaxFundsLimit(myAmount),
filter: types.NewAllowAllMessagesFilter(),
transferAmount: myAmount.Add(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())),
senderKey: granteePrivKey,
expErr: sdkerrors.ErrUnauthorized,
},
"not match filter": {
limit: types.NewMaxFundsLimit(myAmount),
filter: types.NewAcceptedMessageKeysFilter("foo"),
transferAmount: sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt()),
senderKey: granteePrivKey,
expErr: sdkerrors.ErrUnauthorized,
},
"non authorized sender address": { // sanity check - testing sdk
limit: types.NewMaxFundsLimit(myAmount),
filter: types.NewAllowAllMessagesFilter(),
senderKey: otherPrivKey,
transferAmount: myAmount,
expErr: sdkerrors.ErrUnauthorized,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup grant
grant, err := types.NewContractGrant(contractAddr, spec.limit, spec.filter)
require.NoError(t, err)
authorization := types.NewContractExecutionAuthorization(*grant)
grantMsg, err := authz.NewMsgGrant(granterAddr, granteeAddr, authorization, time.Now().Add(time.Hour))
require.NoError(t, err)
_, err = chain.SendMsgs(grantMsg)
require.NoError(t, err)
granterStartBalance := chain.Balance(granterAddr, sdk.DefaultBondDenom).Amount
// when
anyValidReflectMsg := []byte(fmt.Sprintf(`{"reflect_msg": {"msgs": [{"bank":{"burn":{"amount":[{"denom":%q, "amount": %q}]}}}]}}`, sdk.DefaultBondDenom, myAmount.Amount.String()))
execMsg := authz.NewMsgExec(spec.senderKey.PubKey().Address().Bytes(), []sdk.Msg{&types.MsgExecuteContract{
Sender: granterAddr.String(),
Contract: contractAddr.String(),
Msg: anyValidReflectMsg,
Funds: sdk.NewCoins(spec.transferAmount),
}})
_, gotErr := chain.SendNonDefaultSenderMsgs(spec.senderKey, &execMsg)
// then
if spec.expErr != nil {
require.ErrorIs(t, gotErr, spec.expErr)
assert.Equal(t, sdk.NewInt(1_000_000), chain.Balance(granteeAddr, sdk.DefaultBondDenom).Amount)
assert.Equal(t, granterStartBalance, chain.Balance(granterAddr, sdk.DefaultBondDenom).Amount)
return
}
require.NoError(t, gotErr)
assert.Equal(t, sdk.NewInt(1_000_000), chain.Balance(granteeAddr, sdk.DefaultBondDenom).Amount)
assert.Equal(t, granterStartBalance.Sub(spec.transferAmount.Amount), chain.Balance(granterAddr, sdk.DefaultBondDenom).Amount)
})
}
}