Skip to content

Commit

Permalink
Merge pull request #182 from decentrio/feat/vesting-delegate-remake
Browse files Browse the repository at this point in the history
feat: allow depositing vesting tokens in the vault
  • Loading branch information
vuong177 authored Aug 12, 2024
2 parents 8f8145d + e593473 commit 1e2b9e4
Show file tree
Hide file tree
Showing 21 changed files with 177 additions and 22 deletions.
20 changes: 20 additions & 0 deletions demo/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ import (
"github.com/osmosis-labs/mesh-security-sdk/x/meshsecurity"
meshseckeeper "github.com/osmosis-labs/mesh-security-sdk/x/meshsecurity/keeper"
meshsectypes "github.com/osmosis-labs/mesh-security-sdk/x/meshsecurity/types"
meshsecprov "github.com/osmosis-labs/mesh-security-sdk/x/meshsecurityprovider"
meshsecprovkeeper "github.com/osmosis-labs/mesh-security-sdk/x/meshsecurityprovider/keeper"
meshsecprovtypes "github.com/osmosis-labs/mesh-security-sdk/x/meshsecurityprovider/types"
)

const appName = "MeshApp"
Expand Down Expand Up @@ -200,6 +203,7 @@ var (
ica.AppModuleBasic{},
ibcfee.AppModuleBasic{},
meshsecurity.AppModuleBasic{},
meshsecprov.AppModuleBasic{},
)

// module account permissions
Expand Down Expand Up @@ -263,6 +267,7 @@ type MeshApp struct {
TransferKeeper ibctransferkeeper.Keeper
WasmKeeper wasmkeeper.Keeper
MeshSecKeeper *meshseckeeper.Keeper
MeshSecProvKeeper *meshsecprovkeeper.Keeper

ScopedIBCKeeper capabilitykeeper.ScopedKeeper
ScopedICAHostKeeper capabilitykeeper.ScopedKeeper
Expand Down Expand Up @@ -314,6 +319,7 @@ func NewMeshApp(
wasmtypes.StoreKey, icahosttypes.StoreKey,
icacontrollertypes.StoreKey,
meshsectypes.StoreKey,
meshsecprovtypes.StoreKey,
)

tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
Expand Down Expand Up @@ -417,6 +423,15 @@ func NewMeshApp(
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

app.MeshSecProvKeeper = meshsecprovkeeper.NewKeeper(
appCodec,
keys[meshsecprovtypes.StoreKey],
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
app.BankKeeper,
app.WasmKeeper,
app.StakingKeeper,
)

app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec,
legacyAmino,
Expand Down Expand Up @@ -589,6 +604,7 @@ func NewMeshApp(
nested,
// append our custom message handler for mesh-security
meshseckeeper.NewDefaultCustomMsgHandler(app.MeshSecKeeper),
meshsecprovkeeper.CustomMessageDecorator(app.MeshSecProvKeeper),
)
})
wasmOpts = append(wasmOpts, meshMessageHandler,
Expand Down Expand Up @@ -694,6 +710,7 @@ func NewMeshApp(
ibcfee.NewAppModule(app.IBCFeeKeeper),
ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper),
meshsecurity.NewAppModule(appCodec, app.MeshSecKeeper),
meshsecprov.NewAppModule(app.MeshSecProvKeeper),
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)), // always be last to make sure that it checks for all invariants and not only part of them
)

Expand All @@ -715,6 +732,7 @@ func NewMeshApp(
ibcfeetypes.ModuleName,
wasmtypes.ModuleName,
meshsectypes.ModuleName,
meshsecprovtypes.ModuleName,
)

app.ModuleManager.SetOrderEndBlockers(
Expand All @@ -731,6 +749,7 @@ func NewMeshApp(
ibcfeetypes.ModuleName,
wasmtypes.ModuleName,
meshsectypes.ModuleName, // last to capture all chain events
meshsecprovtypes.ModuleName,
)

// NOTE: The genutils module must occur after staking so that pools are
Expand All @@ -755,6 +774,7 @@ func NewMeshApp(
// wasm after ibc transfer
wasmtypes.ModuleName,
meshsectypes.ModuleName,
meshsecprovtypes.ModuleName,
}
app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)
app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...)
Expand Down
Binary file added demo/build/meshd
Binary file not shown.
4 changes: 3 additions & 1 deletion tests/e2e/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type example struct {
ConsumerChain *ibctesting.TestChain
ProviderChain *ibctesting.TestChain
ConsumerApp *app.MeshApp
ProviderApp *app.MeshApp
IbcPath *ibctesting.Path
ProviderDenom string
ConsumerDenom string
Expand All @@ -114,6 +115,7 @@ func setupExampleChains(t *testing.T) example {
ConsumerChain: consChain,
ProviderChain: provChain,
ConsumerApp: consChain.App.(*app.MeshApp),
ProviderApp: provChain.App.(*app.MeshApp),
IbcPath: ibctesting.NewPath(consChain, provChain),
ProviderDenom: sdk.DefaultBondDenom,
ConsumerDenom: sdk.DefaultBondDenom,
Expand All @@ -132,7 +134,7 @@ func setupMeshSecurity(t *testing.T, x example) (*TestConsumerClient, ConsumerCo
x.ConsumerChain.DefaultMsgFees = sdk.NewCoins(sdk.NewCoin(x.ConsumerDenom, math.NewInt(1_000_000)))

providerCli := NewProviderClient(t, x.ProviderChain)
providerContracts := providerCli.BootstrapContracts(x.IbcPath.EndpointA.ConnectionID, converterPortID)
providerContracts := providerCli.BootstrapContracts(x.ProviderApp, x.IbcPath.EndpointA.ConnectionID, converterPortID)

// setup ibc control path: consumer -> provider (direction matters)
x.IbcPath.EndpointB.ChannelConfig = &ibctesting2.ChannelConfig{
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/mvp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ func TestMVP(t *testing.T) {
// provider chain
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
execMsg := `{"bond":{}}`
providerCli.MustExecVault(execMsg, sdk.NewInt64Coin(x.ProviderDenom, 100_000_000))
execMsg := fmt.Sprintf(`{"bond":{"amount":{"denom":"%s", "amount":"100000000"}}}`, x.ProviderDenom)
providerCli.MustExecVault(execMsg)

// then query contract state
assert.Equal(t, 100_000_000, providerCli.QueryVaultFreeBalance())
Expand Down
12 changes: 6 additions & 6 deletions tests/e2e/slashing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func TestSlashingScenario1(t *testing.T) {
// Provider chain
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
execMsg := `{"bond":{}}`
providerCli.MustExecVault(execMsg, sdk.NewInt64Coin(x.ProviderDenom, 200_000_000))
execMsg := fmt.Sprintf(`{"bond":{"amount":{"denom":"%s", "amount":"200000000"}}}`, x.ProviderDenom)
providerCli.MustExecVault(execMsg)

// Stake Locally - A user triggers a local staking action to a chosen validator.
myLocalValidatorAddr := sdk.ValAddress(x.ProviderChain.Vals.Validators[0].Address).String()
Expand Down Expand Up @@ -121,8 +121,8 @@ func TestSlashingScenario2(t *testing.T) {
// Provider chain
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
execMsg := `{"bond":{}}`
providerCli.MustExecVault(execMsg, sdk.NewInt64Coin(x.ProviderDenom, 200_000_000))
execMsg := fmt.Sprintf(`{"bond":{"amount":{"denom":"%s", "amount":"200000000"}}}`, x.ProviderDenom)
providerCli.MustExecVault(execMsg)

// Stake Locally - A user triggers a local staking action to a chosen validator.
myLocalValidatorAddr := sdk.ValAddress(x.ProviderChain.Vals.Validators[0].Address).String()
Expand Down Expand Up @@ -208,8 +208,8 @@ func TestSlashingScenario3(t *testing.T) {
// Provider chain
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
execMsg := `{"bond":{}}`
providerCli.MustExecVault(execMsg, sdk.NewInt64Coin(x.ProviderDenom, 200_000_000))
execMsg := fmt.Sprintf(`{"bond":{"amount":{"denom":"%s", "amount":"200000000"}}}`, x.ProviderDenom)
providerCli.MustExecVault(execMsg)

// Stake Locally - A user triggers a local staking action to a chosen validator.
myLocalValidatorAddr := sdk.ValAddress(x.ProviderChain.Vals.Validators[0].Address).String()
Expand Down
8 changes: 5 additions & 3 deletions tests/e2e/test_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ type ProviderContracts struct {
externalStaking sdk.AccAddress
}

func (p *TestProviderClient) BootstrapContracts(connId, portID string) ProviderContracts {
var (
func (p *TestProviderClient) BootstrapContracts(provApp *app.MeshApp, connId, portID string) ProviderContracts { var (
unbondingPeriod = 21 * 24 * 60 * 60 // 21 days - make configurable?
localSlashRatioDoubleSign = "0.20"
localSlashRatioOffline = "0.10"
Expand All @@ -95,7 +94,10 @@ func (p *TestProviderClient) BootstrapContracts(connId, portID string) ProviderC
nativeInitMsg := []byte(fmt.Sprintf(`{"denom": %q, "proxy_code_id": %d, "slash_ratio_dsign": %q, "slash_ratio_offline": %q }`, localTokenDenom, proxyCodeID, localSlashRatioDoubleSign, localSlashRatioOffline))
initMsg := []byte(fmt.Sprintf(`{"denom": %q, "local_staking": {"code_id": %d, "msg": %q}}`, localTokenDenom, nativeStakingCodeID, base64.StdEncoding.EncodeToString(nativeInitMsg)))
vaultContract := InstantiateContract(p.t, p.chain, vaultCodeID, initMsg)

ctx := p.chain.GetContext()
params := provApp.MeshSecProvKeeper.GetParams(ctx)
params.VaultAddress = vaultContract.String()
provApp.MeshSecProvKeeper.SetParams(ctx, params)
// external staking
extStakingCodeID := p.chain.StoreCodeFile(buildPathToWasm("mesh_external_staking.wasm")).CodeID
initMsg = []byte(fmt.Sprintf(
Expand Down
8 changes: 4 additions & 4 deletions tests/starship/mvp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ func Test2WayContract(t *testing.T) {
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
fmt.Println("provider chain: deposit vault denom to provide some collateral to account")
execMsg := `{"bond":{}}`
vault, err := providerClient1.MustExecVault(execMsg, sdk.NewInt64Coin(providerClient1.Chain.Denom, 100_000_000))
execMsg := fmt.Sprintf(`{"bond":{"amount":{"denom":"%s", "amount":"100000000"}}}`, providerClient1.Chain.Denom)
vault, err := providerClient1.MustExecVault(execMsg)
require.NoError(t, err)
require.NotEmpty(t, vault)

Expand Down Expand Up @@ -130,8 +130,8 @@ func Test2WayContract(t *testing.T) {
// ==============
// Deposit - A user deposits the vault denom to provide some collateral to their account
fmt.Println("provider chain: deposit vault denom to provide some collateral to account")
execMsg = `{"bond":{}}`
vault, err = providerClient2.MustExecVault(execMsg, sdk.NewInt64Coin(providerClient2.Chain.Denom, 100_000_000))
execMsg = fmt.Sprintf(`{"bond":{"amount":{"denom":"%s", "amount":"100000000"}}}`, providerClient2.Chain.Denom)
vault, err = providerClient2.MustExecVault(execMsg)
require.NoError(t, err)
require.NotEmpty(t, vault)

Expand Down
6 changes: 3 additions & 3 deletions tests/testdata/copy_local_wasm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ command -v shellcheck > /dev/null && shellcheck "$0"

echo "DEV-only: copy from local built instead of downloading"

for contract in external_staking mesh_converter mesh_native_staking mesh_native_staking_proxy mesh_simple_price_feed \
for contract in mesh_external_staking mesh_converter mesh_native_staking mesh_native_staking_proxy mesh_simple_price_feed \
mesh_vault mesh_virtual_staking ; do
cp -f ../../../../mesh-security/artifacts/${contract}.wasm .
cp -f ../../../mesh-security/artifacts/${contract}.wasm .
gzip -fk ${contract}.wasm
rm -f ${contract}.wasm
done

cd ../../../../mesh-security
cd ../../../mesh-security
tag=$(git rev-parse HEAD)
cd -
rm -f version.txt
Expand Down
Binary file modified tests/testdata/mesh_converter.wasm.gz
Binary file not shown.
Binary file modified tests/testdata/mesh_external_staking.wasm.gz
Binary file not shown.
Binary file modified tests/testdata/mesh_native_staking.wasm.gz
Binary file not shown.
Binary file modified tests/testdata/mesh_native_staking_proxy.wasm.gz
Binary file not shown.
Binary file modified tests/testdata/mesh_simple_price_feed.wasm.gz
Binary file not shown.
Binary file modified tests/testdata/mesh_vault.wasm.gz
Binary file not shown.
Binary file modified tests/testdata/mesh_virtual_staking.wasm.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/testdata/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.10.0-alpha.1
34284a38601ff132e8d7b5594a87794faa71bbed
2 changes: 1 addition & 1 deletion x/meshsecurity/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func TestEndBlocker(t *testing.T) {
assert: func(t *testing.T, ctx sdk.Context) {
require.Len(t, capturedCalls, 2)
assert.Equal(t, myContractAddr, capturedCalls[0].contractAddress)
exp := fmt.Sprintf(`{"valset_update":{"additions":[{"address":"%s","commission":"0.000000000000000000","max_commission":"0.000000000000000000","max_change_rate":"0.000000000000000000"}],"removals":[],"updated":[],"jailed":[],"unjailed":[],"slashed":[],"tombstoned":[]}}`, val1.GetOperator())
exp := fmt.Sprintf(`{"handle_valset_update":{"additions":[{"address":"%s","commission":"0.000000000000000000","max_commission":"0.000000000000000000","max_change_rate":"0.000000000000000000"}],"removals":[],"updated":[],"jailed":[],"unjailed":[],"slashed":[],"tombstoned":[]}}`, val1.GetOperator())
assert.JSONEq(t, exp, string(capturedCalls[0].msg))

assert.Equal(t, myOtherContractAddr, capturedCalls[1].contractAddress)
Expand Down
2 changes: 1 addition & 1 deletion x/meshsecurity/contract/out_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
type (
SudoMsg struct {
HandleEpoch *struct{} `json:"handle_epoch,omitempty"`
ValsetUpdate *ValsetUpdate `json:"valset_update,omitempty"`
ValsetUpdate *ValsetUpdate `json:"handle_valset_update,omitempty"`
}

// Validator alias to wasmVM type
Expand Down
21 changes: 21 additions & 0 deletions x/meshsecurityprovider/contract/in_message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package contract

import wasmvmtypes "github.com/CosmWasm/wasmvm/types"

type (
CustomMsg struct {
Provider *ProviderMsg `json:"provider,omitempty"`
}
ProviderMsg struct {
Bond *BondMsg `json:"bond,omitempty"`
Unbond *UnbondMsg `json:"unbond,omitempty"`
}
BondMsg struct {
Amount wasmvmtypes.Coin `json:"amount"`
Delegator string `json:"delegator"`
}
UnbondMsg struct {
Amount wasmvmtypes.Coin `json:"amount"`
Delegator string `json:"delegator"`
}
)
51 changes: 51 additions & 0 deletions x/meshsecurityprovider/keeper/handle_plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package keeper

import (
"encoding/json"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/osmosis-labs/mesh-security-sdk/x/meshsecurityprovider/contract"
)

type CustomMessenger struct {
k *Keeper
}


// CustomMessageDecorator returns decorator for custom CosmWasm bindings messages
func CustomMessageDecorator(provKeeper *Keeper) *CustomMessenger {
return &CustomMessenger{
k: provKeeper,
}
}

var _ wasmkeeper.Messenger = (*CustomMessenger)(nil)

// DispatchMsg executes on the contractMsg.
func (h CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, _ string, msg wasmvmtypes.CosmosMsg) ([]sdk.Event, [][]byte, error) {
if msg.Custom == nil {
return nil, nil, wasmtypes.ErrUnknownMsg
}
var customMsg contract.CustomMsg
if err := json.Unmarshal(msg.Custom, &customMsg); err != nil {
return nil, nil, sdkerrors.ErrJSONUnmarshal.Wrap("custom message")
}
if customMsg.Provider == nil {
// not our message type
return nil, nil, wasmtypes.ErrUnknownMsg
}
switch {
case customMsg.Provider.Bond != nil:
return h.k.HandleBondMsg(ctx, contractAddr, customMsg.Provider.Bond)
case customMsg.Provider.Unbond != nil:
return h.k.HandleUnbondMsg(ctx, contractAddr, customMsg.Provider.Unbond)
}
return nil, nil, wasmtypes.ErrUnknownMsg
}

59 changes: 59 additions & 0 deletions x/meshsecurityprovider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package keeper
import (
"github.com/cometbft/cometbft/libs/log"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/osmosis-labs/mesh-security-sdk/x/meshsecurityprovider/contract"
"github.com/osmosis-labs/mesh-security-sdk/x/meshsecurityprovider/types"
)

Expand Down Expand Up @@ -88,3 +91,59 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
Params: k.GetParams(ctx),
}
}

func (k Keeper) HandleBondMsg(ctx sdk.Context, actor sdk.AccAddress, bondMsg *contract.BondMsg) ([]sdk.Event, [][]byte, error) {
if actor.String() != k.VaultAddress(ctx) {
return nil, nil, sdkerrors.ErrUnauthorized.Wrapf("contract has no permission for mesh security operations")
}

coin, err := wasmkeeper.ConvertWasmCoinToSdkCoin(bondMsg.Amount)
if err != nil {
return nil, nil, err
}

delAddr, err := sdk.AccAddressFromBech32(bondMsg.Delegator)
if err != nil {
return nil, nil, err
}

err = k.bankKeeper.DelegateCoins(ctx, delAddr, actor, sdk.NewCoins(coin))
if err != nil {
return nil, nil, err
}

return []sdk.Event{sdk.NewEvent(
types.EventTypeBond,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
sdk.NewAttribute(sdk.AttributeKeyAmount, coin.String()),
sdk.NewAttribute(types.AttributeKeyDelegator, delAddr.String()),
)}, nil, nil
}

func (k Keeper) HandleUnbondMsg(ctx sdk.Context, actor sdk.AccAddress, unbondMsg *contract.UnbondMsg) ([]sdk.Event, [][]byte, error) {
if actor.String() != k.VaultAddress(ctx) {
return nil, nil, sdkerrors.ErrUnauthorized.Wrapf("contract has no permission for mesh security operations")
}

coin, err := wasmkeeper.ConvertWasmCoinToSdkCoin(unbondMsg.Amount)
if err != nil {
return nil, nil, err
}

delAddr, err := sdk.AccAddressFromBech32(unbondMsg.Delegator)
if err != nil {
return nil, nil, err
}

err = k.bankKeeper.UndelegateCoins(ctx, actor, delAddr, sdk.NewCoins(coin))
if err != nil {
return nil, nil, err
}

return []sdk.Event{sdk.NewEvent(
types.EventTypeUnbond,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
sdk.NewAttribute(sdk.AttributeKeyAmount, coin.String()),
sdk.NewAttribute(types.AttributeKeyDelegator, delAddr.String()),
)}, nil, nil
}

0 comments on commit 1e2b9e4

Please sign in to comment.