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: NoLock gauge type and external gauge creation wiring to CL #5459

Merged
merged 51 commits into from
Jun 10, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
636b017
feat/docs: CL external incentives tool
p0mvn Jun 7, 2023
3bde128
updates
p0mvn Jun 8, 2023
efa9a2d
updates
p0mvn Jun 8, 2023
5adbfa4
updates
p0mvn Jun 8, 2023
6425507
updates
p0mvn Jun 8, 2023
95cf146
updates
p0mvn Jun 8, 2023
5eb5ce2
updates
p0mvn Jun 8, 2023
ec2d50a
updates
p0mvn Jun 8, 2023
b758cd4
updates
p0mvn Jun 8, 2023
03c59df
updates
p0mvn Jun 8, 2023
ca3ca48
updates
p0mvn Jun 8, 2023
15a575f
updates
p0mvn Jun 8, 2023
68e42a6
updates
p0mvn Jun 8, 2023
d017483
updates
p0mvn Jun 8, 2023
7f4a4e2
Apply suggestions from code review
p0mvn Jun 8, 2023
3832b0e
updates
p0mvn Jun 8, 2023
4ced149
updates
p0mvn Jun 8, 2023
c84b0d1
more assertions in TestCreateGauge_NoLockGauges
p0mvn Jun 8, 2023
54bd0b5
add comments to CreateGauge
p0mvn Jun 8, 2023
17dff34
update comments for Distribute
p0mvn Jun 8, 2023
9704f9c
updates
p0mvn Jun 8, 2023
cc6ee0f
revert
p0mvn Jun 8, 2023
eef881f
changelog
p0mvn Jun 8, 2023
be45979
add incentives module docs
p0mvn Jun 8, 2023
6a91d9e
fix test names
p0mvn Jun 8, 2023
be800fd
CL module README
p0mvn Jun 8, 2023
db9e712
updates
p0mvn Jun 8, 2023
cc8e484
typo
p0mvn Jun 8, 2023
6f08fbd
fix test
p0mvn Jun 8, 2023
55bfe54
test updates
p0mvn Jun 8, 2023
bf0513c
Update x/incentives/README.md
p0mvn Jun 8, 2023
b809226
Update x/incentives/keeper/gauge_test.go
czarcas7ic Jun 8, 2023
db3d9c2
Update x/incentives/keeper/gauge.go
czarcas7ic Jun 8, 2023
c9760e6
refactor/fix: external vs internal pool id and gauge id links for "No…
p0mvn Jun 9, 2023
d3ce09a
superfluid comment
p0mvn Jun 9, 2023
c856cc4
disallow no lock gauge with duration set
p0mvn Jun 9, 2023
897e9df
test gauge distribution state update
p0mvn Jun 9, 2023
975275b
error message improvement
p0mvn Jun 9, 2023
56684e9
remove obsolete field
p0mvn Jun 9, 2023
4cc0e83
clarify test name
p0mvn Jun 9, 2023
657e293
updates
p0mvn Jun 9, 2023
52bd732
doc improvements
p0mvn Jun 9, 2023
f9a3d73
clean up TestDistribute_InternalIncentives_NoLock
p0mvn Jun 9, 2023
24ba68c
clarifying comment
p0mvn Jun 9, 2023
02049e6
updates
p0mvn Jun 9, 2023
2aa0fcc
Merge branch 'main' into roman/cl-external-incentives
p0mvn Jun 10, 2023
7499cff
Update x/incentives/keeper/distribute_test.go
p0mvn Jun 10, 2023
ffcaa04
error message
p0mvn Jun 10, 2023
692cb86
zero duration check and test
p0mvn Jun 10, 2023
a701132
clean up
p0mvn Jun 10, 2023
7cdf7ae
lint
p0mvn Jun 10, 2023
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
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}/x/incentives",
"program": "${workspaceFolder}/x/incentives/keeper",
"args": [
"-test.timeout",
"30m",
"-test.run",
"TestKeeperTestSuite/TestYourName",
"TestKeeperTestSuite/TestDistribute_ExternalIncentives_ConcentratedPool",
"-test.v"
],
},
Expand Down
14 changes: 13 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ test: test-unit test-build
test-all: test-race test-cover

test-unit:
@VERSION=$(VERSION) SKIP_WASM_WSL_TESTS=$(SKIP_WASM_WSL_TESTS) go test -mod=readonly -tags='ledger test_ledger_mock norace' $(PACKAGES_UNIT)
@VERSION=$(VERSION) SKIP_WASM_WSL_TESTS=$(SKIP_WASM_WSL_TESTS) go test -mod=readonly -tags='ledger test_ledger_mock norace' $(PACKAGES_UNIT) -count=1

test-race:
@VERSION=$(VERSION) go test -mod=readonly -race -tags='ledger test_ledger_mock' $(PACKAGES_UNIT)
Expand Down Expand Up @@ -459,6 +459,18 @@ localnet-cl-small-swap:
localnet-cl-large-swap:
go run tests/cl-go-client/main.go --operation 2

# creates a gauge and waits for one epoch so that the gauge
# is converted into an incentive record for pool id 1.
localnet-cl-external-incentive:
go run tests/cl-go-client/main.go --operation 3

# attempts to create a CL pool at id 1.
# if pool already exists, this is a no-op.
# if pool with different id is desired, tweak expectedPoolId
# in the script.
localnet-cl-create-pool:
go run tests/cl-go-client/main.go --operation 4

# does both of localnet-cl-create-positions and localnet-cl-small-swap
localnet-cl-positions-small-swaps: localnet-cl-create-positions localnet-cl-small-swap

Expand Down
6 changes: 6 additions & 0 deletions proto/osmosis/incentives/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ message MsgCreateGauge {
// num_epochs_paid_over is the number of epochs distribution will be completed
// over
uint64 num_epochs_paid_over = 6;

// pool_id is the ID of the pool that the gauge is meant to be associated
// with. if pool_id is set, then the "QueryCondition.LockQueryType" must be
// "NoLock" with all other fields unset.
// The denom query condition is set to "no-lock/{pool_id}" prefix in such a case.
uint64 pool_id = 7;
}
message MsgCreateGaugeResponse {}

Expand Down
1 change: 1 addition & 0 deletions proto/osmosis/lockup/lock.proto
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum LockQueryType {

ByDuration = 0;
ByTime = 1;
NoLock = 2;
}

// QueryCondition is a struct used for querying locks upon different conditions.
Expand Down
19 changes: 19 additions & 0 deletions tests/cl-go-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,22 @@ make localnet-cl-positions-large-swaps
```

This script runs "Create Positions" and "Make Large Invertible Swaps" scripts in sequence.

### Create Incentive

Creates a new gauge and waits for one epoch so that the gauge
is converted into an incentive record for pool id 1.

```bash
make localnet-cl-external-incentive
```

### Create Pool

Attempts to create a CL pool at id 1. If pool at id 1 already exists, this is a no-op.
If pool with different id is desired, tweak expectedPoolId in the script.

```bash
make localnet-cl-create-pool
```

2 changes: 1 addition & 1 deletion tests/cl-go-client/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ require (
github.com/nxadm/tail v1.4.8 // indirect
github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230516205127-c213fddde069 // indirect
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230606194542-47ea1e2c85ca // indirect
github.com/osmosis-labs/osmosis/v16 v16.0.0-20230603032959-4d2ba21b8d1e // indirect
github.com/osmosis-labs/osmosis/v16 v16.0.0-20230608013130-4c65a87ef8f1 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions tests/cl-go-client/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,8 @@ github.com/osmosis-labs/osmosis/v16 v16.0.0-20230602200356-bdf5b96b3674 h1:sCXD8
github.com/osmosis-labs/osmosis/v16 v16.0.0-20230602200356-bdf5b96b3674/go.mod h1:Vg+05vXFc682OEF52HTqhEKF+deQ0GSt9rkisCFJ8Ug=
github.com/osmosis-labs/osmosis/v16 v16.0.0-20230603032959-4d2ba21b8d1e h1:Rbkpe0cLh67eyWpCMN8u/6xDNHlWimrLceMEhtNJ0TI=
github.com/osmosis-labs/osmosis/v16 v16.0.0-20230603032959-4d2ba21b8d1e/go.mod h1:Vg+05vXFc682OEF52HTqhEKF+deQ0GSt9rkisCFJ8Ug=
github.com/osmosis-labs/osmosis/v16 v16.0.0-20230608013130-4c65a87ef8f1 h1:y3UZi17rDKrI26UHUM789NN0PfDa8sMxQ53d+5/QbfU=
github.com/osmosis-labs/osmosis/v16 v16.0.0-20230608013130-4c65a87ef8f1/go.mod h1:3+K8CJxnPSCzf+eytwgHCRlkWnFFf5lF3wqoxK2f7Dk=
github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 h1:RIrWLzIiZN5Xd2JOfSOtGZaf6V3qEQYg6EaDTAkMnCo=
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230331072320-5d6f6cfa2627 h1:A0SwZgp4bmJFbivYJc8mmVhMjrr3EdUZluBYFke11+w=
github.com/osmosis-labs/wasmd v0.31.0-osmo-v16 h1:X747cZYdnqc/+RV48iPVeGprpVb/fUWSaKGsZUWrdbg=
Expand Down
171 changes: 150 additions & 21 deletions tests/cl-go-client/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ import (
"github.com/ignite/cli/ignite/pkg/cosmosaccount"
"github.com/ignite/cli/ignite/pkg/cosmosclient"

clqueryproto "github.com/osmosis-labs/osmosis/v16/x/concentrated-liquidity/client/queryproto"
"github.com/osmosis-labs/osmosis/v16/x/concentrated-liquidity/model"
cltypes "github.com/osmosis-labs/osmosis/v16/x/concentrated-liquidity/types"
incentivestypes "github.com/osmosis-labs/osmosis/v16/x/incentives/types"
lockuptypes "github.com/osmosis-labs/osmosis/v16/x/lockup/types"
poolmanagerqueryproto "github.com/osmosis-labs/osmosis/v16/x/poolmanager/client/queryproto"
poolmanagertypes "github.com/osmosis-labs/osmosis/v16/x/poolmanager/types"
epochstypes "github.com/osmosis-labs/osmosis/x/epochs/types"
)

// operation defines the desired operation to be run by this script.
Expand All @@ -38,6 +42,12 @@ const (
// and swaps it back while accounting for the spread factor. This is done to
// ensure that we cross ticks while minimizing the chance of running out of funds or liquidity.
makeManyInvertibleLargeSwaps

// createExternalCLIncentives creates external CL incentives.
createExternalCLIncentives

// createPoolOperation creates a pool with expectedPoolId.
createPoolOperation
)

const (
Expand All @@ -49,19 +59,22 @@ const (
denom1 = "uusdc"
tickSpacing int64 = 100
accountNamePrefix = "lo-test"
numPositions = 100
numSwaps = 100
minAmountDeposited = int64(1_000_000)
randSeed = 1
maxAmountDeposited = 1_00_000_000
maxAmountSingleSwap = 1_000_000
largeSwapAmount = 90_000_000_000
// Note, this is localosmosis-specific.
expectedEpochIdentifier = "hour"
numPositions = 100
numSwaps = 100
minAmountDeposited = int64(1_000_000)
randSeed = 1
maxAmountDeposited = 1_00_000_000
maxAmountSingleSwap = 1_000_000
largeSwapAmount = 90_000_000_000
)

var (
defaultAccountName = fmt.Sprintf("%s%d", accountNamePrefix, 1)
defaultMinAmount = sdk.ZeroInt()
defaultSpreadFactor = sdk.MustNewDecFromStr("0.001")
externalGaugeCoins = sdk.NewCoins(sdk.NewCoin("uosmo", sdk.NewInt(1000_000_000)))
accountMutex sync.Mutex
)

Expand Down Expand Up @@ -97,26 +110,16 @@ func main() {

log.Println("connected to: ", "chain-id", statusResp.NodeInfo.Network, "height", statusResp.SyncInfo.LatestBlockHeight)

// Instantiate a query client
clQueryClient := poolmanagerqueryproto.NewQueryClient(igniteClient.Context())

// Print warnings with common problems
log.Printf("\n\n\nWARNING 1: your localosmosis and client home are assummed to be %s. Run 'osmosisd get-env' and confirm it matches the path you see printed here\n\n\n", clientHome)

log.Printf("\n\n\nWARNING 2: you are attempting to interact with pool id %d.\nConfirm that the pool exists. if this is not the pool you want to interact with, please change the expectedPoolId variable in the code\n\n\n", expectedPoolId)

log.Println("\n\n\nWARNING 3: sometimes the script hangs when just started. In that case, kill it and restart")

// Query pool with id 1 and create new if does not exist.
_, err = clQueryClient.Pool(ctx, &poolmanagerqueryproto.PoolRequest{PoolId: expectedPoolId})
if err != nil {
if !strings.Contains(err.Error(), poolmanagertypes.FailedToFindRouteError{PoolId: expectedPoolId}.Error()) {
log.Fatal(err)
}
createdPoolId := createPool(igniteClient, defaultAccountName)
if createdPoolId != expectedPoolId {
log.Fatalf("created pool id (%d), expected pool id (%d)", createdPoolId, expectedPoolId)
}
// Check if need to create pool before every opperation.
if operation(desiredOperation) != createPoolOperation {
createPoolOp(igniteClient)
}

rand.Seed(randSeed)
Expand All @@ -130,6 +133,10 @@ func main() {
return
case makeManyInvertibleLargeSwaps:
swapGivenLargeAmountsBothDirections(igniteClient, expectedPoolId, numSwaps, largeSwapAmount)
case createExternalCLIncentives:
createExternalCLIncentive(igniteClient, expectedPoolId, externalGaugeCoins, expectedEpochIdentifier)
case createPoolOperation:
createPoolOp(igniteClient)
default:
log.Fatalf("invalid operation: %d", desiredOperation)
}
Expand Down Expand Up @@ -231,6 +238,78 @@ func swapGivenLargeAmountsBothDirections(igniteClient cosmosclient.Client, poolI
log.Println("finished swapping, num swaps done", numSwaps)
}

func createExternalCLIncentive(igniteClient cosmosclient.Client, poolId uint64, gaugeCoins sdk.Coins, expectedEpochIdentifier string) {
var (
randAccountNum = rand.Intn(8) + 1
accountName = fmt.Sprintf("%s%d", accountNamePrefix, randAccountNum)
)

epochsQueryClient := epochstypes.NewQueryClient(igniteClient.Context())
currentEpochResponse, err := epochsQueryClient.CurrentEpoch(context.Background(), &epochstypes.QueryCurrentEpochRequest{
expectedEpochIdentifier,
})
if err != nil {
log.Fatal(err)
}

log.Println("current epoch", currentEpochResponse.CurrentEpoch, "epoch identifier", expectedEpochIdentifier)

log.Println("querying epoch info. Note that incentives are distributed at the end of epoch. That's why it matters.")
epochInfosRespose, err := epochsQueryClient.EpochInfos(context.Background(), &epochstypes.QueryEpochsInfoRequest{})
if err != nil {
log.Fatal(err)
}

if len(epochInfosRespose.Epochs) > 0 {
lastEpochInfo := epochInfosRespose.Epochs[len(epochInfosRespose.Epochs)-1]
log.Println("epoch duration", lastEpochInfo, "next epoch start time", lastEpochInfo.StartTime.Add(lastEpochInfo.Duration))
} else {
log.Println("could not find information about previous epoch. If duration is too long, this test might be infeasible")
}

//.Create gauge
runMessageWithRetries(func() error {
return createGauge(igniteClient, expectedPoolId, accountName, gaugeCoins)
})

epochAfterGaugeCreation := int64(-1)
for {
// Wait for 1 epoch to pass
currentEpochResponse, err = epochsQueryClient.CurrentEpoch(context.Background(), &epochstypes.QueryCurrentEpochRequest{
expectedEpochIdentifier,
})
if err != nil {
log.Fatal(err)
}
if epochAfterGaugeCreation == -1 {
log.Println("current epoch after gauge creation", currentEpochResponse.CurrentEpoch)
log.Println("waiting for next epoch...")
epochAfterGaugeCreation = currentEpochResponse.CurrentEpoch
continue
}

// One epoch after gauge creation has passed
if epochAfterGaugeCreation+1 == currentEpochResponse.CurrentEpoch {
log.Println("next epoch reached, checking incentive records...")
break
}

log.Println("current epoch", currentEpochResponse.CurrentEpoch)
time.Sleep(5 * time.Second)
}

clQueryClient := clqueryproto.NewQueryClient(igniteClient.Context())

incentiveRecordsResponse, err := clQueryClient.IncentiveRecords(context.Background(), &clqueryproto.IncentiveRecordsRequest{
PoolId: expectedPoolId,
})
if err != nil {
log.Fatal(err)
}

log.Println("incentive records. If empty, something probably went wrong", incentiveRecordsResponse.IncentiveRecords)
}

func createPool(igniteClient cosmosclient.Client, accountName string) uint64 {
msg := &model.MsgCreateConcentratedPool{
Sender: getAccountAddressFromKeyring(igniteClient, accountName),
Expand Down Expand Up @@ -309,6 +388,56 @@ func makeSwap(client cosmosclient.Client, poolId uint64, senderKeyringAccountNam
return resp.TokenOutAmount, nil
}

func createGauge(client cosmosclient.Client, poolId uint64, senderKeyringAccountName string, gaugeCoins sdk.Coins) error {
accountMutex.Lock() // Lock access to getAccountAddressFromKeyring
senderAddress := getAccountAddressFromKeyring(client, senderKeyringAccountName)
accountMutex.Unlock() // Unlock access to getAccountAddressFromKeyring

log.Println("creating CL gauge for pool id", expectedPoolId, "gaugeCoins", gaugeCoins)

msg := &incentivestypes.MsgCreateGauge{
IsPerpetual: false,
Owner: senderAddress,
DistributeTo: lockuptypes.QueryCondition{
LockQueryType: lockuptypes.NoLock,
},
StartTime: time.Now(),
Coins: gaugeCoins,
NumEpochsPaidOver: 5,
PoolId: expectedPoolId,
}
txResp, err := client.BroadcastTx(senderKeyringAccountName, msg)
if err != nil {
return err
}
resp := &incentivestypes.MsgCreateGaugeResponse{}
if err := txResp.Decode(resp); err != nil {
return err
}

log.Println("gauge created")
return nil
}

func createPoolOp(igniteClient cosmosclient.Client) {
// Instantiate a query client
poolManagerClient := poolmanagerqueryproto.NewQueryClient(igniteClient.Context())

// Query pool with id 1 and create new if does not exist.
_, err := poolManagerClient.Pool(context.Background(), &poolmanagerqueryproto.PoolRequest{PoolId: expectedPoolId})
if err != nil {
if !strings.Contains(err.Error(), poolmanagertypes.FailedToFindRouteError{PoolId: expectedPoolId}.Error()) {
log.Fatal(err)
}
createdPoolId := createPool(igniteClient, defaultAccountName)
if createdPoolId != expectedPoolId {
log.Fatalf("created pool id (%d), expected pool id (%d)", createdPoolId, expectedPoolId)
}
} else {
log.Println("pool already exists. Tweak expectedPoolId variable if you want another pool, current expectedPoolId", expectedPoolId)
}
}

func getAccountAddressFromKeyring(igniteClient cosmosclient.Client, accountName string) string {
account, err := igniteClient.Account(accountName)
if err != nil {
Expand Down Expand Up @@ -338,7 +467,7 @@ func runMessageWithRetries(runMsg func() error) {
for j := 0; j < maxRetries; j++ {
err := runMsg()
if err != nil {
log.Println("retrying, error occurred while creating position: ", err)
log.Println("retrying, error occurred while running message: ", err)
time.Sleep(8 * time.Second)
} else {
time.Sleep(200 * time.Millisecond)
Expand Down
4 changes: 2 additions & 2 deletions tests/localosmosis/scripts/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ edit_genesis () {
dasel put string -f $GENESIS '.app_state.incentives.lockable_durations.[1]' "120s"
dasel put string -f $GENESIS '.app_state.incentives.lockable_durations.[2]' "180s"
dasel put string -f $GENESIS '.app_state.incentives.lockable_durations.[3]' "240s"
dasel put string -f $GENESIS '.app_state.incentives.params.distr_epoch_identifier' "day"
dasel put string -f $GENESIS '.app_state.incentives.params.distr_epoch_identifier' "hour"

# Update mint module
dasel put string -f $GENESIS '.app_state.mint.params.mint_denom' "uosmo"
dasel put string -f $GENESIS '.app_state.mint.params.epoch_identifier' "day"
dasel put string -f $GENESIS '.app_state.mint.params.epoch_identifier' "hour"

# Update poolmanager module
dasel put string -f $GENESIS '.app_state.poolmanager.params.pool_creation_fee.[0].denom' "uosmo"
Expand Down
2 changes: 1 addition & 1 deletion x/cosmwasmpool/cosmwasm/msg/transmuter/transmuter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (s *TransmuterSuite) TestFunctionalTransmuter() {
LockQueryType: lockuptypes.ByDuration,
Denom: expectedShareDenom,
Duration: lockDuration,
}, s.Ctx.BlockTime(), 1)
}, s.Ctx.BlockTime(), 1, 0)
s.Require().NoError(err)
gauge, err := s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, gaugeId)
s.Require().NoError(err)
Expand Down
2 changes: 1 addition & 1 deletion x/incentives/keeper/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func benchmarkDistributionLogic(b *testing.B, numAccts, numDenoms, numGauges, nu
numEpochsPaidOver = uint64(r.Int63n(durationMillisecs/millisecsPerEpoch)) + 1
}

gaugeId, err := app.IncentivesKeeper.CreateGauge(ctx, isPerpetual, addr, rewards, distributeTo, startTime, numEpochsPaidOver)
gaugeId, err := app.IncentivesKeeper.CreateGauge(ctx, isPerpetual, addr, rewards, distributeTo, startTime, numEpochsPaidOver, 0)
if err != nil {
fmt.Printf("Create Gauge, %v\n", err)
b.FailNow()
Expand Down
Loading