Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Handle zero max cap on chain logic #173

Merged
merged 14 commits into from
Sep 5, 2024
Merged
18 changes: 18 additions & 0 deletions docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
## Table of Contents

- [osmosis/meshsecurity/v1beta1/meshsecurity.proto](#osmosis/meshsecurity/v1beta1/meshsecurity.proto)
- [Delegation](#osmosis.meshsecurity.v1beta1.Delegation)
- [Params](#osmosis.meshsecurity.v1beta1.Params)
- [VirtualStakingMaxCapInfo](#osmosis.meshsecurity.v1beta1.VirtualStakingMaxCapInfo)

Expand Down Expand Up @@ -41,6 +42,23 @@



<a name="osmosis.meshsecurity.v1beta1.Delegation"></a>

### Delegation
Delegation represents the bond with tokens held by an account.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `delegator_address` | [string](#string) | | delegator_address is the bech32-encoded address of the delegator. |
| `validator_address` | [string](#string) | | validator_address is the bech32-encoded address of the validator. |
| `amount` | [string](#string) | | amount define the delegation amount. |






<a name="osmosis.meshsecurity.v1beta1.Params"></a>

### Params
Expand Down
155 changes: 155 additions & 0 deletions note.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
{
"stake": {
"delegator": "cosmos1ph3tq3s5afcg6z4c4mpd9kdklt9a8j7gw8sygn",
"validator": "cosmosvaloper1gtnfjqp6pgkdu6szu5rzk4h5z5d54fadcfsv90",
"stake": {
"denom": "stake",
"amount": "20000000"
},
"tx_id": 2
}
}

[
Execute {
contract_addr: "cosmos1qg5ega6dykkxc307y25pecuufrjkxkaggkkxh7nad0vhyhtuhw3s6ufdm4",
msg: {
"internal_unstake":{
"delegator":"cosmos1whqnmupfwm3gfmvjegy0j69z42mfngmg2q8emj",
"validator":"cosmosvaloper1jgaec5l7glsy2l37n25kmqj7p9hrfzsh43df3u",
"amount":{"denom":"stake","amount":"22500000"}}
},
funds: []
},
Execute {
contract_addr: "cosmos1qg5ega6dykkxc307y25pecuufrjkxkaggkkxh7nad0vhyhtuhw3s6ufdm4",
msg: {
"internal_unstake":{
"delegator":"cosmos1whqnmupfwm3gfmvjegy0j69z42mfngmg2q8emj",
"validator":"cosmosvaloper1mt78w786v2qz24skefvv6x3xulq4495egj33yc",
"amount":{"denom":"stake","amount":"9000000"}}}, funds: [] }]

panic:
failed to execute scheduled task for contract
"cosmos1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3s493rn8":
execution: {Loading CosmWasm module: execute}: panic [recovered]

routes: map[
/cosmos.auth.v1beta1.MsgUpdateParams:0x10378c850
/cosmos.authz.v1beta1.MsgExec:0x10378c850
/cosmos.authz.v1beta1.MsgGrant:0x10378c850
/cosmos.authz.v1beta1.MsgRevoke:0x10378c850
/cosmos.bank.v1beta1.MsgMultiSend:0x10378c850
/cosmos.bank.v1beta1.MsgSend:0x10378c850
/cosmos.bank.v1beta1.MsgSetSendEnabled:0x10378c850
/cosmos.bank.v1beta1.MsgUpdateParams:0x10378c850
/cosmos.consensus.v1.MsgUpdateParams:0x10378c850
/cosmos.crisis.v1beta1.MsgUpdateParams:0x10378c850
/cosmos.crisis.v1beta1.MsgVerifyInvariant:0x10378c850
/cosmos.distribution.v1beta1.MsgCommunityPoolSpend:0x10378c850
/cosmos.distribution.v1beta1.MsgFundCommunityPool:0x10378c850
/cosmos.distribution.v1beta1.MsgSetWithdrawAddress:0x10378c850
/cosmos.distribution.v1beta1.MsgUpdateParams:0x10378c850
/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward:0x10378c850 /
cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission:0x10378c850
/cosmos.evidence.v1beta1.MsgSubmitEvidence:0x10378c850
/cosmos.feegrant.v1beta1.MsgGrantAllowance:0x10378c8
50 /cosmos.feegrant.v1beta1.MsgRevokeAllowance:0x10378c850
/cosmos.gov.v1.MsgDeposit:0x10378c850
/cosmos.gov.v1.MsgExecLegacyContent:0x10378c850
/cosmos.gov.v1.MsgSubmitProposal:0x10378c850
/cosmos.gov.v1.MsgUpdateParams:0x10378c850
/cosmos.gov.v1.MsgVote:0x10378c850
/cosmos.gov.v1.MsgVoteWeighted:0x10378c850
/cosmos.gov.v1beta1.MsgDeposit:0x10378c850
/cosmos.gov.v1beta1.MsgSubmitProposal:0x10378c850
/cosmos.gov.v1beta1.MsgVote:0x10378c850
/cosmos.gov.v1beta1.MsgVoteWeighted:0x10378c850
/cosmos.group.v1.MsgCreateGroup:0x10378c850
/cosmos.group.v1.MsgCreateGroupPolicy:0x10378c850
/cosmos.group.v1.MsgCreateGroupWithPolicy:0x10378c850
/cosmos.group.v1.MsgExec:0x10378c850
/cosmos.group.v1.MsgLeaveGroup:0x10378c850
/cosmos.group.v1.MsgSubmitProposal:0x10378c850
/cosmos.group.v1.MsgUpdateGroupAdmin:0x10378c850
/cosmos.group.v1.MsgUpdateGroupMembers:0x10378c850
/cosmos.group.v1.MsgUpdateGroupMetadata:0x10378c850
/cosmos.group.v1.MsgUpdateGroupPolicyAdmin:0x10378c850
/cosmos.group.v1.MsgUpdateGroupPolicyDecisionPolicy:0x10378c850
/cosmos.group.v1.MsgUpdateGroupPolicyMetadata:0x10378c850
/cosmos.group.v1.MsgVote:0x10378c850
/cosmos.group.v1.MsgWithdrawProposal:0x10378c850
/cosmos.mint.v1beta1.MsgUpdateParams:0x10378c850
/cosmos.nft.v1beta1.MsgSend:0x10378c850
/cosmos.slashing.v1beta1.MsgUnjail:0x10378c850
/cosmos.slashing.v1beta1.MsgUpdateParams:0x10378c850
/cosmos.staking.v1beta1.MsgBeginRedelegate:0x10378c850
/cosmos.staking.v1beta1.MsgCancelUnbondingDelegation:0x10378c850
/cosmos.staking.v1beta1.MsgCreateValidator:0x10378c850
/cosmos.staking.v1beta1.MsgDelegate:0x10378c850
/cosmos.staking.v1beta1.MsgEditValidator:0x10378c850
/cosmos.staking.v1beta1.MsgUndelegate:0x10378c850
/cosmos.staking.v1beta1.MsgUpdateParams:0x10378c850
/cosmos.upgrade.v1beta1.MsgCancelUpgrade:0x10378c850
/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade:0x10378c850
/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount:0x10378c850
/cosmos.vesting.v1beta1.MsgCreatePermanentLockedAccount:0x10378c850
/cosmos.vesting.v1beta1.MsgCreateVestingAccount:0x10378c850
/cosmwasm.wasm.v1.MsgAddCodeUploadParamsAddresses:0x10378c850
/cosmwasm.wasm.v1.MsgClearAdmin:0x10378c850
/cosmwasm.wasm.v1.MsgExecuteContract:0x10378c850
/cosmwasm.wasm.v1.MsgInstantiateContract:0x10378c850
/cosmwasm.wasm.v1.MsgInstantiateContract2:0x10378c850
/cosmwasm.wasm.v1.MsgMigrateContract:0x10378c850
/cosmwasm.wasm.v1.MsgPinCodes:0x10378c850
/cosmwasm.wasm.v1.MsgRemoveCodeUploadParamsAddresses:0x10378c850
/cosmwasm.wasm.v1.MsgStoreAndInstantiateContract:0x10378c850
/cosmwasm.wasm.v1.MsgStoreAndMigrateContract:0x10378c850
/cosmwasm.wasm.v1.MsgStoreCode:0x10378c850
/cosmwasm.wasm.v1.MsgSudoContract:0x10378c850
/cosmwasm.wasm.v1.MsgUnpinCodes:0x10378c850
/cosmwasm.wasm.v1.MsgUpdateAdmin:0x10378c850
/cosmwasm.wasm.v1.MsgUpdateContractLabel:0x10378c850
/cosmwasm.wasm.v1.MsgUpdateInstantiateConfig:0x10378c850
/cosmwasm.wasm.v1.MsgUpdateParams:0x10378c850
/ibc.applications.fee.v1.MsgPayPacketFee:0x10378c850
/ibc.applications.fee.v1.MsgPayPacketFeeAsync:0x10378c850
/ibc.applications.fee.v1.MsgRegisterCounterpartyPayee:0x10378c850
/ibc.applications.fee.v1.MsgRegisterPayee:0x10378c850
/ibc.applications.interchain_accounts.controller.v1.MsgRegisterInterchainAccount:0x10378c850
/ibc.applications.interchain_accounts.controller.v1.MsgSendTx:0x10378c850
/ibc.applications.transfer.v1.MsgTransfer:0x10378c850
/ibc.core.channel.v1.MsgAcknowledgement:0x10378c850
/ibc.core.channel.v1.MsgChannelCloseConfirm:0x10378c850
/ibc.core.channel.v1.MsgChannelCloseInit:0x10378c850
/ibc.core.channel.v1.MsgChannelOpenAck:0x10378c850
/ibc.core.channel.v1.MsgChannelOpenConfirm:0x10378c850
/ibc.core.channel.v1.MsgChannelOpenInit:0x10378c850
/ibc.core.channel.v1.MsgChannelOpenTry:0x10378c850
/ibc.core.channel.v1.MsgRecvPacket:0x10378c850
/ibc.core.channel.v1.MsgTimeout:0x10378c850
/ibc.core.channel.v1.MsgTimeoutOnClose:0x10378c850
/ibc.core.client.v1.MsgCreateClient:0x10378c850
/ibc.core.client.v1.MsgSubmitMisbehaviour:0x10378c850
/ibc.core.client.v1.MsgUpdateClient:0x10378c850
/ibc.core.client.v1.MsgUpgradeClient:0x10378c850
/ibc.core.connection.v1.MsgConnectionOpenAck:0x10378c850
/ibc.core.connection.v1.MsgConnectionOpenConfirm:0x10378c850
/ibc.core.connection.v1.MsgConnectionOpenInit:0x10378c850
/ibc.core.connection.v1.MsgConnectionOpenTry:0x10378c850
/osmosis.meshsecurity.v1beta1.MsgSetVirtualStakingMaxCap:0x10378c850]


Cannot unbond 49999999 tokens from validator cosmosvaloper1fhm5lj9wcvxwdxmgtz36mnjuhwtk7ly93c3rqg, not enough staked

data: {
"internal_unstake":{
"delegator":"cosmos1yw0saxm7nkwl0e8r3kqpar2a0vusdzcaku8mys",
"validator":"cosmosvaloper1szy96jnddalx7s686e4ylres02uv6a5dyxj82c",
"normalize_amount":{"denom":"stake","amount":"9000000"},
"inverted_amount":{"denom":"stake","amount":"19999999"}
}
}

failed to execute message; message index: 0: acknowledge packet callback failed: on ack: submessages: Error calling the VM: Error executing Wasm: Wasmer runtime error: RuntimeError:
Aborted: panicked at contracts/consumer/virtual-staking/src/contract.rs:519:9:
15 changes: 15 additions & 0 deletions proto/osmosis/meshsecurity/v1beta1/meshsecurity.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ message VirtualStakingMaxCapInfo {
cosmos.base.v1beta1.Coin cap = 3 [ (gogoproto.nullable) = false ];
}

// Delegation represents the bond with tokens held by an account.
message Delegation {
option (gogoproto.equal) = false;

// delegator_address is the bech32-encoded address of the delegator.
string delegator_address = 1;
// validator_address is the bech32-encoded address of the validator.
string validator_address = 2;
// amount define the delegation amount.
string amount = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}

// Params defines the parameters for the x/meshsecurity module.
message Params {
option (amino.name) = "meshsecurity/Params";
Expand Down
7 changes: 3 additions & 4 deletions tests/e2e/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# End-To-End Tests

Multi-chain system tests that run against the demo app.

Run them with:

Run them with:
```shell
make test
```


```
4 changes: 3 additions & 1 deletion tests/e2e/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ type example struct {
ProviderDenom string
ConsumerDenom string
MyProvChainActor string
MaxRetrieve uint16
}

func setupExampleChains(t *testing.T) example {
Expand All @@ -120,6 +121,7 @@ func setupExampleChains(t *testing.T) example {
ProviderDenom: sdk.DefaultBondDenom,
ConsumerDenom: sdk.DefaultBondDenom,
MyProvChainActor: provChain.SenderAccount.GetAddress().String(),
MaxRetrieve: 50,
}
}

Expand All @@ -128,7 +130,7 @@ func setupMeshSecurity(t *testing.T, x example) (*TestConsumerClient, ConsumerCo

// setup contracts on both chains
consumerCli := NewConsumerClient(t, x.ConsumerChain)
consumerContracts := consumerCli.BootstrapContracts()
consumerContracts := consumerCli.BootstrapContracts(x)
converterPortID := wasmkeeper.PortIDForContract(consumerContracts.converter)
// add some fees so that we can distribute something
x.ConsumerChain.DefaultMsgFees = sdk.NewCoins(sdk.NewCoin(x.ConsumerDenom, math.NewInt(1_000_000)))
Expand Down
1 change: 0 additions & 1 deletion tests/e2e/mvp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ func TestMVP(t *testing.T) {
// ...
x := setupExampleChains(t)
consumerCli, consumerContracts, providerCli := setupMeshSecurity(t, x)

// then the active set should be stored in the ext staking contract
// and contain all active validator addresses
qRsp := providerCli.QueryExtStaking(Query{"list_active_validators": {}})
Expand Down
11 changes: 6 additions & 5 deletions tests/e2e/slashing_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package e2e

import (
"cosmossdk.io/math"
"encoding/base64"
"fmt"
"testing"

"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)

func TestSlashingScenario1(t *testing.T) {
Expand All @@ -17,7 +18,6 @@ func TestSlashingScenario1(t *testing.T) {
// - We use millions instead of unit tokens.
x := setupExampleChains(t)
consumerCli, _, providerCli := setupMeshSecurity(t, x)

// Provider chain
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
Expand Down Expand Up @@ -91,6 +91,7 @@ func TestSlashingScenario1(t *testing.T) {
// Assert that the validator's stake has been slashed
// and that the validator has been jailed
validator1, found = x.ConsumerApp.StakingKeeper.GetValidator(ctx, myExtValidator1)
require.True(t, found)
require.True(t, validator1.IsJailed())
require.Equal(t, validator1.GetTokens(), sdk.NewInt(41_400_000)) // 10% slash

Expand All @@ -117,7 +118,6 @@ func TestSlashingScenario2(t *testing.T) {
// - We use millions instead of unit tokens.
x := setupExampleChains(t)
consumerCli, _, providerCli := setupMeshSecurity(t, x)

// Provider chain
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
Expand Down Expand Up @@ -178,6 +178,7 @@ func TestSlashingScenario2(t *testing.T) {
// Assert that the validator's stake has been slashed
// and that the validator has been jailed
validator1, found = x.ConsumerApp.StakingKeeper.GetValidator(ctx, myExtValidator1)
require.True(t, found)
require.True(t, validator1.IsJailed())
require.Equal(t, validator1.GetTokens(), sdk.NewInt(81_900_000)) // 10% slash

Expand All @@ -204,7 +205,6 @@ func TestSlashingScenario3(t *testing.T) {
// - We use millions instead of unit tokens.
x := setupExampleChains(t)
consumerCli, _, providerCli := setupMeshSecurity(t, x)

// Provider chain
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
Expand Down Expand Up @@ -265,6 +265,7 @@ func TestSlashingScenario3(t *testing.T) {
// Assert that the validator's stake has been slashed
// and that the validator has been jailed
validator1, found = x.ConsumerApp.StakingKeeper.GetValidator(ctx, myExtValidator1)
require.True(t, found)
require.True(t, validator1.IsJailed())
require.Equal(t, validator1.GetTokens(), sdk.NewInt(61_700_000)) // 10% slash (plus 50_000 rounding)

Expand Down
20 changes: 16 additions & 4 deletions tests/e2e/test_client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package e2e

import (
"context"
"encoding/base64"
"fmt"
"strconv"
Expand All @@ -20,9 +21,11 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"

"github.com/osmosis-labs/mesh-security-sdk/demo/app"
"github.com/osmosis-labs/mesh-security-sdk/x/meshsecurity"
"github.com/osmosis-labs/mesh-security-sdk/x/meshsecurity/keeper"
"github.com/osmosis-labs/mesh-security-sdk/x/meshsecurity/types"
)

Expand Down Expand Up @@ -353,7 +356,7 @@ type ConsumerContract struct {
converter sdk.AccAddress
}

func (p *TestConsumerClient) BootstrapContracts() ConsumerContract {
func (p *TestConsumerClient) BootstrapContracts(x example) ConsumerContract {
// modify end-blocker to fail fast in tests
msModule := p.app.ModuleManager.Modules[types.ModuleName].(*meshsecurity.AppModule)
msModule.SetAsyncTaskRspHandler(meshsecurity.PanicOnErrorExecutionResponseHandler())
Expand All @@ -370,8 +373,8 @@ func (p *TestConsumerClient) BootstrapContracts() ConsumerContract {
virtStakeCodeID := p.chain.StoreCodeFile(buildPathToWasm("mesh_virtual_staking.wasm")).CodeID
// instantiate converter
codeID = p.chain.StoreCodeFile(buildPathToWasm("mesh_converter.wasm")).CodeID
initMsg = []byte(fmt.Sprintf(`{"price_feed": %q, "discount": %q, "remote_denom": %q,"virtual_staking_code_id": %d}`,
priceFeedContract.String(), discount, remoteDenom, virtStakeCodeID))
initMsg = []byte(fmt.Sprintf(`{"price_feed": %q, "discount": %q, "remote_denom": %q,"virtual_staking_code_id": %d, "max_retrieve": %d}`,
priceFeedContract.String(), discount, remoteDenom, virtStakeCodeID, x.MaxRetrieve))
converterContract := InstantiateContract(p.t, p.chain, codeID, initMsg)

staking := Querier(p.t, p.chain)(converterContract.String(), Query{"config": {}})["virtual_staking"]
Expand Down Expand Up @@ -404,6 +407,15 @@ func (p *TestConsumerClient) ExecNewEpoch() {
}
}

func (p *TestConsumerClient) ExecSetMaxCap(cap sdk.Coin) {
msgServer := keeper.NewMsgServer(p.app.MeshSecKeeper)
msgServer.SetVirtualStakingMaxCap(p.chain.GetContext(), &types.MsgSetVirtualStakingMaxCap{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Contract: p.contracts.staking.String(),
MaxCap: cap,
})
}

// MustEnableVirtualStaking add authority to mint/burn virtual tokens gov proposal
func (p *TestConsumerClient) MustEnableVirtualStaking(maxCap sdk.Coin) {
govProposal := &types.MsgSetVirtualStakingMaxCap{
Expand All @@ -423,7 +435,7 @@ func (p *TestConsumerClient) MustExecGovProposal(msg *types.MsgSetVirtualStaking
func (p *TestConsumerClient) QueryMaxCap() types.QueryVirtualStakingMaxCapLimitResponse {
q := baseapp.QueryServiceTestHelper{GRPCQueryRouter: p.app.GRPCQueryRouter(), Ctx: p.chain.GetContext()}
var rsp types.QueryVirtualStakingMaxCapLimitResponse
err := q.Invoke(nil, "/osmosis.meshsecurity.v1beta1.Query/VirtualStakingMaxCapLimit", &types.QueryVirtualStakingMaxCapLimitRequest{Address: p.contracts.staking.String()}, &rsp)
err := q.Invoke(context.TODO(), "/osmosis.meshsecurity.v1beta1.Query/VirtualStakingMaxCapLimit", &types.QueryVirtualStakingMaxCapLimitRequest{Address: p.contracts.staking.String()}, &rsp)
require.NoError(p.t, err)
return rsp
}
Expand Down
Loading
Loading