diff --git a/contracts/keeper/README-NEW.md b/contracts/keeper/README-NEW.md
new file mode 100644
index 00000000..e69de29b
diff --git a/contracts/multi_staking/README.md b/contracts/multi_staking/README.md
index b9469223..12b57f17 100644
--- a/contracts/multi_staking/README.md
+++ b/contracts/multi_staking/README.md
@@ -22,11 +22,603 @@ Dexter Multi-staking contract enables LP incentivization mechanism on Dexter. It
Following transition functions can only be executed by the `owner` of the contract.
#### 1. _**Create Reward Schedule**_
-Creates a new reward schedule. Owner can create a reward sFchedule on the behalf of a user.
+Allows the contract owner to create a new reward schedule. Owner can create this schedule on behalf of another user (particularly useful with XPRT governance).
+Before introduction in V3.0 of the contract, the contract used to follow a proposal / accept based flow for creation of reward schedules. That has been removed in favour of chain governance based approach where Governance Admin contract through it's admin privileges can create a new reward schedule if approved by the chain governance.
+##### Example
+```json
+{
+ "create_reward_schedule": {
+ "lp_token": "persistence",
+ "title": "Create reward schedule for DYDX/USDC Pool",
+ "actual_creator": null,
+ "start_block_time": 10000,
+ "end_block_time": 20000
+ }
+}
+```
+See more examples for usages in tests [here](TODO)
+### 2. _**Update Config**_
+Allows the contract owner to update config params. Can update any of the following parameters selectively by only including that key
+Primary params that support update are:
+a. **keeper_addr**: fee collector address
+b. **unlock_period**: lockup period after unbonding for which the tokens are in an unlocking state.
+c. **instant_unbond_fee_bp**: fee in basis points for Instant LP unbonding feature.
+d. **instant_unbond_min_fee_bp**: min fee for tier based fee structure for instant-unlock feature for unlocking liquidity during the unlocking period.
+e. **fee_tier_interval**: interval for fee tier change. the unlock period is divided into tiers for partial unbond fee during unlock period.
+```json
+{
+ "keeper_addr": "",
+}
+
+```
+
+### 3. _**Allow LP Token**_
+
+Allows the contract owner to add a new LP token to the contract. This is needed before reward schedule creation for that LP token.
+
+```json
+{
+ "allow_lp_token": {
+ "lp_token": ""
+ }
+}
+
+```
+
+### 4. _**Remove LP Token**_
+
+Remove LP Token from allowed list. Existing reward schedules for this LP token will remain unaffected.
+
+```json
+{
+ "remove_lp_token": {
+ "lp_token": ""
+ }
+}
+```
+
+### 5. _**Propose new owner**_
+
+Allows the contract owner to propose a new owner for the contract. The new owner needs to accept the proposal before becoming the new owner.
+
+```json
+{
+ "propose_new_owner": {
+ "new_owner": ""
+ }
+}
+```
+
+### 6. _**Drop ownership (transfer) proposal**_
+
+Allows the contract owner to drop the ownership proposal if they initiated one earlier. Applicable only till the new owner has not accepted the proposal.
+
+```json
+{
+ "drop_ownership_proposal": {}
+}
+```
+
+### User executable
+
+Following transition functions can be executed by any user who wants to bond / unbond LP tokens in the contract.
+
+### 1. _**Bond**_
+
+Allows the user to bond LP tokens in the contract. The user can bond multiple times for the same LP token. The bonded amount is added to the existing bonded amount for that user. User needs to allow spending of LP tokens to the contract before bonding.
+
+
+```json
+{
+ "bond": {
+ "lp_token": "",
+ "amount": "1000000000000000000000000"
+ }
+}
+```
+
+### 2. _**Unbond**_
+
+Allows the user to unbond LP tokens in the contract. Unbonded tokens enter a lockup period after which they can be withdrawn.
+During the lockup period, the user can use Instant Unlock feature to withdraw their LP tokens instantly by paying a fee. The fee is calculated based on the time remaining in the lockup period and the fee tier structure. The fee tier structure is defined by the contract owner and can be updated by the owner.
+
+```json
+{
+ "unbond": {
+ "lp_token": "",
+ "amount": "1000000000000000000000000"
+ }
+}
+```
+
+### 3. _**Unlock**_
+Allows the user to receive LP tokens after the lockup period. This functions calculates all the currently unlocked (which could be in multiple token locks) and sends them to the user.
+
+```json
+{
+ "unlock": {
+ "lp_token": "",
+ }
+}
+```
+
+### 4. _**Instant Unbond**_
+
+Allows the user to instantly unbond LP tokens in the contract without entering a lockup period. The user needs to pay a fee for this feature.
+
+```json
+{
+ "instant_unbond": {
+ "lp_token": "",
+ "amount": "1000000000000000000000000"
+ }
+}
+```
+
+### 5. _**Instant Unloock**_
+
+
+Allows the user to instantly unlock LP tokens in the contract if they are in the lockup period. The user needs to pay a fee for this feature which is calculated based on the time remaining in the lockup period and the fee tier structure.
+
+```json
+{
+ "instant_unlock": {
+ "lp_token": "",
+ "token_locks": [
+ {
+ "unlock_time": 10000,
+ "amount": "1000000000"
+ }
+ ]
+ }
+}
+```
+
+### 5. _**Withdraw (Rewards)**_
+
+Allows a user to withdraw the unclaimed reward from last claim time that has been accrued for them from any reward schedules.
+
+```json
+{
+ "withdraw": {
+ "lp_token": "",
+ }
+}
+```
+
+### Reward creator executable
+
+Following transition functions can be executed by the reward schedule creator. This is a special role that is assigned to the user on behalf on whom the owner creates the reward schedule. This is particularly useful for XPRT governance where the governance admin contract would create reward schedules on behalf of the actual creator.
+
+### 1. _**Claim Unallocated Rewards**_
+
+Allows the reward schedule creator to claim any unallocated rewards from the reward schedule. This is useful when the reward schedule has an interim period of
+no bonded tokens and thus no rewards are being distributed. The creator can claim these rewards back.
+
+```json
+{
+ "claim_unallocated_rewards": {
+ "lp_token": "",
+ }
+}
+```
+
+
+### New proposed owner executable
+
+Following transition functions can be executed by the new proposed owner of the contract. This is a special role that is assigned to the user who has been proposed as the new owner of the contract.
+
+### 1. _**Claim Ownership**_
+
+Allows the new proposed owner to claim ownership of the contract. This is needed after the current owner has proposed a new owner.
+
+```json
+{
+ "claim_ownership": {}
+}
+```
+
+
+
+### Supported Queries
+
+#### 1. _**Config**_
+
+Returns the current config of the contract.
+
+##### Query:
+
+```json
+{
+ "config": {}
+}
+```
+
+##### Response:
+
+```json
+{
+ // use persistence address
+ "owner": "persistence1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v",
+ "keeper": "persistence1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v",
+ "allowed_lp_tokens": [
+ "persistence1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v"
+ ],
+ "unlock_period": 86400,
+ "minimum_reward_schedule_proposal_start_delay": 86400,
+ "instant_unbond_fee_bp": 100,
+ "fee_tier_interval": 86400,
+ "instant_unbond_min_fee_bp": 100
+}
+```
+
+
+### 2. _**Reward Schedules**_
+
+Returns the list of reward schedules created in the contract for a particular LP token and reward asset.
+
+##### Request
+
+```json
+{
+ "reward_schedules": {
+ "lp_token": "",
+ "asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ }
+ }
+}
+```
+
+#### Response
+```json
+[
+ {
+ "id": 12,
+ "reward_schedule": {
+ "title": "Sample reward schedule",
+ "creator": "persitence",
+ "asset": {
+ "native_token": {
+ "uxprt"
+ }
+ },
+ "amount": "10000000000",
+ "staking_lp_token": "",
+ "start_block_time": 17000000000,
+ "end_block_time": 18000000000,
+ }
+ }
+ ...
+]
+```
+
+### 3. _**Bonded LP Token**_
+
+Query amount of LP token bonded by the user for a particular LP token
+
+#### Request
+
+```json
+{
+ "bonded_lp_tokens": {
+ "lp_token": "",
+ "user": ""
+ }
+}
+```
+
+#### Response
+
+```json
+"10000000"
+```
+
+### 4. _**Unclaimed Rewards**_
+
+Query the unclaimed reward by the user. This can be queried for the current time or any future block time based on the current active reward schedules. Past block time is an invalid argument.
+
+#### Request
+```json
+{
+ "unclaimed_rewards": {
+ "lp_token": "",
+ "user": "",
+ "block_time": null
+ }
+}
+```
+
+#### Response
+```json
+[
+ {
+ "asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ammount": "10000000"
+ },
+ {
+ "asset": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "ammount": "12000000"
+ }
+]
+```
+
+### 5. _**Creator Claimable Reward**_
+
+Returns the reward that creator of a reward schedule can claim back in case no liquidity was bonded over a certain period. This is to handle the edge case where due to no liquidity being bonded for a period, the corresponding reward during that time become stuck in the contract.
+This reward is claimable strictly after the reward schedule period is over.
+
+
+#### Request
+```json
+{
+ "creator_claimable_reward": {
+ "reward_schedule_id": 2
+ }
+}
+```
+
+#### Response
+```json
+{
+ "claimed": false,
+ "amount": "10000000",
+ "last_update": 1230000 // block time for the last time creator claimable reward was calculated
+}
+```
+
+### 6. _**Allowed LP Tokens for reward**_
+
+Multi-staking contract only whitelists a set of LP tokens which are elligible to receive reward schedules. This is ensure that only active pools get new reward schedules, and spam can be prevented.
+
+#### Request
+```json
+{
+ "allowed_lp_tokens_for_reward": {}
+}
+```
+
+#### Response
+```json
+[
+ "", ""
+]
+```
+
+### 7. _**Owner**_
+
+Returns the address of the owner of the contract
+
+#### Request
+```json
+{
+ "owner": {}
+}
+```
+
+#### Response
+```json
+""
+```
+
+### 5. _**Token Locks**_
+
+Returns the token locks for a LP token, and also the currently unlocked but not-withdrawn value of the LP token that is present in the contract. It can be queried for a future block time also to find how much value is going to be unlocked at a particular time in the future.
+
+#### Request
+```json
+{
+ "token_locks": {
+ "lp_token": "",
+ "user": "",
+ "block_time": null
+ }
+}
+
+```
+
+#### Response
+```json
+{
+ "locks": [
+ {
+ "unlock_time": 2000000,
+ "amount": "10000000"
+ },
+ {
+ "unlock_time": 2001000,
+ "amount": "12000000"
+ }
+ ],
+ "unlocked_amount": "20000000"
+}
+```
+
+### 6. _**Raw token locks**_
+
+Returns raw state of the token locks for a user for a given LP token. It might include the token locks which are already unlocked and won't give the current ideal view of the token locks but the actual one as it is stored in the contract
+
+#### Request
+```json
+{
+ "raw_token_locks": {
+ "lp_token": "",
+ "user": "",
+ }
+}
+```
+
+#### Response
+```json
+[
+ {
+ "unlock_time": 1999000,
+ "amount": "20000000"
+ },
+ {
+ "unlock_time": 2000000,
+ "amount": "10000000"
+ },
+ {
+ "unlock_time": 2001000,
+ "amount": "12000000"
+ }
+]
+```
+
+### 7. _**Instant Unlock Fee**_
+
+Query unlock fee for a currently running lock. The instant-unlock mechanism follows a fee tier mechanism where the fee charged decreases based on the set fee-tier interval. The maximum fee percentage charged is equal to the instant unbond fee, and minimum fee percent is based on the `instant_unbond_min_fee_bp` parameter.
+
+#### Request
+```json
+{
+ "instant_unlock_fee": {
+ "user": "",
+ "lp_token": "",
+ "token_lock": {
+ "unlock_time": 2000000,
+ "amount": "10000000"
+ }
+ }
+}
+```
+
+#### Response
+```json
+{
+ "time_until_lock_expiry": 100000,
+ "unlock_fee_bp": 300,
+ "unlock_fee": "300000",
+ "unlock_amount": "10000000"
+}
+```
+
+### 8. _**Instant Unlock fee tiers**_
+
+Returns current Instant Unlock fee tiers based on the configured lock period, fee tier interval and the min and max unlock fee. Refer to the tests for better understanding and clarity of usage.
+
+#### Request
+```json
+{
+ "instant_unlock_fee_tiers": {}
+}
+```
+
+#### Response
+```json
+[
+ {
+ "seconds_till_unlock_start": "0",
+ "seconds_till_unlock_end": "1000",
+ "unlock_fee_bp": 200
+ },
+ {
+ "seconds_till_unlock_start": "1000",
+ "seconds_till_unlock_end": "2000",
+ "unlock_fee_bp": 300
+ },
+ {
+ "seconds_till_unlock_start": "2000",
+ "seconds_till_unlock_end": "3000",
+ "unlock_fee_bp": 400
+ }
+]
+```
+
+
+### 4. _**Reward State**_
+
+Returns the current global reward state for a given LP token and reward asset combination. For each such combination we maintain a reward index, which tracks the rate of growth of reward distribution for that asset based on current running reward schedules. All current stakers are distributed based on a ratio of this reward index.
+
+##### Request
+
+```json
+{
+ "lp_token": "",
+ "asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ }
+}
+```
+
+##### Response
+
+```json
+{
+ "reward_index": "0.45",
+ "last_distributed": 19000000
+}
+```
+
+
+### 5. _**Staker Info**_
+
+Returns the staking information for a given user based on the last interaction with the contract. This can be used to find pending reward for this asset for the staker
+
+#### Request
+
+```json
+{
+ "lp_token": "",
+ "asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "user": ""
+}
+```
+
+#### Response
+
+```json
+{
+ "asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "reward_index": "0.40",
+ "pending_reward": "50000000"
+}
+```
+
+
+
+## Changelog
+
+v1.0 - Initial release
+- Added multi-staking contract with proposal based flow for reward schedule creation.
+
+v2.0 - Instant LP Unbonding
+- Added Instant LP unbonding feature. LP Tokens can be unbonded with a fixed fee instantly. Also, support Instant unlock feature where a currently running unbonding lock can be unlocked instantly by paying a fee based on a fee tier based mechanism.
+
+v2.1 - Fix release
+- Made keeper address updatable via a config change execution message.
+
+v2.2 - Remove proposal flow for reward schedule
+- Removed the proposal flow for the reward schedule in favor of only contract owner being able to create reward schedule. This release was bumped up to v3.0 due to API incompatibility with v2.x
+
+v3.0 - Remove proposal flow for reward schedule
+- Added migration entrypoints from v1.0 and other valid contract versions.
+- mostly a bump up from v2.2 for contract API compatibility
diff --git a/contracts/pools/stable_pool/README.md b/contracts/pools/stable_pool/README.md
index 834512b3..f4480e3c 100644
--- a/contracts/pools/stable_pool/README.md
+++ b/contracts/pools/stable_pool/README.md
@@ -1,183 +1,535 @@
-# Dexter Protocol :: Stable-5-Pool
+# Dexter: Stableswap Pool
+
+Dexter implements a generic version of Curve's stableswap invariant for upto 5 assets in the pool and implements compute calculations on liquidity provision / withdrawal and swaps.
+
+Dexter's contract architecture is unique in that it separates the ownership of the assets in the pool in the Vault contract. Pool contracts are only responsible for the math computes which dictate number of tokens to be transferred during swaps / liquidity provisioning events, and do not handle the token transfers themselves.
+
+Dexter's Vault queries the Pool contracts to compute how many tokens to transfer and processes those transfers itself.
+
+This separation simplifies pool contracts, since they no longer need to actively manage their assets; pools only need to calculate amounts for swaps, joins, and exits. New pool types, can be easily added which only implement the math computes and do not need to worry about the token transfer logic.
-Dexter's Stable-5-Pool implements the stableswap invariant for upto 5 assets in the pool and implements compute calculations on Liquidity provision / withdrawal and swaps.
## Contract State
| Message | Description |
| ------------ | ----------------------------------------------------------------------------------------------- |
-| `CONFIG` | Stores pool contract's core Configuration parameters in a [`Config`] struct |
+| `CONFIG` | Stores pool contract's core Configuration parameters in a [`Config`] struct. This is the base config that is same for all pool types. |
| `TWAPINFO` | Stores Twap prices for the tokens supported by the pool in a [`Twap`] struct |
| `MATHCONFIG` | Stores custom configuration parameters related with the stableswap invariant like AMP parameter |
+| `STABLESWAP_CONFIG` | Stores additional configurations like scaling factors (for metastable pools) and the max allowed spread |
+| `PRECISIONS` | Stores precision of all assets in the pool. For CW20 tokens, it is fetched using the contract, and for native assets, it must be specified during pool creation |
---
-- **Separating Token Accounting and Pool Logic**
- The Dexter Pools are responsible only for the math computes which dictate number of tokens to be transferred during swaps / liquidity provisioning events, and do not handle the token transfers themselves. Dexter's Vault queries the Pool contracts to compute how many tokens to transfer and processes those transfers itself.
+## Supported Execute Messages
- This separation simplifies pool contracts, since they no longer need to actively manage their assets; pools only need to calculate amounts for swaps, joins, and exits.
- Anyone who comes up with a novel idea for a trading system can make a custom pool and have it added to Dexter's PoolType Registery via approval from the Dexter DAO instead of needing to build their own Decentralized Exchange.
+### Update Config
-## Supported Execute Messages
+Executable only by Dexter Vault's owner. Updates the pool's math configuration with the specified parameters in the `params` variable encoded in base64.
-| Message | Description |
-| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `ExecuteMsg::UpdateConfig` | Executable only by Dexter Vault's owner. Updates the pool's math configuration with the specified parameters in the `params` variable. Accepts only `StartChangingAmp` and `StopChangingAmp` commands |
-| `ExecuteMsg::UpdateLiquidity` | Executable only by Dexter Vault. Updates locally stored asset balances state in `config.assets` for the pool and updates the TWAP. |
+Accepts the following commands in the `params` variable:
-## Supported Query Messages
+- `StartChangingAmp` : Starts the process of changing the amplification factor of the pool. It takes following params:
-| Message | Description |
-| -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `QueryMsg::Config()` | Returns the stored Vault Configuration settings in custom [`ConfigResponse`] struct |
-| `QueryMsg::FeeParams()` | Returns the provided [`PoolType`]'s Configuration settings in custom [`FeeResponse`] struct |
-| `QueryMsg::PoolId()` | Returns Pool ID which is of type [`Uint128`] |
-| `QueryMsg::OnJoinPool( assets_in, mint_amount , slippage_tolerance )` | Returns [`AfterJoinResponse`] type which contains - `return_assets` info, number of LP shares to be minted, the `response` of type [`ResponseType`] and `fee` of type [`Option`] which is the fee to be charged. |
-| `QueryMsg::OnExitPool( assets_out, burn_amount )` | Returns [`AfterExitResponse`] type which contains - `assets_out` info, number of LP shares to be burnt, the `response` of type [`ResponseType`] and `fee` of type [`Option`] which is the fee to be charged. |
-| `QueryMsg::OnSwap( swap_type, offer_asset, ask_asset, amount, max_spread, belief_price )` | Returns [`SwapResponse`] type which contains - `trade_params` info, the `response` of type [`ResponseType`] and `fee` of type [`Option`] which is the fee to be charged. |
-| `QueryMsg::CumulativePrice( swap_type, offer_asset, ask_asset, amount, max_spread, belief_price )` | Returns information about the cumulative price of the asset in a [`CumulativePriceResponse`] object. |
-| `QueryMsg::CumulativePrices( )` | Returns information about the cumulative prices in a [`CumulativePricesResponse`] object. |
+ - `next_amp` : The target amplification factor to reach at `next_amp_time`
+ - `next_amp_time` : The timestamp when the amplification factor should be `next_amp`. This should at least be equal to MIN_AMP_CHANGE_TIME which is currently hard-coded to 1 day.
-## Enums & Structs
+- `StopChangingAmp` : Stops the process of changing the amplification factor of the pool. It takes no params. It stops the amp at the current value.
-### `MathConfig` struct - This struct describes the main math configuration of the stable-pool.
+- `UpdateScalingFactor` : Updates the scaling factor of the asset in the pool. It takes following params:
-```
-struct MathConfig {
- // This is the current amplification used in the pool
- pub init_amp: u64,
- // This is the start time when amplification starts to scale up or down
- pub init_amp_time: u64,
- // This is the target amplification to reach at `next_amp_time`
- pub next_amp: u64,
- // This is the timestamp when the current pool amplification should be `next_amp`
- pub next_amp_time: u64,
- /// The greatest precision of assets in the pool
- pub greatest_precision: u8,
+ - `asset_info` : The asset whose scaling factor is to be updated
+ - `scaling_factor` : The new scaling factor for the asset
+
+- `UpdateScalingFactorManager` : Updates the scaling factor manager of the pool. It takes following params:
+
+ - `manager` : The new scaling factor manager for the pool
+
+- `UpdateMaxAllowedSpread` : Updates the max allowed spread between the price of the asset and the price of the pool. If the spread is greater than this value, the swap will fail. It takes following params:
+ - `max_allowed_spread` : The new max allowed spread for the pool
+
+The relevant struct can be found [here](../contracts/pools/stable_pool/src/state.rs#L122)
+
+#### Request
+
+Update message
+```json
+{
+ "start_changing_amp": {
+ "next_amp": 1000000000000000000,
+ "next_amp_time": 1629820800
+ }
}
```
-### `StablePoolUpdateParams` enum - This enum stores the options available to start and stop changing a stableswap pool's amplification. Used in the Execute::UpdateConfig function.
+We base64 encode the above message and pass it as the `params` variable in the Execute::UpdateConfig message.
+
+Update execute message to contract goes like
+```json
+{
+ "update_config": {
+ "params": ""
+ }
+}
```
-enum StablePoolUpdateParams {
- StartChangingAmp { next_amp: u64, next_amp_time: u64 },
- StopChangingAmp {},
+
+### Update Liquidity
+
+Executable only by Dexter Vault. Updates locally stored asset balances state in `config.assets` for the pool and updates the TWAP.
+
+
+#### Request
+
+```json
+{
+ "update_liquidity": {
+ "assets": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ }
+ ]
+ }
}
```
-### `ResponseType` enum - This enum is used to describe if the math computations (joins/exits/swaps) will be successful or not
+### Update Fee
-```
-enum ResponseType {
- Success {},
- Failure (String),
+Executable only by the Dexter Vault where it is triggerd by the Vault owner. Updates the fee for this particular pool. The fee is specified in basis points.
+
+
+#### Request
+
+```json
+{
+ "update_fee": {
+ "total_fee_bps": "1000"
+ }
}
```
-### `Config` struct - This struct describes the main control config of pool.
+## Supported Queries
+
+### Config
+Returns the stored pool configuration
+
+#### Request
+
+```json
+{
+ "config": {}
+}
```
-struct Config {
- /// ID of contract which is allowed to create pools of this type
- pub pool_id: Uint128,
- /// The address of the LP token associated with this pool
- pub lp_token_addr: Option,
- /// the vault contract address
- pub vault_addr: Addr,
- /// Assets supported by the pool
- pub assets: Vec,
- /// The pools type (provided in a [`PoolType`])
- pub pool_type: PoolType,
- /// The Fee details of the pool
- pub fee_info: FeeStructs,
- /// The block time when pool liquidity was last updated
- pub block_time_last: u64,
+
+#### Response
+
+```json
+{
+ "pool_id": "1",
+ "lp_token_addr": "persistence1...",
+ "vault_addr": "persistence1...",
+ "assets": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ }
+ ],
+ "pool_type": {
+ "stableswap": {}
+ },
+ "fee_info": {
+ "total_fee_bps": "1000"
+ },
+ "block_time_last": "1629820800",
+ "math_params": null,
+ "additional_params": null
}
```
-### `Trade` struct - This helper struct is used for swap operations
+### Fee Params
-```
-struct Trade {
- /// The number of tokens to be sent by the user to the Vault
- pub amount_in: Uint128,
- /// The number of tokens to be received by the user from the Vault
- pub amount_out: Uint128,
- /// The spread associated with the swap tx
- pub spread: Uint128,
+Returns the stored fee parameters for the pool type
+
+#### Request
+
+```json
+{
+ "fee_params": {}
}
```
-### `AfterJoinResponse` struct - Helper struct for [`QueryMsg::OnJoinPool`]
+#### Response
-```
-struct AfterJoinResponse {
- // Is a sorted list consisting of amount of info of tokens which will be provided by the user to the Vault as liquidity
- pub provided_assets: Vec,
- // Is the amount of LP tokens to be minted
- pub new_shares: Uint128,
- // Is the response type :: Success or Failure
- pub response: ResponseType,
- // Is the fee to be charged
- pub fee: Option,
+```json
+{
+ "total_fee_bps": "1000"
}
```
-### `AfterExitResponse` struct - Helper struct for [`QueryMsg::OnExitPool`]
+### Pool ID
-```
-struct AfterExitResponse {
- /// Assets which will be transferred to the recipient against tokens being burnt
- pub assets_out: Vec,
- /// Number of LP tokens to burn
- pub burn_shares: Uint128,
- /// Operation will be a `Success` or `Failure`
- pub response: ResponseType,
- /// Fee to be charged
- pub fee: Option,
+Returns the pool ID of the pool
+
+#### Request
+
+```json
+{
+ "pool_id": {}
}
```
-### `SwapResponse` struct - Helper struct for [`QueryMsg::OnSwap`]
+#### Response
+```json
+{
+ "pool_id": "1"
+}
```
-struct SwapResponse {
- /// Is of type [`Trade`] which contains all params related with the trade
- pub trade_params: Trade,
- /// Operation will be a `Success` or `Failure`
- pub response: ResponseType,
- /// Fee to be charged
- pub fee: Option,
+
+### On Join Pool
+
+Takes either the amounts of assets to be deposited or the amount of LP tokens to be minted for a join operation and returns the following:
+- The amount of assets to be deposited
+- Amount of LP tokens to be minted based on the current pool state
+- Fee to be charged. It mostly applies in a non balanced pools. The calculations is based on the Curve's stableswap invariant
+
+**Additional note**: This request never fails. If the join operation is not possible, the response will contain the reason for failure in the `response` field.
+
+#### Request
+
+```json
+{
+ "on_join_pool": {
+ "assets_in": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ }
+ ]
+ }
}
```
-### `CumulativePriceResponse` struct - Helper struct for [`QueryMsg::CumulativePrice`]
+#### Response
+
+```json
+{
+ "provided_assets": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ }
+ ],
+ "new_shares": "1000000000000",
+ "response": {
+ "success": {}
+ },
+ "fee": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000"
+ }
+ ]
+}
+```
+### On Exit Pool
+
+Useful for estimating the amount of assets received after an exit operation. It takes an exit type parameter which can either of the following:
+1. `ExactLpBurn` : User wants to burn a specific amount of LP tokens and receive the assets in return. It returns assets in the same ratio as the pool. This type of withdraw is called balanced withdraw.
+
+2. `ExactAssetsOut`: In this type of withdraw, user specifies the particular type of tokens that the user want to take out of the pool.
+The pool logic estimates the LP token to be burnt based on the current pool state. Since, the assets are returned exactly as specified by the user and not according to the pool ratio, we call this type of withdraw as imbalanced withdraw.
+
+Currently, we have disabled the imbalanced withdraws for the stableswap pool for pool stability reasons. It can be enabled using the chain governance.
+
+**Additional note**: This request never fails. If the exit operation is not possible, the response will contain the reason for failure in the `response` field.
+
+#### Request
+
+```json
+{
+ "on_exit_pool": {
+ "exit_type": {
+ "exact_assets_out": {
+ "assets_out": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ }
+ ]
+ }
+ }
+ }
+}
```
-struct CumulativePriceResponse {
- pub exchange_info: AssetExchangeRate,
- pub total_share: Uint128,
+
+#### Response
+
+```json
+{
+ "assets_out": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "100000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "amount": "100000000"
+ }
+ ],
+ "burn_shares": "10000000",
+ "response": {
+ "success": {}
+ },
+ "fee": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000"
+ }
+ ]
}
```
-### `CumulativePricesResponse` struct - Helper struct for [`QueryMsg::CumulativePrices`]
+### On Swap
+
+Allows for a swap simulation. Takes following parameters and returns the expected swap result based on the current pool state.
+
+- `offer_asset`: The asset to be sent by the user
+
+- `ask_asset`: The asset to be received by the user
+
+- `swap_type`: It has 2 types, `GiveIn` or `GiveOut` to specify the context of the amount parameter. If `GiveIn`, the amount is the amount of `offer_asset` to be sent by the user. If `GiveOut`, the amount is the amount of `ask_asset` to be received by the user.
+
+- `amount`: The amount of `offer_asset` or `ask_asset` depending on the `swap_type` parameter
+
+- `max_spread`: The max spread between the price of the asset and the price of the pool. If the spread is greater than this value, the swap will fail. For the purpose of stableswap pool, the exchange rate for the spread calculation is 1 and for metastable pools, it is the current redemption rate of the asset in the LST protocol. For example, if the `max_spread` is set at 0.02, the swap will fail if pool is not able to provide a rate better than 0.98 for the current swap.
+- `belief_price`: The price at which the user wants to swap. If the pool is able to provide a better rate than this, the swap will succeed. For example, if the `belief_price` is set at 1.1, the swap will succeed if the pool is able to provide a rate better than 1.1 for the current swap.
+
+
+The expected swap response has the following fields. It contains the following fields:
+
+- `trade` : Trade related infromaton, it has following fields
+ - `amount_in` : The amount of `offer_asset` to be sent by the user
+ - `amount_out` : The amount of `ask_asset` to be received by the user
+ - `spread` : The spread associated with the swap tx.
+
+- `response` : It has 2 types, `Success` or `Failure` to specify the context of the swap result. If `Success`, the swap will succeed. If `Failure`, the swap will fail.
+
+- `fee` : The fee to be charged. The calculations is based on the Curve's stableswap invariant.
+
+#### Request
+
+```json
+{
+ "on_swap": {
+ "offer_asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ask_asset": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "swap_type": {
+ "give_in": {}
+ },
+ "amount": "100000000",
+ "max_spread": "0.02",
+ "belief_price": "0.8"
+ }
+}
```
-struct CumulativePricesResponse {
- pub exchange_info: Vec,
- pub total_share: Uint128,
+
+#### Response
+
+```json
+{
+ "trade": {
+ "amount_in": "100000000",
+ "amount_out": "79997000",
+ "spread": "0.01"
+ },
+ "response": {
+ "success": {}
+ },
+ "fee": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "300000"
+ }
+ ]
}
```
-## Build schema and run unit-tests
+### Cumulative Price
+
+Returns the cumulative price of the asset in the pool. This is for the TWAP calculation for any external party to use the TWAP price of the asset in the Dexter pool.
+
+Culumative price can be calculated across two block times and the TWAP price can be calculated using the following formula:
+```rust
+TWAP = (cumulative_price_2 - cumulative_price_1) / (block_time_2 - block_time_1)
```
-cargo schema
-cargo test
+
+#### Request
+
+```json
+{
+ "cumulative_price": {
+ "offer_asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ask_asset": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ }
+ }
+}
```
-## License
+#### Response
+
+```json
+{
+ "exchange_info": [{
+ "offer_info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ask_info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "rate": "0.8",
+ }],
+ "total_share": "1000000000000",
+}
+```
+
+**Note**: `total_share` is the total amount of LP tokens in the pool at the current block time.
+
-TBD
+### Cumulative Prices
+
+Returns the cumulative prices of all the assets in the pool for all possible exchange pairs. This is for calculation for any external party to use the TWAP price of the asset in the Dexter pool across two block times.
+
+#### Request
+
+```json
+{
+ "cumulative_prices": {}
+}
+```
+
+#### Response
+
+```json
+{
+ "exchange_info": [{
+ "offer_info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ask_info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "rate": "0.8",
+ }],
+ "total_share": "1000000000000",
+}
+```
diff --git a/contracts/pools/weighted_pool/README.md b/contracts/pools/weighted_pool/README.md
index b3028e44..85306d40 100644
--- a/contracts/pools/weighted_pool/README.md
+++ b/contracts/pools/weighted_pool/README.md
@@ -1,185 +1,468 @@
-# Dexter Protocol :: Weighted Pool
+# Dexter: Weighted Pool
-Dexter's Weighted Pool is based on a particular N-dimensional surface which defines a cost function for the exchange of
-any pair of tokens held in a Pool which was introduced by Balancer. Dexter's weighted pool accepts maximum 9 tokens and the weights cannot be updated once the pool has been initialized.
+Dexter implements a Balancer inspired Weighted pool which support upto 8 assets in the pool and implements compute calculations on liquidity provision / withdrawal and swaps.
-Unlike pools in other DeFi protocols that only provide 50/50 weightings, Dexter's Weighted Pools enable users to build pools with different token counts and weightings, such as pools with 80/20 or 60/20/20 weightings.
+Dexter support any custom weighted configuration like 50:50, 60:40, 70:30, 10:10:20:60 or any other combination of weights. The weights cannot be updated once the pool has been initialized.
+
+Dexter's contract architecture is unique in that it separates the ownership of the assets in the pool in the Vault contract. Pool contracts are only responsible for the math computes which dictate number of tokens to be transferred during swaps / liquidity provisioning events, and do not handle the token transfers themselves.
+
+Dexter's Vault queries the Pool contracts to compute how many tokens to transfer and processes those transfers itself.
+
+This separation simplifies pool contracts, since they no longer need to actively manage their assets; pools only need to calculate amounts for swaps, joins, and exits. New pool types, can be easily added which only implement the math computes and do not need to worry about the token transfer logic.
Note - Dexter's weighted pool accepts an `exit_fee` parameter during pool initialization. The `exit_fee` is the % fee charged to the user when liquidity is withdrawn from the pool. 100% of the exit fee charged is distributed among the LPs of the Pool. `exit_fee` cannot be more than 1%.
+Currently, Dexter protocol does not use this parameter and would likely not use it in the future.
+
## Contract State
-| Message | Description |
-| ------------ | -------------------------------------------------------------------------------- |
-| `CONFIG` | Stores pool contract's core Configuration parameters in a [`Config`] struct |
-| `TWAPINFO` | Stores Twap prices for the tokens supported by the pool in a [`Twap`] struct |
-| `MATHCONFIG` | Stores `exit_fee` and `greatest_precision` configuration parameters for the pool |
-| `PRECISIONS` | Stores decimal precision for each asset supported by the pool |
-| `WEIGHTS` | Stores normalized weight for each asset supported by the pool |
+| Message | Description |
+| ------------ | ----------------------------------------------------------------------------------------------- |
+| `CONFIG` | Stores pool contract's core Configuration parameters in a [`Config`]() struct. This is the base config that is same for all pool types. |
+| `TWAPINFO` | Stores Twap prices for the tokens supported by the pool in a [`Twap`]() struct |
+| `MATHCONFIG` | Stores custom global configuration parameters like `exit_fee` and greatest precision which aids in certain calculations |
+| `WEIGHTS` | Stores weights of all assets in the pool |
+| `PRECISIONS` | Stores precision of all assets in the pool. For CW20 tokens, it is fetched using the contract, and for native assets, it must be specified during pool creation |
+
+State related information can be found [here](../contracts/pools/weighted_pool/src/state.rs)
---
-- **Separating Token Accounting and Pool Logic**
- The Dexter Pools are responsible only for the math computes which dictate number of tokens to be transferred during swaps / liquidity provisioning events, and do not handle the token transfers themselves. Dexter's Vault queries the Pool contracts to compute how many tokens to transfer and processes those transfers itself.
+## Supported Execute Messages
- This separation simplifies pool contracts, since they no longer need to actively manage their assets; pools only need to calculate amounts for swaps, joins, and exits.
- Anyone who comes up with a novel idea for a trading system can make a custom pool and have it added to Dexter's PoolType Registery via approval from the Dexter DAO instead of needing to build their own Decentralized Exchange.
+### Update Config
-## Supported Execute Messages
+Currently the Dexter weighted pool doesn't have any configurable parameters. This message is a placeholder for future updates (if any).
-| Message | Description |
-| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
-| `ExecuteMsg::UpdateConfig` | Executable only by Dexter Vault's owner. Not supported by the Weighted pool |
-| `ExecuteMsg::UpdateLiquidity` | Executable only by Dexter Vault. Updates locally stored asset balances state in `config.assets` for the pool and updates the TWAP. |
-## Supported Query Messages
+### Update Liquidity
-| Message | Description |
-| -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `QueryMsg::Config()` | Returns the stored Vault Configuration settings in custom [`ConfigResponse`] struct, including `exit_fee` and normalized token weights |
-| `QueryMsg::FeeParams()` | Returns the provided [`PoolType`]'s Configuration settings in custom [`FeeResponse`] struct |
-| `QueryMsg::PoolId()` | Returns Pool ID which is of type [`Uint128`] |
-| `QueryMsg::OnJoinPool( assets_in, mint_amount , slippage_tolerance )` | Returns [`AfterJoinResponse`] type which contains - `return_assets` info, number of LP shares to be minted, the `response` of type [`ResponseType`] and `fee` of type [`Option`] which is the fee to be charged. |
-| `QueryMsg::OnExitPool( assets_out, burn_amount )` | Returns [`AfterExitResponse`] type which contains - `assets_out` info, number of LP shares to be burnt, the `response` of type [`ResponseType`] and `fee` of type [`Option`] which is the fee to be charged. |
-| `QueryMsg::OnSwap( swap_type, offer_asset, ask_asset, amount, max_spread, belief_price )` | Returns [`SwapResponse`] type which contains - `trade_params` info, the `response` of type [`ResponseType`] and `fee` of type [`Option`] which is the fee to be charged. |
-| `QueryMsg::CumulativePrice( swap_type, offer_asset, ask_asset, amount, max_spread, belief_price )` | Returns information about the cumulative price of the asset in a [`CumulativePriceResponse`] object. |
-| `QueryMsg::CumulativePrices( )` | Returns information about the cumulative prices in a [`CumulativePricesResponse`] object. |
+Executable only by Dexter Vault. Updates locally stored asset balances state in `config.assets` for the pool and updates the TWAP.
-## Enums & Structs
-### `MathConfig` struct - This struct describes the main math configuration of the weighted-pool.
+#### Request
-```
-struct MathConfig {
- pub exit_fee: Option,
- /// The greatest precision of assets in the pool
- pub greatest_precision: u8,
+```json
+{
+ "update_liquidity": {
+ "assets": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ },
+ "amount": "900000000000"
+ }
+ ]
+ }
}
```
-### `WeightedAsset` struct - This struct describes a asset (native or CW20) and its normalized weight
+### Update Fee
-```
-struct WeightedAsset {
- /// Information about an asset stored in a [`Asset`] struct
- pub asset: Asset,
- /// The weight of the asset
- pub weight: Decimal,
+Executable only by the Dexter Vault where it is triggerd by the Vault owner. Updates the fee for this particular pool. The fee is specified in basis points.
+
+#### Request
+
+```json
+{
+ "update_fee": {
+ "total_fee_bps": "1000"
+ }
}
```
-### `ResponseType` enum - This enum is used to describe if the math computations (joins/exits/swaps) will be successful or not
+## Supported Queries
+
+### Config
+Returns the stored pool configuration
+
+#### Request
+
+```json
+{
+ "config": {}
+}
```
-enum ResponseType {
- Success {},
- Failure (String),
+
+#### Response
+
+```json
+{
+ "pool_id": "1",
+ "lp_token_addr": "persistence1...",
+ "vault_addr": "persistence1...",
+ "assets": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ },
+ "amount": "1000000000000"
+ }
+ ],
+ "pool_type": {
+ "weighted": {}
+ },
+ "fee_info": {
+ "total_fee_bps": "1000"
+ },
+ "block_time_last": "1629820800",
+ "math_params": null,
+ "additional_params": null
}
```
-### `Config` struct - This struct describes the main control config of pool.
+### Fee Params
-```
-struct Config {
- /// ID of contract which is allowed to create pools of this type
- pub pool_id: Uint128,
- /// The address of the LP token associated with this pool
- pub lp_token_addr: Option,
- /// the vault contract address
- pub vault_addr: Addr,
- /// Assets supported by the pool
- pub assets: Vec,
- /// The pools type (provided in a [`PoolType`])
- pub pool_type: PoolType,
- /// The Fee details of the pool
- pub fee_info: FeeStructs,
- /// The block time when pool liquidity was last updated
- pub block_time_last: u64,
+Returns the stored fee parameters for the pool type
+
+#### Request
+
+```json
+{
+ "fee_params": {}
}
```
-### `Trade` struct - This helper struct is used for swap operations
+#### Response
-```
-struct Trade {
- /// The number of tokens to be sent by the user to the Vault
- pub amount_in: Uint128,
- /// The number of tokens to be received by the user from the Vault
- pub amount_out: Uint128,
- /// The spread associated with the swap tx
- pub spread: Uint128,
+```json
+{
+ "total_fee_bps": "1000"
}
```
-### `AfterJoinResponse` struct - Helper struct for [`QueryMsg::OnJoinPool`]
+### Pool ID
-```
-struct AfterJoinResponse {
- // Is a sorted list consisting of amount of info of tokens which will be provided by the user to the Vault as liquidity
- pub provided_assets: Vec,
- // Is the amount of LP tokens to be minted
- pub new_shares: Uint128,
- // Is the response type :: Success or Failure
- pub response: ResponseType,
- // Is the fee to be charged
- pub fee: Option,
+Returns the pool ID of the pool
+
+#### Request
+
+```json
+{
+ "pool_id": {}
}
```
-### `AfterExitResponse` struct - Helper struct for [`QueryMsg::OnExitPool`]
+#### Response
-```
-struct AfterExitResponse {
- /// Assets which will be transferred to the recipient against tokens being burnt
- pub assets_out: Vec,
- /// Number of LP tokens to burn
- pub burn_shares: Uint128,
- /// Operation will be a `Success` or `Failure`
- pub response: ResponseType,
- /// Fee to be charged
- pub fee: Option,
+```json
+{
+ "pool_id": "1"
}
```
-### `SwapResponse` struct - Helper struct for [`QueryMsg::OnSwap`]
-
+### On Join Pool
+
+Takes either the amounts of assets to be deposited or the amount of LP tokens to be minted for a join operation and returns the following:
+- The amount of assets to be deposited
+- Amount of LP tokens to be minted based on the current pool state
+- Fee to be charged. It mostly applies when liquidity is being added in a ratio other than the pool ratio since it is equivalent to a swap and add in that scenario. The calculations is based on the Balancer's weighted pool calculations.
+
+**Additional note**: This request never fails. If the join operation is not possible, the response will contain the reason for failure in the `response` field.
+
+#### Request
+
+```json
+{
+ "on_join_pool": {
+ "assets_in": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ },
+ "amount": "900000000000"
+ }
+ ]
+ }
+}
```
-struct SwapResponse {
- /// Is of type [`Trade`] which contains all params related with the trade
- pub trade_params: Trade,
- /// Operation will be a `Success` or `Failure`
- pub response: ResponseType,
- /// Fee to be charged
- pub fee: Option,
+
+#### Response
+
+```json
+{
+ "provided_assets": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ },
+ "amount": "900000000000"
+ }
+ ],
+ "new_shares": "1000000000000",
+ "response": {
+ "success": {}
+ },
+ "fee": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000"
+ }
+ ]
}
```
-### `CumulativePriceResponse` struct - Helper struct for [`QueryMsg::CumulativePrice`]
+### On Exit Pool
+
+Useful for estimating the amount of assets received after an exit operation. It takes an exit type parameter which can either of the following:
+1. `ExactLpBurn` : User wants to burn a specific amount of LP tokens and receive the assets in return. It returns assets in the same ratio as the pool. This type of withdraw is called balanced withdraw.
+
+2. `ExactAssetsOut`: In this type of withdraw, user specifies the particular type of tokens that the user want to take out of the pool.
+The pool logic estimates the LP token to be burnt based on the current pool state. Since, the assets are returned exactly as specified by the user and not according to the pool ratio, we call this type of withdraw as imbalanced withdraw.
+
+This type of exit is NOT SUPPORTED for the weighted pool.
+
+**Additional note**: This request never fails. If the exit operation is not possible, the response will contain the reason for failure in the `response` field.
+
+#### Request
+
+```json
+{
+ "on_exit_pool": {
+ "exit_type": {
+ "exact_lp_burn": "10000000"
+ }
+ }
+}
```
-struct CumulativePriceResponse {
- pub exchange_info: AssetExchangeRate,
- pub total_share: Uint128,
+
+#### Response
+
+```json
+{
+ "assets_out": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "1000000000"
+ },
+ {
+ "info": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ },
+ "amount": "900000000"
+ }
+ ],
+ "burn_shares": "10000000",
+ "response": {
+ "success": {}
+ },
+ "fee": []
}
```
-### `CumulativePricesResponse` struct - Helper struct for [`QueryMsg::CumulativePrices`]
+### On Swap
+
+Allows for a swap simulation. Takes following parameters and returns the expected swap result based on the current pool state.
+
+- `offer_asset`: The asset to be sent by the user
+
+- `ask_asset`: The asset to be received by the user
+
+- `swap_type`: It has 2 types, `GiveIn` or `GiveOut` to specify the context of the amount parameter. If `GiveIn`, the amount is the amount of `offer_asset` to be sent by the user. If `GiveOut`, the amount is the amount of `ask_asset` to be received by the user.
+
+- `amount`: The amount of `offer_asset` or `ask_asset` depending on the `swap_type` parameter
+
+- `max_spread`: The max spread between the price of the asset and the price of the pool. If the spread is greater than this value, the swap will fail.
+
+This parameter is NOT SUPPORTED for the weighted pool since there's no ideal tethered price for the assets in the pool.
+
+- `belief_price`: This parameter is NOT SUPPORTED for the weighted pool.
+
+The expected swap response has the following fields. It contains the following fields:
+
+- `trade` : Trade related infromaton, it has following fields
+ - `amount_in` : The amount of `offer_asset` to be sent by the user
+ - `amount_out` : The amount of `ask_asset` to be received by the user
+ - `spread` : Ignored. Always 0 for weighted pool.
+
+- `response` : It has 2 types, `Success` or `Failure` to specify the context of the swap result. If `Success`, the swap will succeed. If `Failure`, the swap will fail.
+
+- `fee` : The fee to be charged. The calculations is based on the Curve's stableswap invariant.
+
+#### Request
+
+```json
+{
+ "on_swap": {
+ "offer_asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ask_asset": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ },
+ "swap_type": "GiveOut",
+ "amount": "100000000",
+ "max_spread": null,
+ "belief_price": null
+ }
+}
```
-struct CumulativePricesResponse {
- pub exchange_info: Vec,
- pub total_share: Uint128,
+
+#### Response
+
+```json
+{
+ "trade": {
+ "amount_in": "923000000",
+ "amount_out": "100000000",
+ "spread": "0"
+ },
+ "response": {
+ "success": {}
+ },
+ "fee": [
+ {
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "amount": "2769000"
+ }
+ ]
}
```
-## Build schema and run unit-tests
+### Cumulative Price
+Returns the cumulative price of the asset in the pool. This is for the TWAP calculation for any external party to use the TWAP price of the asset in the Dexter pool.
+
+Culumative price can be calculated across two block times and the TWAP price can be calculated using the following formula:
+
+```rust
+TWAP = (cumulative_price_2 - cumulative_price_1) / (block_time_2 - block_time_1)
+```
+
+#### Request
+
+```json
+{
+ "cumulative_price": {
+ "offer_asset": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ask_asset": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ }
+ }
+}
```
-cargo schema
-cargo test
+
+#### Response
+
+```json
+{
+ "exchange_info": [{
+ "offer_info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ask_info": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ },
+ "rate": "0.12",
+ }],
+ "total_share": "1000000000000",
+}
```
-## License
+**Note**: `total_share` is the total amount of LP tokens in the pool at the current block time.
+
-TBD
+### Cumulative Prices
+
+Returns the cumulative prices of all the assets in the pool for all possible exchange pairs. This is for calculation for any external party to use the TWAP price of the asset in the Dexter pool across two block times.
+
+#### Request
+
+```json
+{
+ "cumulative_prices": {}
+}
+```
+
+#### Response
+
+```json
+{
+ "exchange_info": [{
+ "offer_info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "ask_info": {
+ "native_token": {
+ "denom": "stk/uatom"
+ }
+ },
+ "rate": "0.12",
+ }],
+ "total_share": "1000000000000",
+}
+```
diff --git a/contracts/vault/README.md b/contracts/vault/README.md
index cf965f03..57ebb54b 100644
--- a/contracts/vault/README.md
+++ b/contracts/vault/README.md
@@ -1,422 +1,487 @@
-# DEXTER Protocol -::- Vault Contract
+# Dexter - Vault contract
-The Vault is the core of Dexter; it is a smart contract that holds and manages all tokens in each Dexter Pool. It is also the portal through which most Dexter operations (swaps/joins/exits) take place.
+Dexter vault contract is the core contract of the Dexter protocol. It handles all protocol liquidity and faciliates pool related operations like:
+- Join Pool
+- Exit Pool
+- Swap tokens using a specific pool
-## **Admin powers -**
+## Roles
-The Dexter’s Vault contract can be assigned an **admin** (multisig or a assembly contract) which has the following powers,
+**Owner**: owner is the admin of the contract. Owner term is used to distinguish it from the Cosmwasm contract-admin. Current owner role has following privileges:
+- Manage the Vault and Pool admin parameters
+- Create a pool
+- Pause the pool swap and join operations in case of an adverse event
-- Admin can call the **UpdateConfig()** function in the Vault contract to update any of the following parameters,
- - **Fee_collector** - Address to which the fee collected by the vault is transferred
- - **Generator_address** - Address of dexter generator contract, which supports bonding LP tokens for rewards. It can be set only once and cannot be changed.
- - This is used to facilitate bonding the LP tokens with the generator in the same tx in which the user provides liquidity to the pool
- - **Lp_token_code_id** - Code ID of the LP token contract which is used for initializing LP tokens for pools.
-- Admin can call the **UpdatePoolConfig()** function via which it can update the following parameters for that pool_type,
- - **Disabling / Enabling new pool instances creation: Address in-charge of a particular pool type can disable or enable initialization for new instances**
- - **Disable / Enable support with dexter generator:** Address in-charge of a particular pool type can disable or enable support by dexter generator, implying pools of that type will no longer be able to be supported by the generator for incentives
- - **Update fee_info which will be applicable for new pool instances:** Address in-charge of a particular pool type can update the fee configuration to be used for new pool instances
-- **Add a new pool type -** Only admin can add a new pool type to dexter’s Vault via the **AddToRegistry()** function.
-- All the dexter pools are assigned the dexter’s admin as their admin when being initialized, implying they can be upgraded by the dexter admin.
+With the rollout of Chain governance based contol on Dexter, Dexter Governance admin assumes this role therefore all the above actions can be triggered by correct proposals on the Persistence chain.
-## **Functional Flows**
+**Manager**: Manager is a subordinate role to the contract owner to manage day-to-day functions. It overall holds less control over the protocol and it primarily exists to aid any actions that due to involvement of Governance, the owner might be slow to act on. It currently has following privileges:
+- Create a pool (if allowed by the owner)
+- Pause the pool swap and join operations
-### 1. **JoinPool - Execution Function**
+This role is currently owned by the [Dexter team multisig]()
-- Vault contract’s **JoinPool** fn is the only entry point for providing liquidity to any of the dexter’s supported pools.
-- If the pool is live on dexter generator for additional rewards, the user can choose to stake the newly minted LP tokens with the generator by providing **auto_stake = True**
-- Vault contract queries the specific pool contract to which liquidity is to be provided to get the following information,
- - Sorted list of assets to be transferred from the user to the Vault as Pool Liquidity. This is provided by param **provided_assets**
- - The number of LP tokens to be minted to the user / recipient. This is provided by param **new_shares**
- - The response type :: Success or Failure. This is provided by param **response**
- - Optional List assets (info and amounts) to be charged as fees to the user. This is provided by param **fee**
-- Only Stable-5-Pool and Weighted Pool charge fee when providing liquidity in an imbalanced manner. XYK and stableswap pools do not charge any fee
-- **Fee Calculations -**
+**User**: User is an individual that interacts with the Dexter Protocol to join a pool, exit from a pool or to perform a swap.
-- We assume that the asset balances provided in **provided_assets** params are the total number of tokens to be transferred to the Vault and the protocol and developer fee is yet to be deducted from this.
-- For the number of LP tokens to be minted, we assume that they are being minted proportional to **tokens_transferred_to_vault - total_fee** while we actually provide **tokens_transferred_to_vault - total_fee + lp_fee** as liquidity to the pool
-### 2. **ExitPool - Execution Function**
+## Supported state transition functions
-- Vault contract’s **ExitPool** fn is the only entry point for removing liquidity from any of the dexter’s supported pools.
-- Vault contract queries the specific pool contract from which liquidity is to be removed to get the following information
- - Sorted list of assets to be transferred to the user from the Vault. This is provided by param **assets_out**
- - The number of LP tokens to be burnt by the user. This is provided by param **burn_shares**
- - The response type :: Success or Failure. This is provided by param **response**
- - Optional List assets (info and amounts) to be charged. This is provided by param **fee**
-- Only Stable-5-Pool charges fee when withdrawing liquidity in an imbalanced manner.
-- Weighted Pool has an exit fee param and the fee is charged only in LP tokens and is not accrued towards anything.
-- XYK and stableswap pools do not charge any fee when withdrawing liquidity
+### Owner and manager executable
-**Fee Calculations -**
+#### 1. _**Update Pause Info**_
-- We assume that the asset balances provided in **assets_out** params are the total number of tokens to be transferred to the User and the protocol and developer fee are additional amounts to be transferred as fees
-- For the number of LP tokens to be burnt, we assume that they are burnt proportional to **assets_out + total_fee**
+Can be used to pause a pool's swap, join and imbalanced-withdraw operations. Normal withdraw operations are not affected by always enabled and cannot be paused by any means.
+Pause can happen on a Pool Type or a Pool ID level. If a pool type is paused, all pools of that type are paused. If a pool ID is paused, only that pool is paused.
-### 3. **Swap - Execution Function**
+**Request Example:**
-- Vault contract’s **Swap** fn is the only entry point for swapping tokens via any of the dexter’s supported pools.
-- Vault contract queries the specific pool contract from which liquidity is to be routed to get the following information
- - Number of tokens to be transferred to the user from the Vault and from Vault to the user, this is returned in **trade_params**
- - The response type :: Success or Failure. This is provided by param **response**
- - Optional asset (info and amount) to be charged as fee. This is provided by param **fee**
-
-**Fee Calculations -**
-
-- We assume that the asset out amount provided in **trade_params** are the total number of tokens to be transferred to the User and the protocol and developer fee are additional amounts to be transferred as fees and hence are to be additionally subtracted from the pool’s current liquidity balance
-- Pool Liquidity for the ask_asset is updated as following,
-
-**`new_pool_liquidity = old_pool_liquidity - return_amount - protocol_fee - dev_fee`**
-
-`where,`
-
-`old_pool_liquidity: Pool liquidity for ask asset before the swap`
-
-`new_pool_liquidity: Pool liquidity for ask asset after the swap`
-
-`return_amount: Number of ask tokens transferred to the user`
-
-`protocol_fee: protocol fee amount`
-
-`dev_fee; dev fee amount`
-
-- **Stable-5-Pool** returns the number of ask tokens to be transferred to the user and the fee charged in ask_token.
-- **Weighted Pool** returns the number of ask tokens to be transferred to the user and the fee charged in ask_token.
-- **XYK Pool** returns the number of ask tokens to be transferred to the user and the fee charged in ask_token.
-- **Stableswap Pool** returns the number of ask tokens to be transferred to the user and the fee charged in ask_token.
-
-## Contract State
-
-| Message | Description |
-| -------------------- | -------------------------------------------------------------------------------------------------------------- |
-| `CONFIG` | Stores Vault contract's core Configuration parameters in a [`Config`] struct |
-| `REGISTERY` | Stores configuration data associated with each [`PoolType`] supported by the Vault in a [`PoolConfig`] struct |
-| `ACTIVE_POOLS` | Stores current state of each Pool instance identified by its ID supported by the Vault in a [`PoolInfo`] struc |
-| `OWNERSHIP_PROPOSAL` | Ownership Proposal currently active in the Vault in a [`OwnershipProposal`] struc |
-| `TMP_POOL_INFO` | Temporarily stores the PoolInfo of the Pool which is currently being created in a [`PoolInfo`] struc |
-
----
-
-- **Separating Token Accounting and Pool Logic**
-
- The Dexter's Vault architecture is inspired by the Balancer's Vault and similarly separates the token accounting and management from the pool logic. This separation simplifies pool contracts, since they no longer need to actively manage their assets; pools only need to calculate amounts for swaps, joins, and exits.
- This architecture brings different pool designs under the same umbrella; the Vault is agnostic to pool math and can accommodate any system that satisfies a few requirements. Anyone who comes up with a novel idea for a trading system can make a custom pool plugged directly into Dexter's existing liquidity instead of needing to build their own Decentralized Exchange.
-
-- **Security**
-
- It's crucial to note that the Vault is designed to keep pool balances strictly independent. Maintaining this independence protects from malicious or negligently designed tokens or custom pools from draining funds from any other pools.
-
-## Supported Execute Messages
+```json
+{
+ "update_pause_info": {
+ "update_type": {
+ "pool_id": "1",
+ },
+ "pause_info": {
+ "swap": false,
+ "join": true,
+ "imbalanced_withdraw": true
+ }
+ }
+}
+```
-| Message | Description |
-| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `ExecuteMsg::UpdateConfig` | Executable only by `config.owner`. Facilitates updating `config.fee_collector`, `config.generator_address`, `config.lp_token_code_id` parameters. |
-| `ExecuteMsg::UpdatePoolConfig` | Executable only by `pool_config.fee_info.developer_addr` or `config.owner` if its not set. Facilitates enabling / disabling new pool instances creation (`pool_config.is_disabled`) , and updating Fee (` pool_config.fee_info`) for new pool instances |
-| `ExecuteMsg::AddToRegistery` | Adds a new pool with a new [`PoolType`] Key. |
-| `ExecuteMsg::CreatePoolInstance` | Creates a new pool with the specified parameters in the `asset_infos` variable. |
-| `ExecuteMsg::JoinPool` | Entry point for a user to Join a pool supported by the Vault. User can join by providing the pool id and either the number of assets to be provided or the LP tokens to be minted to the user (as defined by the Pool Contract). |
-| `ExecuteMsg::Swap` | Entry point for a swap tx between offer and ask assets. The swap request details are passed in [`SingleSwapRequest`] Type parameter. |
-| `ExecuteMsg::ProposeNewOwner` | Creates a new request to change ownership. Only owner can execute it. |
-| `ExecuteMsg::DropOwnershipProposal` | ARemoves a request to change ownership. Only owner can execute it |
-| `ExecuteMsg::ClaimOwnership` | New owner claims ownership. Only new proposed owner can execute it |
+#### 2. _**Create Pool Instance**_
-## Supported Query Messages
+Used to create a pool instance. Pools of only the registered pool types can be created. Currently, Dexter supports following pool types:
+- Weighted
+- Stable
-| Message | Description |
-| ---------------------------------------- | ------------------------------------------------------------------------------------------------------ |
-| `QueryMsg::Config()` | Returns the stored Vault Configuration settings in custom [`ConfigResponse`] structure |
-| `QueryMsg::QueryRegistry([`PoolType`])` | Returns the provided [`PoolType`]'s Configuration settings in custom [`PoolConfigResponse`] structure |
-| `QueryMsg::GetPoolById([`Uint128`])` | Returns the current stored state of pool with the provided ID in custom [`PoolInfoResponse`] structure |
-| `QueryMsg::GetPoolByAddress([`String`])` | Returns the current stored state of the Pool in custom [`PoolInfoResponse`] structure |
+Based on the pool type, this function can be configured by the owner to be either be executable by:
+1. Only them
+2. Them and the whitelisted manager address(es)
+3. Anyone
-## Instantiate -::- InstantiateMsg
+In current Dexter configuration, we give this privilege to the manager role as well which is currently the [Dexter team multisig]().
-The instantiation message takes in the token code ID (`lp_token_code_id`) for the token type used by Dexter for instantiating LP tokens against supported pool instances. It also takes in address of the `fee_collector` that collects fees for governance, the `owner` address which owns access to the admin priviledges on the Vault contract, the Generator contract address (`generator_address`) and the initial pool types supported by Dexter Vault which are then stored in the REGISTERY.
+**Request Example:**
```json
{
- "lp_token_code_id": 123,
- "fee_collector": "persistence...",
- "owner": "persistence...",
- "generator_address": "persistence...",
- "pool_configs": "Vec"
+ "create_pool_instance": {
+ "pool_type": {
+ "weight": {}
+ },
+ "asset_infos": [
+ {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ }
+ ],
+ "native_asset_precisions": [
+ {
+ "denom": "stk/uxprt",
+ "precision": 6
+ },
+ {
+ "denom": "uxprt",
+ "precision": 6
+ }
+ ],
+ // Optional: Uses pool type's default config if not provided here
+ "fee_info": null,
+ // base64 encoded params to be passed to the pool contract on instantiation
+ "init_params": ""
+ }
}
```
-## Execute -::- ExecuteMsg
-### `Receive(Cw20ReceiveMsg)` - Receives LP Tokens when removing Liquidity
+### Only owner executable
-### `UpdateConfig` - Updates contract variables & executable only by `config.owner`, namely the code ID of the token implementation used in dexter, the address that receives governance fees and the Generator contract address.
+#### 1. _**Update Config**_
-```json
-{
- "update_config": {
- "lp_token_code_id": 123,
- "fee_collector": "terra...",
- "generator_address": "terra..."
- }
-}
-```
+Used to update the Vault and Pool admin parameters. Currently, it can be used to update the following parameters:
+- LP Token Code ID. Ideally not used after the initial deployment.
+- Pool creation fee
+- Fee collector address
+- Auto stake implementation address i.e. the address of the contract that implements the auto stake interface. Currently, this is the [Dexter Multi-staking contract]()
+- Pause Info on protocol level i.e. pause all pools
-### `UpdatePoolConfig` - Executable only by `pool_config.fee_info.developer_addr` or `config.owner` if its not set. Facilitates enabling / disabling new pool instances creation , and updating Fee for new pool instances
+Example request
```json
{
- "update_pool_config": {
- "pool_type": "PoolType",
- "is_disabled": "Option",
- "new_fee_info": "Option"
+ "update_config": {
+ "pool_creation_fee": "disabled",
+ "paused": {
+ "swap": false,
+ "join": true,
+ "imbalanced_withdraw": true
+ }
}
}
```
-### `AddToRegistery` - Executable only by `config.owner`. Adds a new pool with a new [`PoolType`] Key.
+#### 2. _**Add Address to Whitelist**_
+
+Add an address to the manager whitelist.
+Example request
```json
{
- "add_to_registery": {
- "new_pool_config": "PoolConfig"
+ "add_address_to_whitelist": {
+ "address": "persistence1..."
}
}
```
-### `CreatePoolInstance` - Creates a new pool with the specified parameters in the `asset_infos` variable.
+#### 3. _**Remove Address from Whitelist**_
+Remove an address from the manager whitelist.
+
+Example request
```json
{
- "CreatePoolInstance": {
- "pool_type": "PoolType",
- "asset_infos": "Vec",
- "lp_token_name": "Option",
- "lp_token_symbol": "Option",
- "init_params": "Option"
+ "remove_address_from_whitelist": {
+ "address": "persistence1..."
}
}
```
-### `JoinPool` - Entry point for a user to Join a pool supported by the Vault. User needs to approve Vault contract for allowance on the CW20 tokens before calling the JoinPool Function
+#### 4. _**Update Pool Type config**_
+
+Update the pool type config. Currently, it can be used to update the following parameters:
+-**Instantiation config**: Allow the specific pool type to instantiated by anyone or only the owner or the owner and the whitelisted manager address(es) or None.
+-**Fee Info**: Update the fee info for the specific pool type. This fee info is used when a pool of this type is created. It can be updated later on the pool instance level as well.
+-**Paused**: Updated pause config for the pools of this type.
+Example request
```json
{
- "join_pool": {
- "pool_id": "Uint128",
- "recipient": "Option",
- "assets": " Option>",
- "lp_to_mint": "Option",
- "slippage_tolerance": "Option",
- "auto_stake": "Option"
+ "update_pool_type_config": {
+ "pool_type": {
+ "weighted": {}
+ },
+ "allow_instantiation": "OnlyWhitelistedAddresses",
+ "new_fee_info": null,
+ "paused": null
}
}
```
-### `Swap` - Entry point for a swap tx between offer and ask assets. User needs to approve Vault contract for allowance on the CW20 tokens before calling the Swap Function
+#### 5. _**Update Pool Instance Config**_
+Update the pool instance config. Currently, it can be used to update the following parameters:
+-**Fee Info**: Update the fee info for the specific pool instance. This fee info is used when a pool of this type is created. It can be updated later on the pool instance level as well.
+-**Paused**: Updated pause config for the specific pool instance.
+
+Example request
```json
{
- "swap": {
- "swap_request": "SingleSwapRequest",
- "recipient": "Option"
+ "update_pool_instance_config": {
+ "pool_id": "1",
+ "fee_info": {
+ "total_fee_bps": 50,
+ "protocol_fee_percent": 30
+ },
+ "paused": null
}
}
```
+#### 6. _**Propose new owner**_
-### `ProposeNewOwner` - Entry point for a swap tx between offer and ask assets.
+Propose a new owner for the contract. This is a two step process. First, the current owner proposes a new owner and then the new owner accepts the proposal. This is done to prevent a situation where the current owner proposes a new owner and then transfers the ownership to someone else without that address (person / entity) having the means to act as a new owner.
+Example request
```json
{
"propose_new_owner": {
- "owner": "String",
- "expires_in": "u64"
+ "new_owner": "persistence1...",
+ "expires_in": "1000"
}
}
```
-### `DropOwnershipProposal` - Entry point for a swap tx between offer and ask assets.
+#### 7. _**Drop ownership proposal**_
+
+Drop the ownership proposal if needed ideally to correct the course of action.
+
+Example request
```json
{
"drop_ownership_proposal": {}
}
```
-### `ClaimOwnership` - Entry point for a swap tx between offer and ask assets.
+### User executable
-```json
-{
- "claim_ownership": {}
-}
-```
+#### 1. _**Join Pool**_
-## Execute -::- Cw20HookMsg
+Join a pool. This can be done by sending the native tokens to the vault contract, or by allowing the CW20 tokens to be spent by the vault contract if they are a part of a pool.
-### `ExitPool` - Withdrawing liquidity from the pool identified by `pool_id`
+A user can specify following parameters:
+-**Pool ID**: ID of the pool to join
+-**Recipient**: Address to receive the LP tokens. Can be left empty to receive the LP tokens on the sender address.
+-**Assets**: Assets to join the pool with. This can be a mix of CW20 tokens and native tokens. It can also not be all the assets of the pool i.e. an imbalanced add. The specifics on how many LP tokens are minted is dependent on the pool type and specific join mechanism.
+-**Slippage Tolerance (min_lp_to_receive)**: Slippage tolerance for the join operation. This is used to calculate the maximum amount of LP tokens that can be minted for the given assets. If the slippage tolerance is not met, the join operation fails. Can be left empty for no slippage tolerance.
+-**Auto stake**: If the LP tokens should be auto staked or not. Requires the auto stake implementation to be set on the vault contract.
+Example request
```json
{
- "exit_pool": {
- "pool_id": "Uint128",
- "recipient": "Option",
- "assets": "Option>",
- "burn_amount": "Option"
+ "join_pool": {
+ "pool_id": "1",
+ "assets": [
+ {
+ "amount": "1000000",
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ }
+ },
+ {
+ "amount": "1000000",
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ }
+ }
+ ],
+ "min_lp_to_receive": null,
+ "auto_stake": true,
+ "recipient": null
}
}
```
-## Query -::- QueryMsg
+#### 2. _**Swap**_
+
+Swap assets using a pool. This can be done by sending the native tokens to the vault contract, or by allowing the CW20 tokens to be spent by the vault contract if they are a part of a pool.
-### `Config` -Config returns controls settings that specified in custom [`ConfigResponse`] structure
+Following parameters can be specified:
+-**Swap Request**: Swap request to be executed. Refer to the [swap request](#swap-request) section for more details.
+-**Recipient**: Address to receive the swapped assets. Can be left empty to receive the swapped assets on the sender address.
+-**Slippage Tolerance (min_receive)**: Slippage tolerance for the `GiveIn` swap operation. This is to control minimum expected amount of assets to be received. If the slippage tolerance is not met, the swap operation fails. Can be left empty for no slippage tolerance.
+-**Slippage Tolerance (max spend)**: Slippage tolerance for the `GiveOut` swap operation. This is to control maximum expected amount of assets to be spent. If the slippage tolerance is not met, the swap operation fails. Can be left empty for no slippage tolerance. Rest of the assets are returned to the sender address.
+Example request
```json
{
- "config": {}
+ "swap": {
+ "swap_request": {
+ "pool_id": "1",
+ "asset_in": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ },
+ "asset_out": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ },
+ "swap_type": {
+ "GiveIn": {}
+ },
+ "amount": "1000000",
+ "max_spread": null,
+ "belief_price": null
+ },
+ "min_receive": null,
+ "max_spend": null,
+ "recipient": null
+ }
}
```
-### `QueryRigistery` -Config returns controls settings that specified in custom [`ConfigResponse`] structure
+#### 3. _**Exit Pool**_
+
+Exiting a pool happens via a CW20 Send hook msg to transfer ownership of the LP tokens to the vault contract. The vault contract then burns the required LP tokens and sends the assets to the recipient address. If there are any extra LP tokens left, based on the exit type, they are sent back to the sender address.
+Parameters for this operation are:
+-**Pool ID**: ID of the pool to exit
+-**Recipient**: Address to receive the swapped assets. Can be left empty to receive the swapped assets on the sender address.
+-**Exit Type**: Type of exit to perform. Can be one of the following:
+ -**Exact LP Burn**: Burn the exact amount of LP tokens and send the assets to the recipient address. A user can specify the minimum amount of assets to receive as well to control the slippage tolerance. The assets received are in the pool ratio.
+ -**Exact Assets Out**: Burn the exact amount of assets specified and deduct the corresponding representative LP tokens from the user. Can be used for an imbalanced withdraw. Slippage tolerance is controlled by the user by specifying the maximum amount of LP tokens to burn. Rest of the LP tokens are sent back to the sender address.
+
+Example request
```json
{
- "query_registery": {
- "pool_type": "PoolType"
+ "exit_pool": {
+ "pool_id": "1",
+ "exit_type": {
+ "ExactLPBurn": {
+ "lp_to_burn": "1000000",
+ "min_asset_amounts": [
+ {
+ "amount": "1000000",
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ }
+ },
+ {
+ "amount": "1000000",
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "recipient": null
}
}
```
-### `GetPoolById` -Config returns controls settings that specified in custom [`ConfigResponse`] structure
+## Supported Queries
+
+### 1. _**Config**_
+
+Get the current config of the vault contract. This includes the following parameters:
+- **LP Token Code ID**: Code ID of the LP token contract. This is used to create new LP tokens for new pools. Ideally not updated post initial deployment
+- **Fee Collector Address**: Address of the contract which collects fees. Currently, the Dexter keeper contract
+- **Pool Creation Fee**: Fee in the specified denom for creating a new pool. This is used to prevent spamming of the pool creation feature.
+- **Auto-stake implementation**: Address of the contract which implements the auto-stake feature. Currently, the Dexter multistaking contract
+- **Whitelisted managers**: List of addresses which currently have the manager role
+- **Global Pause Info**: Pause configuration for the protocol. This is used to pause/unpause specific operations for the entire protocol. It overrides the pause configuration on the pool type and pool level i.e. if some operation is paused on a protocol level, it cannot be unpaused on a pool type or pool level.
+
+### 2. _**Query Registry**_
+
+Get pool type config present in the registry for a pool type that's registered on the vault contract.
+
+#### Request
```json
{
- "get_pool_by_id": {
- "pool_id": "Uint128"
+ "query_registry": {
+ "pool_type": {
+ "weighted": {}
+ }
}
}
```
-### `GetPoolByAddress` -Config returns controls settings that specified in custom [`ConfigResponse`] structure
+#### Response
```json
{
- "get_pool_by_address": {
- "pool_addr": "String"
+ "code_id": "3",
+ "pool_type": {
+ "weighted": {}
+ },
+ "default_fee_info": {
+ "total_fee_bps": 30,
+ "protocol_fee_percent": 30
+ },
+ "allow_instantiation": "OnlyWhitelistedAddresses",
+ "paused": {
+ "swap": false,
+ "join": false,
+ "imbalanced_withdraw": true
}
}
```
-## Enums & Structs
+### 3. _**Get Pool by ID**_
-### `PoolType` enum - This enum describes the key for the different Pool types supported by Dexter
+Get the pool config for a pool ID.
-```
-enum PoolType {
- Xyk {},
- Stable2Pool {},
- Stable3Pool {},
- Weighted {},
- Custom(String),
-}
-```
+#### Request
-- New Pool Types can be added via using the PoolType::Custom(String) type.
-
-### `SwapType` enum - This enum describes available Swap types.
-
-```
-enum SwapType {
- GiveIn {},
- GiveOut {},
- Custom(String),
+```json
+{
+ "get_pool_by_id": {
+ "pool_id": "1"
+ }
}
```
-- New Pools can support custom swap types based on math compute logic they want to execute
-
-### `FeeInfo` struct - This struct describes the Fee configuration supported by a particular pool type.
+#### Response
-```
-struct FeeInfo {
- swap_fee_dir: SwapType,
- total_fee_bps: u16,
- protocol_fee_percent: u16,
- dev_fee_percent: u16,
- developer_addr: Option,
+```json
+{
+ "pool_id": "1",
+ "pool_type": {
+ "weighted": {}
+ },
+ "pool_addr": "persistence1...",
+ "lp_token_addr": "persistence1...",
+ "fee_info": {
+ "total_fee_bps": 30,
+ "protocol_fee_percent": 30
+ },
+ "assets": [
+ {
+ "amount": "1000000",
+ "info": {
+ "native_token": {
+ "denom": "uxprt"
+ }
+ }
+ },
+ {
+ "amount": "1000000",
+ "info": {
+ "native_token": {
+ "denom": "stk/uxprt"
+ }
+ }
+ }
+ ],
+ "paused": {
+ "swap": false,
+ "join": false,
+ "imbalanced_withdraw": true
+ }
}
+
```
-### `Config` struct - This struct describes the main control config of Vault.
+### 4. _**Get Pool by Address**_
-```
-struct Config {
- /// The Contract address that used for controls settings for factory, pools and tokenomics contracts
- owner: Addr,
- /// The Contract ID that is used for instantiating LP tokens for new pools
- lp_token_code_id: u64,
- /// The contract address to which protocol fees are sent
- fee_collector: Option,
- /// The contract where users can stake LP tokens for 3rd party rewards. Used for `auto-stake` feature
- generator_address: Option,
- /// The next pool ID to be used for creating new pools
- next_pool_id: Uint128,
-}
-```
+Get the pool config for a pool address.
-### `PoolConfig` struct - This struct stores a pool type's configuration.
+#### Request
-```
-struct PoolConfig {
- /// ID of contract which is used to create pools of this type
- code_id: u64,
- /// The pools type (provided in a [`PoolType`])
- pool_type: PoolType,
- fee_info: FeeInfo,
- /// Whether a pool type is disabled or not. If it is disabled, new pools cannot be
- /// created, but existing ones can still read the pool configuration
- is_disabled: bool,
- /// Setting this to true means that pools of this type will not be able
- /// to get added to generator
- is_generator_disabled: bool
+```json
+{
+ "get_pool_by_address": {
+ "pool_addr": "persistence1..."
+ }
}
```
-### `PoolInfo` struct - This struct stores a pool type's configuration.
+#### Response
-```
-struct PoolInfo {
- /// ID of contract which is allowed to create pools of this type
- pool_id: Uint128,
- /// Address of the Pool Contract
- pool_addr: Option,
- /// Address of the LP Token Contract
- lp_token_addr: Option,
- /// Assets and their respective balances
- assets: Vec,
- /// The pools type (provided in a [`PoolType`])
- pool_type: PoolType,
- /// The address to which the collected developer fee is transferred
- developer_addr: Option,
-}
-```
+same as above
-### `SingleSwapRequest` struct - This struct stores a pool type's configuration.
+### 5. _**Get Pool by LP Token Address**_
-```
-struct SingleSwapRequest {
- pool_id: Uint128,
- asset_in: AssetInfo,
- asset_out: AssetInfo,
- swap_type: SwapType,
- amount: Uint128,
- max_spread: Option,
- belief_price: Option,
-}
-```
+Get the pool config for a LP token address.
-## Build schema and run unit-tests
+#### Request
-```
-cargo schema
-cargo test
+```json
+{
+ "get_pool_by_lp_token_address": {
+ "lp_token_addr": "persistence1..."
+ }
+}
```
-## License
+#### Response
-TBD
+same as above
diff --git a/docs/ADMIN_PARAMS.md b/docs/ADMIN_PARAMS.md
new file mode 100644
index 00000000..dfbe4fb0
--- /dev/null
+++ b/docs/ADMIN_PARAMS.md
@@ -0,0 +1,108 @@
+# Dexter Admin Parameters
+
+Dexter admin parameters are spread throughout the codebase. This document is an attempt to consolidate them in one place. All these parameters can be governed by the `owner` of the respective Dexter contracts (vault and the multi-staking contract)
+
+With the rollout of Governance Admin based control of the `owner` role, all these parameters can be changed by triggering right kind of of call from the Governance Admin contract by it's `ExecuteMsgs` entrypoint using a Governance proposal.
+
+## Admin roles and their responsibilities
+
+Currently, there are these admin roles in the Dexter contracts:
+
+### Vault Admin
+- The vault admin role is the main controller of the protocol.
+- It can add pool managers, update the vault config, or update the config of any of the existing pools or pool types.
+
+All the things that the vault admin can do are explained in depth in the respective Contracts section.
+
+### Pool Manager
+- Pool creation
+- Can invoke Emergency Pause - based on Pool type or Pool ID
+
+### Multistaking Admin
+- Can create new reward schedules.
+- Can add or remove new whitelisted tokens for rewards.
+
+### Keeper Admin
+- Keeper admin can withdraw the funds set aside as part of the protocol treasury(30% of the swap fees) that are generated from the Swaps.
+
+
+The roles are mapped to following accounts currently:
+
+| Contract | Role | Account |
+| --- | --- | --- |
+| Vault | Vault Owner | Dexter Governance Admin contract |
+| Vault | Pool Manager | Dexter team multisig contract |
+| Keeper | Keeper Owner | Dexter treasury multisig contract |
+| Multistaking | Multistaking Owner | Dexter Governance Admin contract |
+
+## Contracts
+
+Each contract exposes some functions which could be executed by one of the admins mentioned above.
+
+### Vault
+
+**Vault Owner**: Vault owner has most control over the protocol. It can add pool managers, update the vault config, or update the config of any of the existing pools or pool types.
+
+All of the functions that the vault owner can execute can be found [here](../contracts/vault#only-owner-executable)
+
+The parameters that can be configured are:
+
+| Parameter | Description |
+| --- | --- |
+| Fee Collector Address | Address of the contract which collects fees. Currently, the Dexter keeper contract |
+| LP Token Code ID | Code ID of the LP token contract. This is used to create new LP tokens for new pools. Ideally not updated post initial deployment |
+| Pool Creation Fee | Fee in the specified denom for creating a new pool. This is used to prevent spamming of the pool creation feature. |
+| Auto-stake implementation | Address of the contract which implements the auto-stake feature. Currently, the Dexter multistaking contract |
+| Whitelisted managers | List of addresses which currently have the manager role |
+| Default fee for a pool type | Default fee for a pool type. This is used when a new pool of that type is created. |
+| Pool type pause configuration | Pause configuration for each pool type. This is used to pause/unpause specific operations for a pool type. |
+| Pool pause configuration | Pause configuration for each pool. This is used to pause/unpause specific operations for a pool. |
+
+
+
+**Pool Manager**: Pool manager can create new pools, or pause/unpause existing pools.
+
+All of the functions that the pool manager can execute can be found [here](../contracts/vault#owner-and-manager-executable)
+
+### Stable Pool
+
+**Vault Owner**: Vault owner can update the config of the stable pool type. The parameters that can be updated are:
+
+| Parameter | Description |
+| --- | --- |
+| AMP | The stable swap amplification factor |
+| Scaling factor manager | The address of the scaling factor manager. Scaling factor manager is responsible for updating the scaling factor of one (or more) assets in the pool |
+| Max allowed spread | Max allowed spread between the price of the asset and the price of the pool. If the spread is greater than this value, the swap will fail |
+
+Entry point related information can be found [here]()
+
+### Weighted Pool
+
+Weighted pool doesn't currently have any configurable parameters.
+
+### Multistaking
+
+**Multistaking Owner**: Multistaking owner can create new reward schedules, or add/remove whitelisted tokens for rewards.
+
+All of the functions that the multistaking owner can execute can be found [here](../contracts/multi_staking#owner-executable)
+
+To summarize, the parameters that can be configured are:
+
+| Parameter | Description |
+| --- | --- |
+| keeper_addr | Fee collector address |
+| unlock_period | Lockup period after unbonding for which the tokens are in an unlocking state |
+| instant_unbond_fee_bp | Fee in basis points for Instant LP unbonding feature |
+| instant_unbond_min_fee_bp | Min fee for tier based fee structure for instant-unlock feature for unlocking liquidity during the unlocking period |
+| fee_tier_interval | Interval for fee tier change. The unlock period is divided into tiers for partial unbond fee during unlock period |
+
+
+
+### Keeper
+
+**Keeper Owner**: Keeper owner can withdraw the funds set aside as part of the protocol treasury(30% of the swap fees) that are generated from the Swaps.
+
+All of the functions that the keeper owner can execute can be found [here]()
+
+
+
diff --git a/packages/dexter/src/multi_staking.rs b/packages/dexter/src/multi_staking.rs
index e195c286..b3981581 100644
--- a/packages/dexter/src/multi_staking.rs
+++ b/packages/dexter/src/multi_staking.rs
@@ -204,7 +204,7 @@ pub enum QueryMsg {
/// Returns current config of the contract
#[returns(Config)]
Config {},
- /// Returns currently unclaimed rewards for a user for a give LP token
+ /// Returns currently unclaimed rewards for a user for a given LP token
/// If a future block time is provided, it will return the unclaimed rewards till that block time.
#[returns(Vec)]
UnclaimedRewards {
@@ -362,7 +362,7 @@ pub enum ExecuteMsg {
/// order of transaction execution, thus it is better to pass the full lock explicitly.
token_locks: Vec,
},
- /// Allows to withdraw unbonded rewards for a specific LP token.
+ /// Allows to withdraw rewards for a specific LP token.
/// The rewards are sent to the user's address.
Withdraw {
lp_token: Addr,