Skip to content

Commit

Permalink
Merge pull request #173 from decentrio/trinity/zero-max-cap
Browse files Browse the repository at this point in the history
feat: Handle zero max cap on chain logic
  • Loading branch information
vuong177 authored Sep 5, 2024
2 parents 6663290 + 082fbe5 commit 7360399
Show file tree
Hide file tree
Showing 46 changed files with 979 additions and 182 deletions.
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

0 comments on commit 7360399

Please sign in to comment.