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

deps!: use cosmos-sdk v0.45.16-lsm-ics #2643

Merged
merged 19 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/unreleased/api-breaking/2643-lsm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Add Liquid Staking Module (LSM) and initialize the LSM params:
ValidatorBondFactor, ValidatorLiquidStakingCap, GlobalLiquidStakingCap
([\#2643](https://github.com/cosmos/gaia/pull/2643))
3 changes: 3 additions & 0 deletions .changelog/unreleased/dependencies/2643-bump-ics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Bump [interchain-security](https://github.com/cosmos/interchain-security) to
[v2.0.0-lsm](https://github.com/cosmos/interchain-security/releases/tag/v2.0.0-lsm)
([\#2643](https://github.com/cosmos/gaia/pull/2643))
3 changes: 3 additions & 0 deletions .changelog/unreleased/dependencies/2643-bump-sdk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Bump [cosmos-sdk](https://github.com/cosmos/cosmos-sdk) to
[v0.45.16-ics-lsm](https://github.com/cosmos/ibc-go/releases/tag/v0.45.16-ics-lsm)
([\#2643](https://github.com/cosmos/gaia/pull/2643))
3 changes: 3 additions & 0 deletions .changelog/unreleased/features/2643-lsm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Add Liquid Staking Module (LSM) and initialize the LSM params:
ValidatorBondFactor, ValidatorLiquidStakingCap, GlobalLiquidStakingCap
([\#2643](https://github.com/cosmos/gaia/pull/2643))
3 changes: 3 additions & 0 deletions .changelog/unreleased/state-breaking/2643-lsm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Add Liquid Staking Module (LSM) and initialize the LSM params:
ValidatorBondFactor, ValidatorLiquidStakingCap, GlobalLiquidStakingCap
([\#2643](https://github.com/cosmos/gaia/pull/2643))
21 changes: 10 additions & 11 deletions app/helpers/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,16 @@ func genesisStateWithValSet(t *testing.T,
pkAny, err := codectypes.NewAnyWithValue(pk)
require.NoError(t, err)
validator := stakingtypes.Validator{
OperatorAddress: sdk.ValAddress(val.Address).String(),
ConsensusPubkey: pkAny,
Jailed: false,
Status: stakingtypes.Bonded,
Tokens: bondAmt,
DelegatorShares: sdk.OneDec(),
Description: stakingtypes.Description{},
UnbondingHeight: int64(0),
UnbondingTime: time.Unix(0, 0).UTC(),
Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
MinSelfDelegation: sdk.ZeroInt(),
OperatorAddress: sdk.ValAddress(val.Address).String(),
ConsensusPubkey: pkAny,
Jailed: false,
Status: stakingtypes.Bonded,
Tokens: bondAmt,
DelegatorShares: sdk.OneDec(),
Description: stakingtypes.Description{},
UnbondingHeight: int64(0),
UnbondingTime: time.Unix(0, 0).UTC(),
Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
}
validators = append(validators, validator)
delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec()))
Expand Down
14 changes: 14 additions & 0 deletions app/upgrades/v12/constants.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package v12

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/gaia/v12/app/upgrades"
)

Expand All @@ -9,6 +10,19 @@ const (
UpgradeName = "v12"
)

var (
// The ValidatorBondFactor dictates the cap on the liquid shares
// for a validator - determined as a multiple to their validator bond
// (e.g. ValidatorBondShares = 1000, BondFactor = 250 -> LiquidSharesCap: 250,000)
ValidatorBondFactor = sdk.NewDec(250)
// GlobalLiquidStakingCap represents a cap on the portion of stake that
// comes from liquid staking providers for a specific validator
ValidatorLiquidStakingCap = sdk.MustNewDecFromStr("0.5") // 50%
// GlobalLiquidStakingCap represents the percentage cap on
// the portion of a chain's total stake can be liquid
GlobalLiquidStakingCap = sdk.MustNewDecFromStr("0.25") // 25%
)

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
Expand Down
8 changes: 8 additions & 0 deletions app/upgrades/v12/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ func CreateUpgradeHandler(
return vm, err
}

// Set liquid staking module parameters
params := keepers.StakingKeeper.GetParams(ctx)
params.ValidatorBondFactor = ValidatorBondFactor
params.ValidatorLiquidStakingCap = ValidatorLiquidStakingCap
params.GlobalLiquidStakingCap = GlobalLiquidStakingCap

keepers.StakingKeeper.SetParams(ctx, params)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you saying that? RunMigrations should bump the staking ConsensusVersion to 3 (https://github.com/cosmos/cosmos-sdk/blob/201528c4c4c1661a4b7e3a5510f40fb6865df689/x/staking/module.go#L168) and execute the Migrate2to3 method. This call will add the LSM params (by calling MigrateParamsStore). Then we change the default values of these params in the upgrade handler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@riley-stride By the way, shouldn't we call RefreshTotalLiquidStaked after updating the param values? At the moment it's called by the migration code code in the SDK, see https://github.com/cosmos/cosmos-sdk/blob/201528c4c4c1661a4b7e3a5510f40fb6865df689/x/staking/migrations/v3/store.go#L143

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RefreshTotalLiquidStaked doesn't reference the params. It just sets the TotalLiquidStakedTokens and LiquidShares on each validator

ctx.Logger().Info("Upgrade complete")
return vm, err
}
Expand Down
1 change: 0 additions & 1 deletion cmd/gaiad/cmd/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ func InitTestnet(
sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(),
)
if err != nil {
return err
Expand Down
65 changes: 65 additions & 0 deletions contrib/scripts/local-gaia.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash
set -eux

# User balance of stake tokens
USER_COINS="100000000000stake"
# Amount of stake tokens staked
STAKE="100000000stake"
# Node IP address
NODE_IP="127.0.0.1"

# Home directory
HOME_DIR="/Users/msalopek"

# Validator moniker
MONIKER="coordinator"

# Validator directory
PROV_NODE_DIR=${HOME_DIR}/provider-${MONIKER}

# Coordinator key
PROV_KEY=${MONIKER}-key


# Clean start
pkill -f gaiad &> /dev/null || true
rm -rf ${PROV_NODE_DIR}

# Build file and node directory structure
gaiad init $MONIKER --chain-id provider --home ${PROV_NODE_DIR}
jq ".app_state.gov.voting_params.voting_period = \"20s\" | .app_state.staking.params.unbonding_time = \"86400s\"" \
${PROV_NODE_DIR}/config/genesis.json > \
${PROV_NODE_DIR}/edited_genesis.json && mv ${PROV_NODE_DIR}/edited_genesis.json ${PROV_NODE_DIR}/config/genesis.json

sleep 1

# Create account keypair
gaiad keys add $PROV_KEY --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY}.json 2>&1
sleep 1

# Add stake to user
PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json)
gaiad add-genesis-account $PROV_ACCOUNT_ADDR $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test
sleep 1


# Stake 1/1000 user's coins
gaiad gentx $PROV_KEY $STAKE --chain-id provider --home ${PROV_NODE_DIR} --keyring-backend test --moniker $MONIKER
sleep 1

gaiad collect-gentxs --home ${PROV_NODE_DIR} --gentx-dir ${PROV_NODE_DIR}/config/gentx/
sleep 1

sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26658\"/" ${PROV_NODE_DIR}/config/client.toml
sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_DIR}/config/config.toml
sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_DIR}/config/config.toml


# Start gaia
gaiad start \
--home ${PROV_NODE_DIR} \
--rpc.laddr tcp://${NODE_IP}:26658 \
--grpc.address ${NODE_IP}:9091 \
--address tcp://${NODE_IP}:26655 \
--p2p.laddr tcp://${NODE_IP}:26656 \
--grpc-web.enable=false &> ${PROV_NODE_DIR}/logs
29 changes: 28 additions & 1 deletion docs/delegators/delegator-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ In order to choose their validators, delegators have access to a range of inform
- **Initial commission rate**: The commission rate on revenue charged to any delegator by the validator (see below for more detail).
- **Commission max change rate:** The maximum daily increase of the validator's commission. This parameter cannot be changed by the validator operator.
- **Maximum commission:** The maximum commission rate this validator candidate can charge. This parameter cannot be changed by the validator operator.
- **Minimum self-bond amount**: Minimum amount of Atoms the validator candidate need to have bonded at all time. If the validator's self-bonded stake falls below this limit, their entire staking pool (i.e. all its delegators) will unbond. This parameter exists as a safeguard for delegators. Indeed, when a validator misbehaves, part of their total stake gets slashed. This included the validator's self-delegateds stake as well as their delegators' stake. Thus, a validator with a high amount of self-delegated Atoms has more skin-in-the-game than a validator with a low amount. The minimum self-bond amount parameter guarantees to delegators that a validator will never fall below a certain amount of self-bonded stake, thereby ensuring a minimum level of skin-in-the-game. This parameter can only be increased by the validator operator.
- **Validator self-bond amount**: A validator with a high amount of self-delegated Atoms has more skin-in-the-game than a validator with a low amount.

## Directives of delegators

Expand Down Expand Up @@ -61,6 +61,33 @@ Our validator's staking pool represents 10% of the total stake, which means the

Then, each delegator in the staking pool can claim their portion of the delegators' total revenue.

## Liquid Staking

The Liquid Staking module enacts a safety framework and associated governance-controlled parameters to regulate the adoption of liquid staking.

The LSM mitigates liquid staking risks by limiting the total amount of ATOM that can be liquid staked to a percentage of all staked ATOM. As an additional risk-mitigation feature, the LSM introduces a requirement that validators self-bond ATOM to be eligible for delegations from liquid staking providers or to be eligible to mint LSM tokens. This mechanism is called the “validator bond”, and is technically distinct from the current self-bond mechanism, but functions similarly.

At the same time, the LSM introduces the ability for staked ATOM to be instantly liquid staked, without having to wait for the unbonding period.

The LSM enables users to instantly liquid stake their staked ATOM, without having to wait the twenty-one day unbonding period. This is important, because a very large portion of the ATOM supply is currently staked. Liquid staking ATOM that is already staked incurs a switching cost in the form of three weeks’ forfeited staking rewards. The LSM eliminates this switching cost.

A user would be able to visit any liquid staking provider that has integrated with the LSM and click a button to convert her staked ATOM to liquid staked ATOM. It would be as easy as liquid staking unstaked ATOM.

Technically speaking, this is accomplished by using something called an “LSM share.” Using the liquid staking module, a user can tokenize their staked ATOM and turn it into LSM shares. LSM shares can be redeemed for underlying staked tokens and are transferable. After staked ATOM is tokenized it can be immediately transferred to a liquid staking provider in exchange for liquid staking tokens - without having to wait for the unbonding period.

### Toggling the ability to tokenize shares

Currently the liquid staking module facilitates the immediate conversion of staked assets into liquid staked tokens. Despite the many benefits that come with this capability, it does inadvertently negate a protective measure available via traditional staking, where an account can stake their tokens to render them illiquid in the event that their wallet is compromised (the attacker would first need to unbond, then transfer out the tokens).

Tokenization obviates this potential recovery measure, as an attacker could tokenize and immediately transfer staked tokens to another wallet. So, as an additional protective measure, the staking module permit accounts to selectively disable the tokenization of their stake with the `DisableTokenizeShares` message.

The `DisableTokenizeShares` message is exposed by the staking module and can be executed as follows:
```
gaiad tx staking disable-tokenize-shares --from mykey
```

When tokenization is disabled, a lock is placed on the account, effectively preventing the tokenization of any delegations. Re-enabling tokenization would initiate the removal of the lock, but the process is not immediate. The lock removal is queued, with the lock itself persisting throughout the unbonding period. Following the completion of the unbonding period, the lock would be completely removed, restoring the account's ablility to tokenize. For liquid staking protocols that enable the lock, this delay better positions the base layer to coordinate a recovery in the event of an exploit.

## Risks

Staking Atoms is not free of risk. First, staked Atoms are locked up, and retrieving them requires a 3 week waiting period called unbonding period. Additionally, if a validator misbehaves, a portion of their total stake can be slashed (i.e. destroyed). This includes the stake of their delegators.
Expand Down
Loading
Loading