osmosis-labs / osmosis Goto Github PK
View Code? Open in Web Editor NEWThe AMM Laboratory
Home Page: https://app.osmosis.zone
License: Apache License 2.0
The AMM Laboratory
Home Page: https://app.osmosis.zone
License: Apache License 2.0
If people want to do a trade between two assets that aren’t in the same pool, we need to construct a multihop swap.
To do this, we should switch the PoolId
in a SwapMsg to into a Route
which is an ordered list of PoolIds.
So for example:
type MsgSwapExactAmountIn struct {
Sender string
PoolId uint64
TokenIn types.Coin
TokenOutDenom string
TokenOutMinAmount github_com_cosmos_cosmos_sdk_types.Int
MaxSpotPrice github_com_cosmos_cosmos_sdk_types.Dec
}
would become
type MsgSwapExactAmountIn struct {
Sender string
Route []PoolId (int64)
TokenIn types.Coin
TokenOutDenom string
TokenOutMinAmount github_com_cosmos_cosmos_sdk_types.Int
MaxSpotPrice github_com_cosmos_cosmos_sdk_types.Dec
}
As title. We should allow pool's to be specified by a JSON representation, not many distinct CLI arguments. (Especially as there's really no way to 'undo' a pool creation)
This is similar to whats done in the SDK for governance proposals, we can likely lift a lot of the logic from there.
The mint module doesn't depend on staking anymore, so this dependency can be removed.
Needed in order to keep proper security model for LockupKeeper.
See discussion here:
#22 (comment)
Reference:
https://stackoverflow.com/questions/24622388/how-to-test-a-unexported-private-function-in-go-golang
Currently just says osmosisd tx lockup lock-tokens [flags]
Should have examples of required flags
I think the ForEvent
suffix is not helpful here, as this parameter lives within x/mint
, in which case there is only one such factor.
Since we have no pool-specific governance at launch, it doesn't make sense to have pools get created with lock's (which is already disabled).
We should remove this field from MsgCreatePool
, and then have pools default to have locks off.
When we add support for x/gamm simulation, we should move the spot price checks from
osmosis/x/gamm/keeper/swap_test.go
Lines 82 to 94 in b6cc74c
The CLI and GRPC tests should be run using the norace build flag in CI. Need to make sure -tag=norace
is passed in to the CI's test commands so it runs these tests and doesn't skip them.
By default, when providing liquidity, liquidity providers receive back liquid LP tokens. We want a way to allow liquidity providers to lock their LP tokens for a minimum locktime (i.e. 1 month, 3 months, etc). This lock-ups will help guarantee long term liquidity, which will prevent Vampire Attacks.
These lockups should be easily queryable by other modules, that want to grant certain powers to long-term LPs.
Examples can include:
The repo's go.mod declares this as github.com/c-osmosis/osmosis
. We should switch this this to github.com/osmosis-labs/osmosis
.
We should add a markdown linter to CI, ala https://github.com/tendermint/spec/blob/master/.github/workflows/linter.yml
When you run make all
twice, it gives me a bunch of errors about the Query proto types not satisfying protoreflect.ProtoMessage (missing ProtoReflect method)
# github.com/c-osmosis/osmosis/x/gamm/types
x/gamm/types/query.pb.gw.go:56:2: cannot use msg (type *QueryPoolResponse) as type protoreflect.ProtoMessage in return argument:
*QueryPoolResponse does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:82:2: cannot use msg (type *QueryPoolResponse) as type protoreflect.ProtoMessage in return argument:
*QueryPoolResponse does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:97:44: cannot use &protoReq (type *QueryPoolsRequest) as type protoreflect.ProtoMessage in argument to "github.com/grpc-ecosystem/grpc-gateway/v2/runtime".PopulateQueryParameters:
*QueryPoolsRequest does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:102:2: cannot use msg (type *QueryPoolsResponse) as type protoreflect.ProtoMessage in return argument:
*QueryPoolsResponse does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:113:44: cannot use &protoReq (type *QueryPoolsRequest) as type protoreflect.ProtoMessage in argument to "github.com/grpc-ecosystem/grpc-gateway/v2/runtime".PopulateQueryParameters:
*QueryPoolsRequest does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:118:2: cannot use msg (type *QueryPoolsResponse) as type protoreflect.ProtoMessage in return argument:
*QueryPoolsResponse does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:144:2: cannot use msg (type *QueryPoolParamsResponse) as type protoreflect.ProtoMessage in return argument:
*QueryPoolParamsResponse does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:170:2: cannot use msg (type *QueryPoolParamsResponse) as type protoreflect.ProtoMessage in return argument:
*QueryPoolParamsResponse does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:196:2: cannot use msg (type *QueryTotalShareResponse) as type protoreflect.ProtoMessage in return argument:
*QueryTotalShareResponse does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:222:2: cannot use msg (type *QueryTotalShareResponse) as type protoreflect.ProtoMessage in return argument:
*QueryTotalShareResponse does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
x/gamm/types/query.pb.gw.go:222:2: too many errors
make: *** [osmosis] Error 2
This feature was removed from v0 launch roadmap. Should be removed from the current master codebase.
Currently, the initial shares given to the first LP of a pool is 100 * 10^6. I wonder if this might not have enough precision. Especially, because usually the initial creator of a pool might be a massive whale (such as the project team) to kickstart the pool and add an extremely high amount of liquidity.
Balancer uses 100 * 10^18 as the initial shares amount.
https://github.com/balancer-labs/balancer-core/blob/master/contracts/BConst.sol#L33
Maybe we should use something similar?
After #60, we have no way for a pool to specify who its future governor will be, once we build support for it.
Lets add a string for "Future owner of a pool". This can be an address, or a This LP Token, lockup time
pair. We then need to build a "validate owner string" function.
Then next upgrade when we implement pool-specific governance, we automatically port the governor specification from this string.
Originally posted by @ValarDragon in #60 (comment)
Otherwise pool creators could silently fail, and potentially waste funds
We should add a minimum commission rate that validators are allowed to set to avoid a race to the bottom for validators.
This will have to be done in https://github.com/osmosis-labs/cosmos-sdk
But found you ❤
If they aren't, we should either make them ADR 028 compliant, or remove the addresses for now.
See example from crypto.com chain
https://github.com/crypto-org-chain/chain-main/blob/master/config/config.go#L20
GetRewardsEst
(which is called in RewardsEst
grpc query) calls FilteredLocksDistributionEst
, which iterates all over the locked tokens(https://github.com/osmosis-labs/osmosis/blob/main/x/incentives/keeper/pot.go#L164). This causes issues on performance side, as it need to recalculate the reward every time when the query happens.
The suggested solution is limit the lockup period to the epoch, and make the lockup module updates the total amount when there is lock related event happens. The incentive module will read the cached state when queried.
ref @Thunnini
In some of the modules' proto files, addresses are defined by bytes to be gogoproto casted to sdk.AccAddress
Example:
message MsgCreatePot {
bool is_perpetual = 1; // flag to show if it's perpetual or multi-epoch
// distribution incentives by third party
bytes owner = 2 [ (gogoproto.casttype) =
"github.com/cosmos/cosmos-sdk/types.AccAddress" ];
...
These should be switched to strings as this is the standard in the cosmos sdk now.
We need a way to keep a perpetual pot. Such a pot should distribute it's full balance every epoch, but the pot shouldn't disappear afterwards. This is what OSMO rewards will probably go into.
Like the weekly minted amount should go into a perpetual pot that distributes for 1 epoch. But new coins will be sent to this same pot every week until governance decides to vote to change it.
We should have a CI process to run tests, simulations, etc.
We initially delayed the idea of using an F1-based reward distribution mechanism for Osmosis due to concerns on the timeline, but I do think we can adopt the F1-based module without significantly delaying the launch schedule. I believe there are minimal benefits of an epoch-based system over the F1-based system, and only opens up spam attack risk vectors as well as instability in the block times due to the iterations required.
The x/farm module provides a much more sustainable and manageable architecture, and I've made progress on the implementation that I believe it will create no delays for launch. (Refer to the pool-yield branch)
Below is an outline of how the current architecture functions.
afterPoolCreate
hook created.lockableDurations
at genesis (i.e. 1 week / 2 week / 4 week)lockableDurations
) when the x/gamm afterPoolCreate
is runonTokenLocked
- When the hook runs this, the pool-yield module checks if the locked token is the pool share token. If it is a pool share token, then it will check if the duration matches the lockableDurations
. If both conditions are true, it will get the farm and add the farm share according to the locked poolShare amount. (Because the farm module doesn't custody the farm's share, the lockup module custodies the shares.)onTokenUnlocked
- This is the opposite process of onTokenLocked
.poolId
and lockableDurations
and find the farmId
.AddPoolIncentives
proposal can be used to add records. The records consist of farm Id and weight. When the record is added, reward is allocated according to the record's farm ID. The reward amount equals to weight/ totalWeight.
RemovePoolIncentives
proposal is the opposite of the above proposalmintedDenom
according to the allocationRatio
from the feeCollector module account then distributes the amount to farms according to the logic described above, then the distribution module uses the remaining amount.updatePoolIncentives
proposal type.Not sure whats the better name to be using, but it definitely shouldn't be denormalized. Denormal numbers are something very different in relevant contexts =) https://en.wikipedia.org/wiki/Denormal_number (Essentially an edge case of things with floats)
I think we will have a growing number of math operations that we will need high precision & fast implementations of. I think we should move such functions & related types into its own osmo-math
package in the root directory. For now, Pow
with fractional exponent would go in there.
I was hoping to apply the x/farm
module to the x/gamm
module as well. Currently, the x/gamm
fee distribution mechanism accumulates the swap fees then gives the fee to the user upon claiming in proportion to the shares owned, so technically an LP who deposited later has some advantages if other users don’t claim their portion of the rewards as often. Therefore, I believe the F1 fee distribution mechanism is more reasonable so we should apply to the x/gamm
module as well. Also, since there is no way to distribute the exit fee and the F1 distribution module will allow this as well.
However, this brings up another issue since each LP tokens have a different amount of fee reward accumulated, so unlocked LP tokens are technically not fungible with each other unless there is additional logic to stake the shares. Perhaps staking the share token upon minting by default could solve this. But the bigger issue that I see is that when the pool’s share tokens are staked to the pool, the lockup module isn’t able to be used. One option is to change the lockup module’s architecture, as going with the current implementation will force users to choose whether to receive the pool rewards or the Osmo farming rewards.
Pros:
Cons:
We want at least two types of pool locking for our Balancer pool type. (Following adapted from @sunnya97 )
Currently we only have one Lock boolean, which locks just anyone from adding or removing liquidity.
I believe lockable liquidity providing is captured by a permission for "can anyone add liquidity", with some ability to specify exceptions to this rule.
Lockable trading probably should be up to the AMM to decide conditions of. Namely, a natural one is "trading is locked until liquidity of asset A in the pool is > x".
We should revisit enabling capabilities for this after minimum viable osmosis.
Currently, a number of modules use epochs for different purposes (i.e. incentives uses it to determine when to distribute coins from pots, mint uses it to determine how often to create newly issued coins, etc). In the future, we may want more stuff to use epochs as well (i.e. epoched staking, distribution).
All these different epochs could get quite annoying I think, especially if they are different lengths or offset from each other.
Should we combine all of these epochs into one epochs
module, that others can import? This new module can have a hook called EpochEnd(ctx, epochNum)
, that these other modules can connect to.
This will allow a single global epoch system that I think will make things easier for end users to understand.
Is there any reason why some of these modules will need a bespoke epoch length?
Record in the pools currently refers to an (asset_denom, weight) pair. I believe the name record is fairly misleading for this.
I suggest we rename Record
to PoolAssetType
. (Or perhaps a better name if anyone can think of one)
Upgrade to final release of Stargate
Currently, only the TypeEvtUpdateSwapFee
and the TypeEvtPoolCreated
events are being emitted. Need to emit events for the other x/gamm actions as well
We should add tests for marshalling to/from all of our proto types, both just as a consistency test, and because alot of our types code coverage just looks abysmal without it 😬. (its at 5% in x/gamm/types)
Currently powApprox
under gamm/keeper/math.go
is using a lot of resources. BenchmarkPow()
test will measure the performance of the function. I’m ran 10 small pows on my MBP(2018/2.3GHz 8 Core i9/16GB RAM) and this was the result I got:
go test -bench . -benchmem -cpu 1,2,4,8,16
goos: darwin
goarch: amd64
pkg: github.com/c-osmosis/osmosis/x/gamm/keeper
BenchmarkPow 25 51252602 ns/op 30098473 B/op 898416 allocs/op
BenchmarkPow-2 26 46804606 ns/op 30099396 B/op 898423 allocs/op
BenchmarkPow-4 24 46385548 ns/op 30100596 B/op 898430 allocs/op
BenchmarkPow-8 24 45494231 ns/op 30102812 B/op 898441 allocs/op
BenchmarkPow-16 25 45395677 ns/op 30106263 B/op 898449 allocs/op
PASS
Because multithreading is not used, the number of CPU cores shouldn’t matter, but it does require a lot of memory space and allocation.
Currently, the function is used to find a rational number exponent of a rational number. However, this seems to require too many loops so speed and memory becomes an issue.
The current implementation uses an expanded recursion function to find the binomial series so using multithreading will be difficult.
As for the memory, Cosmos-SDK’s sdk.Dec
is immutable so it’s safer to use, but requires memory allocation every single time so it uses a lot of memory. To run some tests on the benefits, I’ve created a temporary mutable dec
type under the gamm-math-perf
branch.
The following are the results:
goos: darwin
goarch: amd64
pkg: github.com/c-osmosis/osmosis/x/gamm/keeper
BenchmarkPow 40 29956045 ns/op 3770156 B/op 171524 allocs/op
BenchmarkPow-2 39 28767250 ns/op 3770280 B/op 171525 allocs/op
BenchmarkPow-4 40 28282755 ns/op 3770435 B/op 171526 allocs/op
BenchmarkPow-8 40 28204827 ns/op 3770722 B/op 171527 allocs/op
BenchmarkPow-16 40 28658882 ns/op 3771151 B/op 171528 allocs/op
PASS
It seems like memory allocation and memory use has definitely decreased. So the speed is a bit faster. But using a mutable dec will require extra caution, and because it’s different from Cosmos-SDK’s sdk.Dec
each must be managed separately and must be well checked for bugs.
Pros:
Cons:
sdk.Dec
-> may have bugs.See make lint
for what command we should be running
what would be the different between staking with the LP token vs the native zone token by itself? Could this same configuration be for the hub itself?
Initial fairdrop coins need to go through claim process of participating in the network
The types for InitialPoolWeights and for TargetPoolWeights in the SmoothWeightChangeParams are both []PoolAsset
type SmoothWeightChangeParams struct {
StartTime time.Time
Duration time.Duration
InitialPoolWeights []PoolAsset
TargetPoolWeights []PoolAsset
}
But PoolAsset is defined as
type PoolAsset struct {
Token sdk.Coin
Weight sdk.Int
}
But this doesn’t make sense because sdk.Coin includes an amount, but all we want for InitialPoolWeights and TargetPoolWeights is a denom and a weight
I think this comes down to the PoolAsset abstraction just doesn’t make sense
Why are we trying to combine the balance of a pool into the same struct as the weights of the assets? Just to save on storing the denom twice?
A pool’s balances should just be sdk.Coins, and the pool’s weights could be also sdk.Coins, but might make sense to just alias that to a new type called poolWeights (for type safety)
Currently we have two functions: CalculateSpotPrice
and CalculateSpotPriceSansFee
.
I know, this is using the naming used in the Balancer code, but I think this nomenclature of SpotPrice including fees is quite non-standard in industry and we should it correctly. (Even the balancer docs, define spot price as not including fees: https://docs.balancer.finance/core-concepts/protocol/index#spot-price).
I'd recommend switching:
CalculateSpotPriceSansFee
-> CalculateSpotPrice
CalculateSpotPrice
-> CalculateSpotPriceWithFee
.A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.