From 9321c015e76638d320d34021180c3434afc4d1b8 Mon Sep 17 00:00:00 2001 From: Cosmic Vagabond <121588426+cosmic-vagabond@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:19:14 +0200 Subject: [PATCH] docs: improve module docs (#640) * docs: improve module docs * docs: added oracle pool mechanism section and improve stable stake doc to describe (un)bond flows --------- Co-authored-by: Amit Yadav --- x/amm/spec/02_mechanism.md | 107 +++++++++++ x/amm/spec/03_oracle_pools.md | 177 ++++++++++++++++++ x/amm/spec/{02_state.md => 04_state.md} | 2 +- x/amm/spec/{03_keeper.md => 05_keeper.md} | 2 +- .../spec/{04_endpoints.md => 06_endpoints.md} | 2 +- ...sk_management.md => 07_risk_management.md} | 2 +- x/amm/spec/{06_slippage.md => 08_slippage.md} | 2 +- ...eordering.md => 09_swap_txs_reordering.md} | 2 +- x/amm/spec/README.md | 31 ++- x/clock/spec/01_authorization.md | 38 ---- x/clock/spec/01_concepts.md | 83 ++++++++ x/clock/spec/02_usage.md | 14 ++ x/clock/spec/03_keeper.md | 44 +++++ x/clock/spec/04_protobuf_definitions.md | 94 ++++++++++ x/clock/spec/05_functions.md | 77 ++++++++ x/clock/spec/06_authorization.md | 42 +++++ .../{02_integration.md => 07_integration.md} | 14 +- x/clock/spec/README.md | 33 +++- x/epochs/spec/01_concepts.md | 5 + x/parameter/spec/01_concepts.md | 76 ++++++++ x/parameter/spec/02_usage.md | 13 ++ x/parameter/spec/03_keeper.md | 53 ++++++ x/parameter/spec/04_protobuf_definitions.md | 113 +++++++++++ x/parameter/spec/05_functions.md | 67 +++++++ x/parameter/spec/README.md | 29 +++ x/perpetual/spec/02_mechanism.md | 2 +- ...-perpetual-trading-design-long-y-asset.png | Bin x/stablestake/spec/01_concepts.md | 2 +- x/stablestake/spec/02_mechanism.md | 112 +++++++++++ .../spec/{02_usage.md => 03_usage.md} | 2 +- .../spec/{03_keeper.md => 04_keeper.md} | 2 +- ...initions.md => 05_protobuf_definitions.md} | 2 +- .../spec/{05_functions.md => 06_functions.md} | 2 +- x/stablestake/spec/README.md | 9 +- 34 files changed, 1181 insertions(+), 74 deletions(-) create mode 100644 x/amm/spec/02_mechanism.md create mode 100644 x/amm/spec/03_oracle_pools.md rename x/amm/spec/{02_state.md => 04_state.md} (99%) rename x/amm/spec/{03_keeper.md => 05_keeper.md} (99%) rename x/amm/spec/{04_endpoints.md => 06_endpoints.md} (98%) rename x/amm/spec/{05_risk_management.md => 07_risk_management.md} (99%) rename x/amm/spec/{06_slippage.md => 08_slippage.md} (99%) rename x/amm/spec/{07_swap_txs_reordering.md => 09_swap_txs_reordering.md} (99%) delete mode 100644 x/clock/spec/01_authorization.md create mode 100644 x/clock/spec/01_concepts.md create mode 100644 x/clock/spec/02_usage.md create mode 100644 x/clock/spec/03_keeper.md create mode 100644 x/clock/spec/04_protobuf_definitions.md create mode 100644 x/clock/spec/05_functions.md create mode 100644 x/clock/spec/06_authorization.md rename x/clock/spec/{02_integration.md => 07_integration.md} (93%) create mode 100644 x/parameter/spec/01_concepts.md create mode 100644 x/parameter/spec/02_usage.md create mode 100644 x/parameter/spec/03_keeper.md create mode 100644 x/parameter/spec/04_protobuf_definitions.md create mode 100644 x/parameter/spec/05_functions.md create mode 100644 x/parameter/spec/README.md rename x/perpetual/spec/{ => assets}/elys-perpetual-trading-design-long-y-asset.png (100%) create mode 100644 x/stablestake/spec/02_mechanism.md rename x/stablestake/spec/{02_usage.md => 03_usage.md} (98%) rename x/stablestake/spec/{03_keeper.md => 04_keeper.md} (99%) rename x/stablestake/spec/{04_protobuf_definitions.md => 05_protobuf_definitions.md} (99%) rename x/stablestake/spec/{05_functions.md => 06_functions.md} (99%) diff --git a/x/amm/spec/02_mechanism.md b/x/amm/spec/02_mechanism.md new file mode 100644 index 000000000..158677e87 --- /dev/null +++ b/x/amm/spec/02_mechanism.md @@ -0,0 +1,107 @@ + + +# Mechanism + +The Elys Network AMM module implements an Automated Market Maker (AMM) using various types of liquidity pools. It supports the following types of pools: + +1. **AMM Pools**: Non-oracle pools with liquidity centered around a specific spot price, designed for assets with significant price variation. +2. **Oracle Pools**: Oracle pools with liquidity centered around an oracle price, designed for assets with stable prices. + +This section explains the fundamental mechanism of the AMM module and provides an overview of how the module's code is structured to support both types of pools. + +The section **[Oracle Pools](03_oracle_pools.md)** provides additional details on the mechanism of Oracle Pools. + +## Pool + +### Creation of Pool + +When a new pool is created, a fixed amount of 100 share tokens is minted and sent to the pool creator's account. The pool share token denomination follows the format `amm/pool/{poolID}`. By default, pool assets are sorted in alphabetical order. Pool creation requires a minimum of 2 and a maximum of 8 asset denominations. + +A `PoolCreationFee` must be paid to create a pool, which helps prevent the creation of unnecessary or malicious pools. + +### Joining Pool + +Users can join a pool without swapping assets by using the `JoinPool` function. In this case, they provide the maximum amount of tokens (`TokenInMaxs`) they are willing to deposit. This parameter must include all the asset denominations in the pool, or none at all, otherwise, the transaction will be aborted. If no tokens are specified, the user's balance is used as the constraint. + +The front end calculates the number of share tokens the user is eligible for at the moment the transaction is sent. The exact calculation of tokens required for the designated share is performed during transaction processing, ensuring the deposit does not exceed the maximum specified. Once validated, the appropriate number of pool share tokens are minted and sent to the user's account. + +#### Existing Join Types + +- `JoinPool` + +### Exiting Pool + +To exit a pool, users specify the minimum amount of tokens they are willing to receive in return for their pool shares. Unlike joining, exiting a pool incurs an exit fee set as a pool parameter. The user's share tokens are burned in the process. Exiting with a single asset is also possible. + +Exiting is only allowed if the user will leave a positive balance for a certain denomination or a positive number of LP shares. Transactions that would completely drain a pool are aborted. + +Exiting with a swap requires paying both exit and swap fees. + +#### Existing Exit Types + +- `ExitPool` + +### Swap + +When swapping assets within the pool, the input token is referred to as `tokenIn` and the output token as `tokenOut`. The module uses the following formula to calculate the number of tokens exchanged: + +``` +tokenBalanceOut * [1 - { tokenBalanceIn / (tokenBalanceIn + (1 - swapFee) * tokenAmountIn)} ^ (tokenWeightIn / tokenWeightOut)] +``` + +To reverse the calculation (i.e., given `tokenOut`), the following formula is used: + +``` +tokenBalanceIn * [{tokenBalanceOut / (tokenBalanceOut - tokenAmountOut)} ^ (tokenWeightOut / tokenWeightIn) - 1] / tokenAmountIn +``` + +#### Existing Swap Types + +- `SwapExactAmountIn` +- `SwapExactAmountOut` + +### Spot Price + +The spot price, inclusive of the swap fee, is calculated using the formula: + +``` +spotPrice / (1 - swapFee) +``` + +Where `spotPrice` is defined as: + +``` +(tokenBalanceIn / tokenWeightIn) / (tokenBalanceOut / tokenWeightOut) +``` + +### Multi-Hop + +Multi-hop logic is supported by the AMM module, allowing users to swap between multiple pools in a single transaction. The module calculates the optimal path for the swap, taking into account the swap fee and the spot price of each pool. + +## Weights + +Weights determine the distribution of assets within a pool. They are often expressed as ratios. For example, a 1:1 pool between "ETH" and "BTC" has a spot price of `#ETH in pool / #BTC in pool`. A 2:1 pool has a spot price of `2 * (#ETH in pool) / #BTC in pool`, which means fewer ETH reserves are required to maintain the same spot price, though it increases slippage. + +Internally, weights are represented as numbers, with ratios computed as needed. Pools can be defined with weights up to `2^20`, and weight changes are managed with 30 bits of precision for smooth transitions. + +## Network Parameters + +Pools have the following configurable parameters: + +| Key | Type | +| ------------------------ | -------------------------- | +| SwapFee | sdk.Dec | +| ExitFee | sdk.Dec | +| Weights | \*Weights | +| SmoothWeightChangeParams | \*SmoothWeightChangeParams | +| PoolCreationFee | sdk.Coins | + +### Parameter Definitions + +- **SwapFee**: A percentage cut of all swaps that goes to the liquidity providers (LPs) of a pool. +- **ExitFee**: A fee applied when LPs remove their liquidity from the pool. +- **Weights**: Defines the asset weight ratios within the pool. +- **SmoothWeightChangeParams**: Allows for gradual weight adjustments over time. +- **PoolCreationFee**: The fee required to create a new pool, currently set to 20 USDC. diff --git a/x/amm/spec/03_oracle_pools.md b/x/amm/spec/03_oracle_pools.md new file mode 100644 index 000000000..166950d15 --- /dev/null +++ b/x/amm/spec/03_oracle_pools.md @@ -0,0 +1,177 @@ + + +# Oracle Pools + +Oracle Pools are liquidity pools designed to provide low slippage for two assets that are expected to have a tightly correlated price ratio. The AMM (Automated Market Maker) achieves this low slippage around the expected price ratio, though price impact and slippage increase significantly as liquidity becomes more unbalanced. + +This documentation details the implementation of the Solidly stableswap curve, a type of Constant Function Market Maker (CFMM) with the invariant equation: + +$f(x, y) = xy(x^2 + y^2) = k$ + +For multiple assets, this is generalized to: + +$f(a_1, ..., a_n) = a_1 \cdot ... \cdot a_n (a_1^2 + ... + a_n^2)$ + +## Pool Configuration + +### Scaling Factor Handling + +Scaling factors in Oracle pools are analogous to asset weights, affecting the valuation of assets within the pool. A governor can adjust these scaling factors, particularly when assets do not maintain a fixed ratio but instead vary predictably (e.g., non-rebasing LSTs). + +By default, pools do not have a governor, as fixed ratios are sufficient for most stablecoin pools (e.g., 1:1 ratios). Scaling factors should typically be adjusted infrequently and with LPs (Liquidity Providers) being informed of the associated risks. + +### Practical Considerations + +1. **Precision Differences**: Different pegged coins may have varying precision levels. +2. **Token Variants**: Tokens like `TwoFoo` might need to trade around a specific multiple (e.g., `1 TwoFoo = 2 Foo`). +3. **Staking Derivatives**: Value accrual within the token can dynamically change the expected price concentration. + +Scaling factors map "raw coin units" to "AMM math units" by dividing the raw coin units by the scaling factor. For example, if `Foo` has a scaling factor of $10^6$ and `WrappedFoo` has a factor of 1, then the mapping is `raw coin units / scaling factor`. + +Rounding is handled by an enum `rounding mode` with three options: `RoundUp`, `RoundDown`, `RoundBankers`. These ensure precise rounding when dealing with scaled reserves. + +### Implementation + +#### Python Example for Scaling + +```python +scaled_Foo_reserves = decimal_round(pool.Foo_liquidity / 10^6, RoundingMode) +descaled_Foo_reserves = scaled_Foo_reserves * 10^6 +``` + +## Algorithm Details + +The AMM pool interface requires the implementation of several stateful methods: + +```golang +SwapOutAmtGivenIn(tokenIn sdk.Coins, tokenOutDenom string, spreadFactor osmomath.Dec) (tokenOut sdk.Coin, err error) +SwapInAmtGivenOut(tokenOut sdk.Coins, tokenInDenom string, spreadFactor osmomath.Dec) (tokenIn sdk.Coin, err error) +SpotPrice(baseAssetDenom string, quoteAssetDenom string) (osmomath.Dec, error) +JoinPool(tokensIn sdk.Coins, spreadFactor osmomath.Dec) (numShares osmomath.Int, err error) +JoinPoolNoSwap(tokensIn sdk.Coins, spreadFactor osmomath.Dec) (numShares osmomath.Int, err error) +ExitPool(numShares osmomath.Int, exitFee osmomath.Dec) (exitedCoins sdk.Coins, err error) +``` + +### CFMM Function + +The CFMM equation is symmetric, allowing us to reorder the arguments without loss of generality. We simplify the CFMM function for specific assets by using variable substitution: + +$$ +\begin{equation} + v = + \begin{cases} + 1, & \text{if } n=2 \\ + \prod\negthinspace \negthinspace \thinspace^{n}_{i=3} \space a_i, & \text{otherwise} + \end{cases} + \end{equation} +$$ + +$$ +\begin{equation} + w = + \begin{cases} + 0, & \text{if}\ n=2 \\ + \sum\negthinspace \negthinspace \thinspace^{n}_{i=3} \space {a_i^2}, & \text{otherwise} + \end{cases} + \end{equation} +$$ + +Thus, we define $g(x,y,v,w) = xyv(x^2 + y^2 + w) = f(x,y, a_3, ... a_n)$. + +### Swaps + +#### Direct Swap Solution + +For a swap involving $a$ units of $x$, yielding $b$ units of $y$: + +$g(x_0, y_0, v, w) = k = g(x_0 + a, y_0 - b, v, w)$ + +We solve for $y$ using the CFMM equation, which can be complex but is provable and can be approximated through iterative methods like binary search. + +#### Iterative Search Solution + +We perform a binary search to find $y$ such that $ h(x, y, w) = k' $, adjusting bounds iteratively for efficient computation. + +#### Pseudocode for Binary Search + +```python +def solve_y(x_0, y_0, w, x_in): + x_f = x_0 + x_in + err_tolerance = {"within factor of 10^-12", RoundUp} + y_f = iterative_search(x_0, x_f, y_0, w, err_tolerance) + y_out = y_0 - y_f + return y_out + +def iter_k_fn(x_f, y_0, w): + def f(y_f): + y_out = y_0 - y_f + return -(y_out)**3 + 3 y_0 * y_out^2 - (x_f**2 + w + 3y_0**2) * y_out + +def iterative_search(x_0, x_f, y_0, w, err_tolerance): + target_k = target_k_fn(x_0, y_0, w, x_f) + iter_k_calculator = iter_k_fn(x_f, y_0, w) + lowerbound, upperbound = y_0, y_0 + k_ratio = bound_estimation_k0 / bound_estimation_target_k + if k_ratio < 1: + upperbound = ceil(y_0 / k_ratio) + elif k_ratio > 1: + lowerbound = 0 + else: + return y_0 + max_iteration_count = 100 + return binary_search(lowerbound, upperbound, iter_k_calculator, target_k, err_tolerance) + +def binary_search(lowerbound, upperbound, approximation_fn, target, max_iteration_count, err_tolerance): + iter_count = 0 + cur_k_guess = 0 + while (not satisfies_bounds(cur_k_guess, target, err_tolerance)) and iter_count < max_iteration_count: + iter_count += 1 + cur_y_guess = (lowerbound + upperbound) / 2 + cur_k_guess = approximation_fn(cur_y_guess) + if cur_k_guess > target: + upperbound = cur_y_guess + else if cur_k_guess < target: + lowerbound = cur_y_guess + if iter_count == max_iteration_count: + return Error("max iteration count reached") + return cur_y_guess +``` + +### Spot Price + +The spot price is approximated by a small swap amount $\epsilon$: + +$\text{spot price} = \frac{\text{CalculateOutAmountGivenIn}(\epsilon)}{\epsilon}$ + +### LP Equations + +#### JoinPoolNoSwap and ExitPool + +These methods follow generic AMM techniques, maintaining consistency with the CFMM properties. + +#### JoinPoolSingleAssetIn + +For single asset joins: + +```python +def JoinPoolSingleAssetIn(pool, tokenIn): + spreadFactorApplicableFraction = 1 - (pool.ScaledLiquidityOf(tokenIn.Denom) / pool.SumOfAllScaledLiquidity()) + effectiveSpreadFactor = pool.SwapFee * spreadFactorApplicableFraction + effectiveTokenIn = RoundDown(tokenIn * (1 - effectiveSpreadFactor)) + return BinarySearchSingleJoinLpShares(pool, effectiveTokenIn) +``` + +## Code Structure + +The code is structured to facilitate unit testing for each pool interface method, custom message testing, and simulator integrations. + +## Testing Strategy + +- **Unit Tests**: For each pool interface method. +- **Msg Tests**: For custom messages like `CreatePool` and `SetScalingFactors`. +- **Simulator Integrations**: Testing pool creation, join and exit pool operations, single token join/exit, and CFMM adjustments. +- **Fuzz Testing**: To ensure the binary search algorithm and iterative approximation swap algorithm work correctly across various scales. + +By following this documentation, developers can understand and implement the Solidly stableswap curve efficiently, ensuring low slippage and robust functionality for tightly correlated asset pairs. diff --git a/x/amm/spec/02_state.md b/x/amm/spec/04_state.md similarity index 99% rename from x/amm/spec/02_state.md rename to x/amm/spec/04_state.md index 7a976dcb9..e47024d57 100644 --- a/x/amm/spec/02_state.md +++ b/x/amm/spec/04_state.md @@ -1,5 +1,5 @@ # State diff --git a/x/amm/spec/03_keeper.md b/x/amm/spec/05_keeper.md similarity index 99% rename from x/amm/spec/03_keeper.md rename to x/amm/spec/05_keeper.md index c0fbc1366..69f63c1e3 100644 --- a/x/amm/spec/03_keeper.md +++ b/x/amm/spec/05_keeper.md @@ -1,5 +1,5 @@ # Keepers diff --git a/x/amm/spec/04_endpoints.md b/x/amm/spec/06_endpoints.md similarity index 98% rename from x/amm/spec/04_endpoints.md rename to x/amm/spec/06_endpoints.md index 8a802f70a..3b9e575b4 100644 --- a/x/amm/spec/04_endpoints.md +++ b/x/amm/spec/06_endpoints.md @@ -1,5 +1,5 @@ # Endpoints diff --git a/x/amm/spec/05_risk_management.md b/x/amm/spec/07_risk_management.md similarity index 99% rename from x/amm/spec/05_risk_management.md rename to x/amm/spec/07_risk_management.md index 612938cf9..3f96462fc 100644 --- a/x/amm/spec/05_risk_management.md +++ b/x/amm/spec/07_risk_management.md @@ -1,5 +1,5 @@ # Risk management diff --git a/x/amm/spec/06_slippage.md b/x/amm/spec/08_slippage.md similarity index 99% rename from x/amm/spec/06_slippage.md rename to x/amm/spec/08_slippage.md index f701b6d74..24d02a1b2 100644 --- a/x/amm/spec/06_slippage.md +++ b/x/amm/spec/08_slippage.md @@ -1,5 +1,5 @@ # Slippage Model diff --git a/x/amm/spec/07_swap_txs_reordering.md b/x/amm/spec/09_swap_txs_reordering.md similarity index 99% rename from x/amm/spec/07_swap_txs_reordering.md rename to x/amm/spec/09_swap_txs_reordering.md index 59bd01c88..3ca8ae674 100644 --- a/x/amm/spec/07_swap_txs_reordering.md +++ b/x/amm/spec/09_swap_txs_reordering.md @@ -1,5 +1,5 @@ # Swap Transactions Reordering diff --git a/x/amm/spec/README.md b/x/amm/spec/README.md index a87f517a4..1ea2be1c8 100644 --- a/x/amm/spec/README.md +++ b/x/amm/spec/README.md @@ -1,11 +1,28 @@ -# Oracle based pool +# Elys AMM Module ## Contents 1. **[Concepts](01_concepts.md)** -2. **[State](02_state.md)** -3. **[Keeper](03_keeper.md)** -4. **[Endpoints](04_endpoints.md)** -5. **[Risk Management](05_risk_management.md)** -6. **[Slippage Model](06_slippage.md)** -7. **[Swap Transactions Reordering](07_swap_txs_reordering.md)** +2. **[Mechanism](02_mechanism.md)** +3. **[Oracle Pools](03_oracle_pools.md)** +4. **[State](04_state.md)** +5. **[Keeper](05_keeper.md)** +6. **[Endpoints](06_endpoints.md)** +7. **[Risk Management](07_risk_management.md)** +8. **[Slippage Model](08_slippage.md)** +9. **[Swap Transactions Reordering](09_swap_txs_reordering.md)** + +## References + +Resources: + +- [Elys Network Documentation](https://docs.elys.network) +- [Cosmos SDK Documentation](https://docs.cosmos.network) +- [GitHub Repository for Elys Network](https://github.com/elys-network/elys) + +## Overview + +The Elys Network AMM module implements an Automated Market Maker (AMM) using various types of liquidity pools. It supports the following types of pools: + +1. **AMM Pools**: Non-oracle pools with liquidity centered around a specific spot price, designed for assets with significant price variation. +2. **Oracle Pools**: Oracle pools with liquidity centered around an oracle price, designed for assets with stable prices. diff --git a/x/clock/spec/01_authorization.md b/x/clock/spec/01_authorization.md deleted file mode 100644 index 9d01f9733..000000000 --- a/x/clock/spec/01_authorization.md +++ /dev/null @@ -1,38 +0,0 @@ -# Authorization - -For security purposes, only the governance module can add new contracts to the EndBlocker executes. - -## Query contracts - -You can query the list of contracts that are 'ticked' every block with the following command: - -```bash - elysd q clock contracts --output json - # {"contract_addresses":[]} -``` - -## Governance proposal - -To update the authorized address is possible to create an onchain new proposal. You can use the following example `proposal.json` file - -```json -{ - "messages": [ - { - "@type": "/elys.clock.v1.MsgUpdateParams", - "authority": "elys10d07y265gmmuvt4z0w9aw880jnsr700jvss730", - "params": { - "contract_addresses": [ - "elys14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8" - ] - } - } - ], - "metadata": "{\"title\": \"Allow a new contract to use the x/clock module for our features\", \"authors\": [\"Reece\"], \"summary\": \"If this proposal passes elys14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be added to the authorized addresses of the clock module\", \"details\": \"If this proposal passes elys14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be added to the authorized addresses of the clock module\", \"proposal_forum_url\": \"https://commonwealth.im/elys/discussion/9697-elys-protocol-level-defi-incentives\", \"vote_option_context\": \"yes\"}", - "deposit": "1000000uelys", - "title": "Allow a new contract to use the x/clock module for our features", - "summary": "If this proposal passes elys14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be allowed to use the x/clock module to perform XYZ actions", -} -``` - -It can be submitted with the standard `elysd tx gov submit-proposal proposal.json --from=YOURKEY` command. diff --git a/x/clock/spec/01_concepts.md b/x/clock/spec/01_concepts.md new file mode 100644 index 000000000..072512c36 --- /dev/null +++ b/x/clock/spec/01_concepts.md @@ -0,0 +1,83 @@ + + +# Concepts + +The `clock` module in the Elys Network is designed to manage contract execution at the end of each block. It ensures that specific smart contracts are triggered automatically, allowing for scheduled tasks and automated processes within the blockchain. + +## Module Components + +1. **Keeper**: The core component that handles the business logic of the `Clock` module. +2. **End Blocker**: Executes specified contracts at the end of each block. +3. **WASM Integration**: Facilitates interaction with smart contracts through WASM. + +## Key Functions + +### 1. `EndBlocker` + +The `EndBlocker` function is responsible for executing contracts at the end of each block. It performs the following steps: + +- **Retrieve Parameters**: Fetches the current parameters, including contract addresses and gas limits. +- **Execute Contracts**: Iterates over the contract addresses and executes each one with a predefined message. +- **Log Errors**: Logs any errors that occur during contract execution. + +**Function Signature**: + +```go +func EndBlocker(ctx sdk.Context, k keeper.Keeper) +``` + +**Parameters**: + +- `ctx`: The context of the current transaction. +- `k`: The Keeper instance. + +**Return**: + +- This function does not return a value but logs execution errors if any occur. + +### 2. `SetParams` + +The `SetParams` function sets the parameters for the `Clock` module. + +**Function Signature**: + +```go +func (k Keeper) SetParams(ctx sdk.Context, p types.Params) error +``` + +**Parameters**: + +- `ctx`: The context of the current transaction. +- `p`: The parameters to set. + +**Return**: + +- Returns an error if parameter validation fails. + +### 3. `GetParams` + +The `GetParams` function retrieves the current parameters for the `Clock` module. + +**Function Signature**: + +```go +func (k Keeper) GetParams(ctx sdk.Context) (p types.Params) +``` + +**Parameters**: + +- `ctx`: The context of the current transaction. + +**Return**: + +- Returns the current parameters. + +## Error Handling + +The `Clock` module includes error handling to manage cases where contract execution fails. Errors are logged with details about the failed executions. + +## Integration + +The `Clock` module integrates with the WASM module to execute smart contracts. It uses the `Keeper` component to manage contract addresses and execution parameters. diff --git a/x/clock/spec/02_usage.md b/x/clock/spec/02_usage.md new file mode 100644 index 000000000..ca58ef83b --- /dev/null +++ b/x/clock/spec/02_usage.md @@ -0,0 +1,14 @@ + + +# Usage + +## Commands + +### Querying Clock Contracts + +```bash +elysd query clock contracts +elysd query clock params +``` diff --git a/x/clock/spec/03_keeper.md b/x/clock/spec/03_keeper.md new file mode 100644 index 000000000..458de6ce6 --- /dev/null +++ b/x/clock/spec/03_keeper.md @@ -0,0 +1,44 @@ + + +# Keeper + +## Contract Management + +The `clock` module's keeper handles the management of contracts, including retrieving and setting parameters. + +### SetParams + +The `SetParams` function sets the specific parameters in the store. + +```go +func (k Keeper) SetParams(ctx sdk.Context, p types.Params) error { + if err := p.Validate(); err != nil { + return err + } + + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&p) + store.Set(types.ParamsKey, bz) + + return nil +} +``` + +### GetParams + +The `GetParams` function retrieves the parameters from the store. + +```go +func (k Keeper) GetParams(ctx sdk.Context) (p types.Params) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.ParamsKey) + if bz == nil { + return p + } + + k.cdc.MustUnmarshal(bz, &p) + return p +} +``` diff --git a/x/clock/spec/04_protobuf_definitions.md b/x/clock/spec/04_protobuf_definitions.md new file mode 100644 index 000000000..c4d781aaf --- /dev/null +++ b/x/clock/spec/04_protobuf_definitions.md @@ -0,0 +1,94 @@ + + +# Protobuf Definitions + +## Types + +### Params + +The `Params` message defines the structure for module parameters, including contract addresses and gas limits. + +```proto +message Params { + repeated string contract_addresses = 1; + uint64 contract_gas_limit = 2; +} +``` + +### GenesisState + +The `GenesisState` message defines the initial state of the `clock` module at genesis. + +```proto +message GenesisState { + Params params = 1 [(gogoproto.nullable) = false]; +} +``` + +## Messages + +### MsgUpdateParams + +The `MsgUpdateParams` message allows updating the module parameters via governance. + +```proto +message MsgUpdateParams { + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + Params params = 2 [(gogoproto.nullable) = false]; +} +``` + +## Queries + +### Query Service + +The `Query` service defines the gRPC querier service for the `clock` module. + +```proto +service Query { + rpc ClockContracts (QueryClockContracts) returns (QueryClockContractsResponse) { + option (google.api.http).get = "/elys/clock/v1/contracts"; + } + rpc Params (QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/elys/clock/v1/params"; + } +} +``` + +#### QueryClockContractsRequest + +This message requests a list of all contract addresses. + +```proto +message QueryClockContracts {} +``` + +#### QueryClockContractsResponse + +This message responds with the list of all contract addresses. + +```proto +message QueryClockContractsResponse { + repeated string contract_addresses = 1; +} +``` + +#### QueryParamsRequest + +This message requests the current module parameters. + +```proto +message QueryParamsRequest {} +``` + +#### QueryParamsResponse + +This message responds with the current module parameters. + +```proto +message QueryParamsResponse { + Params params = 1; +} +``` diff --git a/x/clock/spec/05_functions.md b/x/clock/spec/05_functions.md new file mode 100644 index 000000000..4c24c6aac --- /dev/null +++ b/x/clock/spec/05_functions.md @@ -0,0 +1,77 @@ + + +# Functions + +## EndBlocker + +The `EndBlocker` function executes specified contracts at the end of each block. + +```go +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) + + message := []byte(types.EndBlockSudoMessage) + p := k.GetParams(ctx) + errorExecs := make([]string, 0) + + for idx, addr := range p.ContractAddresses { + contract, err := sdk.AccAddressFromBech32(addr) + if err != nil { + errorExecs[idx] = addr + continue + } + + childCtx := ctx.WithGasMeter(sdk.NewGasMeter(p.ContractGasLimit)) + _, err = k.GetContractKeeper().Sudo(childCtx, contract, message) + if err != nil { + errorExecs = append(errorExecs, err.Error()) + continue + } + } + + if len(errorExecs) > 0 { + log.Printf("[x/clock] Execute Errors: %v", errorExecs) + } +} +``` + +## SetParams + +The `SetParams` function sets new parameters for the module. + +```go +func (k Keeper) SetParams(ctx sdk.Context, p types.Params) error { + if err := p.Validate(); err != nil { + return err + } + + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&p) + store.Set(types.ParamsKey, bz) + + return nil +} +``` + +## GetParams + +The `GetParams` function retrieves the current parameters for the module. + +```go +func (k Keeper) GetParams(ctx sdk.Context) (p types.Params) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.ParamsKey) + if bz == nil { + return p + } + + k.cdc.MustUnmarshal(bz, &p) + return p +} +``` + +## Hooks + +The `clock` module does not include any hooks for integration with other modules. diff --git a/x/clock/spec/06_authorization.md b/x/clock/spec/06_authorization.md new file mode 100644 index 000000000..59c3c9646 --- /dev/null +++ b/x/clock/spec/06_authorization.md @@ -0,0 +1,42 @@ + + +# Authorization + +For security purposes, only the governance module can add new contracts to the EndBlocker executes. + +## Query contracts + +You can query the list of contracts that are 'ticked' every block with the following command: + +```bash + elysd q clock contracts --output json + # {"contract_addresses":[]} +``` + +## Governance proposal + +To update the authorized address is possible to create an onchain new proposal. You can use the following example `proposal.json` file + +```json +{ + "messages": [ + { + "@type": "/elys.clock.v1.MsgUpdateParams", + "authority": "elys10d07y265gmmuvt4z0w9aw880jnsr700jvss730", + "params": { + "contract_addresses": [ + "elys14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8" + ] + } + } + ], + "metadata": "{\"title\": \"Allow a new contract to use the x/clock module for our features\", \"authors\": [\"Reece\"], \"summary\": \"If this proposal passes elys14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be added to the authorized addresses of the clock module\", \"details\": \"If this proposal passes elys14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be added to the authorized addresses of the clock module\", \"proposal_forum_url\": \"https://commonwealth.im/elys/discussion/9697-elys-protocol-level-defi-incentives\", \"vote_option_context\": \"yes\"}", + "deposit": "1000000uelys", + "title": "Allow a new contract to use the x/clock module for our features", + "summary": "If this proposal passes elys14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be allowed to use the x/clock module to perform XYZ actions" +} +``` + +It can be submitted with the standard `elysd tx gov submit-proposal proposal.json --from=YOURKEY` command. diff --git a/x/clock/spec/02_integration.md b/x/clock/spec/07_integration.md similarity index 93% rename from x/clock/spec/02_integration.md rename to x/clock/spec/07_integration.md index fa7646339..49b522fbd 100644 --- a/x/clock/spec/02_integration.md +++ b/x/clock/spec/07_integration.md @@ -1,3 +1,7 @@ + + # CosmWasm Integration This module does not require any custom bindings. Rather, you must just add the following Sudo message to your contract. If your contract is not whitelisted, you can still upload it to the chain. However, to get it to execute, you must submit a proposal to add your contract to the whitelist. @@ -11,14 +15,14 @@ Add the following to your Rust Contract: ```rust // msg.rs #[cw_serde] -pub enum SudoMsg { +pub enum SudoMsg { ClockEndBlock { }, } // contract.rs #[cfg_attr(not(feature = "library"), entry_point)] pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result { - match msg { + match msg { SudoMsg::ClockEndBlock { } => { let mut config = CONFIG.load(deps.storage)?; config.val += 1; @@ -38,9 +42,9 @@ If you wish not to have your action performed every block, you can use the `env` // contract.rs #[cfg_attr(not(feature = "library"), entry_point)] pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { - match msg { - SudoMsg::ClockEndBlock { } => { - // If the block is not divisible by ten, do nothing. + match msg { + SudoMsg::ClockEndBlock { } => { + // If the block is not divisible by ten, do nothing. if env.block.height % 10 != 0 { return Ok(Response::new()); } diff --git a/x/clock/spec/README.md b/x/clock/spec/README.md index 0eb67d8a7..e8f34bb60 100644 --- a/x/clock/spec/README.md +++ b/x/clock/spec/README.md @@ -1,14 +1,31 @@ -# `clock` +# Elys Clock Module -## Abstract +## Contents -This document specifies the internal `x/clock` module of Elys Network. +1. **[Concepts](01_concepts.md)** +2. **[Usage](02_usage.md)** +3. **[Keeper](03_keeper.md)** +4. **[Protobuf Definitions](04_protobuf_definitions.md)** +5. **[Functions](05_functions.md)** +6. **[Authorization](06_authorization.md)** +7. **[Contract Integration](07_integration.md)** -The `x/clock` module allows specific contracts to be executed at the end of every block. This allows the smart contract to perform actions that may need to happen every block, or at set block intervals. +## References -By using this module, your application can remove the headache of external whitelisted bots and instead depend on the chain itself for constant executions. +Resources: -## Contents +- [Elys Network Documentation](https://docs.elys.network) +- [Cosmos SDK Documentation](https://docs.cosmos.network) +- [GitHub Repository for Elys Network](https://github.com/elys-network/elys) + +## Overview + +The `clock` module in the Elys Network is designed to manage the execution of smart contracts at the end of each block. It provides functionalities for setting, updating, and querying the contract addresses and parameters. This module ensures automated and scheduled execution of tasks, enhancing the functionality of the blockchain. + +## Key Features + +- **Automated Contract Execution**: Execute specified smart contracts at the end of each block. +- **Parameter Management**: Manage contract addresses and execution parameters dynamically. +- **Query Services**: Provide gRPC and CLI query services for accessing contract information and parameters. -1. **[Authorization](01_authorization.md)** -2. **[Contract Integration](02_integration.md)** +For more detailed information, please refer to the individual sections listed in the contents above. diff --git a/x/epochs/spec/01_concepts.md b/x/epochs/spec/01_concepts.md index 8ff8a69e6..8edefb772 100644 --- a/x/epochs/spec/01_concepts.md +++ b/x/epochs/spec/01_concepts.md @@ -7,3 +7,8 @@ order: 1 The `epochs` module defines on-chain timers that execute at fixed time intervals. Other Elys modules can then register logic to be executed at the timer ticks. We refer to the period in between two timer ticks as an "epoch". Every timer has a unique identifier, and every epoch will have a start time and an end time, where `end time = start time + timer interval`. + +# References + +- [Evmos Epochs module](https://docs.evmos.org/protocol/modules/epochs) +- [Osmosis Epochs module](https://docs.osmosis.zone/osmosis-core/modules/epochs) diff --git a/x/parameter/spec/01_concepts.md b/x/parameter/spec/01_concepts.md new file mode 100644 index 000000000..128908be4 --- /dev/null +++ b/x/parameter/spec/01_concepts.md @@ -0,0 +1,76 @@ + + +# Concepts + +The `parameter` module in the Elys Network manages key configuration parameters for the network, enabling dynamic updates and retrievals. It facilitates the modification of various parameters related to commissions, voting power, self-delegation, broker address, total blocks per year, and WASM configuration. + +## Module Components + +1. **Keeper**: The core component that handles the business logic of the `parameter` module. +2. **MsgServer**: Handles the gRPC messages to update parameters. +3. **Querier**: Handles the queries to retrieve parameter values. + +## Key Functions + +### 1. `UpdateMinCommission` + +The `UpdateMinCommission` function updates the minimum commission rate for validators. It performs the following steps: + +- **Check Authority**: Ensures the caller has the authority to update the parameter. +- **Validate Commission Rate**: Checks if the new commission rate is valid. +- **Update State**: Saves the updated commission rate to the store. + +**Function Signature**: + +```go +func (k msgServer) UpdateMinCommission(goCtx context.Context, msg *types.MsgUpdateMinCommission) (*types.MsgUpdateMinCommissionResponse, error) +``` + +**Parameters**: + +- `goCtx`: The context of the current transaction. +- `msg`: The message containing the new commission rate. + +**Return**: + +- Returns an error if the caller lacks authority or if the commission rate is invalid. + +### 2. `UpdateWasmConfig` + +The `UpdateWasmConfig` function updates the configuration parameters for WASM. It includes the maximum label size, maximum size, and maximum proposal size. + +**Function Signature**: + +```go +func (k msgServer) UpdateWasmConfig(goCtx context.Context, msg *types.MsgUpdateWasmConfig) (*types.MsgUpdateWasmConfigResponse, error) +``` + +**Parameters**: + +- `goCtx`: The context of the current transaction. +- `msg`: The message containing the new WASM configuration values. + +**Return**: + +- Returns an error if the caller lacks authority or if the parameters are invalid. + +## Hooks + +The `parameter` module does not include hooks as it primarily deals with static configuration parameters rather than dynamic state changes. + +## Error Handling + +The `parameter` module includes error handling to manage invalid parameters or unauthorized access. Notable errors include: + +- `types.ErrInvalidMinCommissionRate` +- `types.ErrInvalidMaxVotingPower` +- `types.ErrInvalidMinSelfDelegation` +- `types.ErrInvalidBrokerAddress` + +These errors ensure that the module can gracefully handle invalid updates and provide meaningful feedback for debugging and resolution. + +## Integration + +The `parameter` module integrates with other modules by providing a centralized mechanism for updating and retrieving configuration parameters. It ensures consistent and controlled parameter management across the network. diff --git a/x/parameter/spec/02_usage.md b/x/parameter/spec/02_usage.md new file mode 100644 index 000000000..e4a45f1dd --- /dev/null +++ b/x/parameter/spec/02_usage.md @@ -0,0 +1,13 @@ + + +# Usage + +## Commands + +### Querying Parameters + +```bash +elysd query parameter params +``` diff --git a/x/parameter/spec/03_keeper.md b/x/parameter/spec/03_keeper.md new file mode 100644 index 000000000..5feb10f18 --- /dev/null +++ b/x/parameter/spec/03_keeper.md @@ -0,0 +1,53 @@ + + +# Keeper + +## Parameter Management + +The `parameter` module's keeper handles the management of configuration parameters, including setting, updating, and retrieving their values. + +### GetParams + +The `GetParams` function retrieves the current parameters from the store. + +```go +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + store := ctx.KVStore(k.storeKey) + b := store.Get([]byte(types.ParamsKey)) + if b == nil { + return + } + k.cdc.MustUnmarshal(b, ¶ms) + return +} +``` + +### SetParams + +The `SetParams` function sets the parameters in the store. + +```go +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + store := ctx.KVStore(k.storeKey) + b := k.cdc.MustMarshal(¶ms) + store.Set([]byte(types.ParamsKey), b) +} +``` + +### GetLegacyParams + +The `GetLegacyParams` function retrieves the legacy parameters from the store. + +```go +func (k Keeper) GetLegacyParams(ctx sdk.Context) (params types.LegacyParams) { + store := ctx.KVStore(k.storeKey) + b := store.Get([]byte(types.ParamsKey)) + if b == nil { + return + } + k.cdc.MustUnmarshal(b, ¶ms) + return +} +``` diff --git a/x/parameter/spec/04_protobuf_definitions.md b/x/parameter/spec/04_protobuf_definitions.md new file mode 100644 index 000000000..a2227cfb4 --- /dev/null +++ b/x/parameter/spec/04_protobuf_definitions.md @@ -0,0 +1,113 @@ + + +# Protobuf Definitions + +## Types + +### Params + +The `Params` message defines the structure of the configuration parameters, including commission rates, voting power, self-delegation, broker address, and WASM configuration. + +```proto +message Params { + string min_commission_rate = 1 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string max_voting_power = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string min_self_delegation = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + string broker_address = 4; + int64 total_blocks_per_year = 5; + int64 rewards_data_lifetime = 6; + string wasm_max_label_size = 7 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + string wasm_max_size = 8 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + string wasm_max_proposal_wasm_size = 9 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; +} +``` + +### GenesisState + +The `GenesisState` message defines the initial state of the `parameter` module at genesis. + +```proto +message GenesisState { + Params params = 1 [(gogoproto.nullable) = false]; +} +``` + +## Messages + +### MsgUpdateMinCommission + +This message updates the minimum commission rate. + +```proto +message MsgUpdateMinCommission { + string creator = 1; + string min_commission = 2; +} +message MsgUpdateMinCommissionResponse {} +``` + +### MsgUpdateWasmConfig + +This message updates the WASM configuration parameters. + +```proto +message MsgUpdateWasmConfig { + string creator = 1; + string wasm_max_label_size = 2; + string wasm_max_size = 3; + string wasm_max_proposal_wasm_size = 4; +} +message MsgUpdateWasmConfigResponse {} +``` + +## Queries + +### Query Service + +The `Query` service defines the gRPC querier service for the `parameter` module. + +```proto +service Query { + rpc Params (QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/elys-network/elys/parameter/params"; + } +} +``` + +#### QueryParamsRequest + +This message requests the current parameters. + +```proto +message QueryParamsRequest {} +``` + +#### QueryParamsResponse + +This message responds with the current parameters. + +```proto +message QueryParamsResponse { + Params params = 1 [(gogoproto.nullable) = false]; +} +``` diff --git a/x/parameter/spec/05_functions.md b/x/parameter/spec/05_functions.md new file mode 100644 index 000000000..0a45ce081 --- /dev/null +++ b/x/parameter/spec/05_functions.md @@ -0,0 +1,67 @@ + + +# Functions + +## UpdateMinCommission + +The `UpdateMinCommission` function updates the minimum commission rate. + +```go +func (k msgServer) UpdateMinCommission(goCtx context.Context, msg *types.MsgUpdateMinCommission) (*types.MsgUpdateMinCommissionResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + if k.authority != msg.Creator { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, msg.Creator) + } + + minCommission, err := sdk.NewDecFromStr(msg.MinCommission) + if err != nil { + return nil, err + } + + params := k.GetParams(ctx) + params.MinCommissionRate = minCommission + k.SetParams(ctx, params) + return &types.MsgUpdateMinCommissionResponse{}, nil +} +``` + +## UpdateWasmConfig + +The `UpdateWasmConfig` function updates the WASM configuration parameters. + +```go +func (k msgServer) UpdateWasmConfig(goCtx context.Context, msg *types.MsgUpdateWasmConfig) (*types.MsgUpdateWasmConfigResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + if k.authority != msg.Creator { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, msg.Creator) + } + + wasmMaxLabelSize, ok := sdk.NewIntFromString(msg.WasmMaxLabelSize) + if !ok { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "wasm max label size must be a positive integer") + } + + wasmMaxProposalWasmSize, ok := sdk.NewIntFromString(msg.WasmMaxProposalWasmSize) + if !ok { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "wasm max proposal wasm size must be a positive integer") + } + + wasmMaxSize, ok := sdk.NewIntFromString(msg.WasmMaxSize) + + + if !ok { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "wasm max size must be a positive integer") + } + + params := k.GetParams(ctx) + params.WasmMaxLabelSize = wasmMaxLabelSize + params.WasmMaxProposalWasmSize = wasmMaxProposalWasmSize + params.WasmMaxSize = wasmMaxSize + k.SetParams(ctx, params) + return &types.MsgUpdateWasmConfigResponse{}, nil +} +``` diff --git a/x/parameter/spec/README.md b/x/parameter/spec/README.md new file mode 100644 index 000000000..cc402b3e2 --- /dev/null +++ b/x/parameter/spec/README.md @@ -0,0 +1,29 @@ +# Elys Parameter Module + +## Contents + +1. **[Concepts](01_concepts.md)** +2. **[Usage](02_usage.md)** +3. **[Keeper](03_keeper.md)** +4. **[Protobuf Definitions](04_protobuf_definitions.md)** +5. **[Functions](05_functions.md)** + +## References + +Resources: + +- [Elys Network Documentation](https://docs.elys.network) +- [Cosmos SDK Documentation](https://docs.cosmos.network) +- [GitHub Repository for Elys Network](https://github.com/elys-network/elys) + +## Overview + +The `parameter` module in the Elys Network is designed to manage and maintain key configuration parameters within the network. It provides functionalities for creating, updating, and querying parameters. This module enhances the network by allowing dynamic and controlled adjustments to critical settings. + +## Key Features + +- **Dynamic Parameter Management**: Allows for the updating and retrieval of key network parameters. +- **Query Services**: Provides gRPC and CLI query services for accessing parameter information. +- **Controlled Updates**: Ensures that only authorized entities can update parameters, maintaining network integrity. + +For more detailed information, please refer to the individual sections listed in the contents above. diff --git a/x/perpetual/spec/02_mechanism.md b/x/perpetual/spec/02_mechanism.md index e96e02edc..8477cf670 100644 --- a/x/perpetual/spec/02_mechanism.md +++ b/x/perpetual/spec/02_mechanism.md @@ -6,7 +6,7 @@ order: 2 The following section provides a detailed technical explanation of the perpetual trading mechanism as depicted in the Elys Perpetual Trading Design diagram. -![Elys Perpetual Trading Design](elys-perpetual-trading-design-long-y-asset.png) +![Elys Perpetual Trading Design](./assets/elys-perpetual-trading-design-long-y-asset.png) ## Overview diff --git a/x/perpetual/spec/elys-perpetual-trading-design-long-y-asset.png b/x/perpetual/spec/assets/elys-perpetual-trading-design-long-y-asset.png similarity index 100% rename from x/perpetual/spec/elys-perpetual-trading-design-long-y-asset.png rename to x/perpetual/spec/assets/elys-perpetual-trading-design-long-y-asset.png diff --git a/x/stablestake/spec/01_concepts.md b/x/stablestake/spec/01_concepts.md index cf9866f87..5cc05e643 100644 --- a/x/stablestake/spec/01_concepts.md +++ b/x/stablestake/spec/01_concepts.md @@ -4,4 +4,4 @@ order: 1 # Concepts -The `stablestake` module in the Elys Network extends the basic staking capabilities by providing functionalities for borrowing and lending, managing interest rates, and handling debt effectively. This module aims to ensure a stable and efficient staking environment within the network. +The `stablestake` module in the Elys Network extends the basic staking capabilities by providing functionalities for borrowing and lending, managing interest rates, and handling debt effectively. This module aims to ensure a stable and efficient staking environment within the network. Additionally, users can bond and unbond their USDC to earn rewards from the interest paid by ongoing leveraged LP positions. diff --git a/x/stablestake/spec/02_mechanism.md b/x/stablestake/spec/02_mechanism.md new file mode 100644 index 000000000..c6fba0a12 --- /dev/null +++ b/x/stablestake/spec/02_mechanism.md @@ -0,0 +1,112 @@ + + +# Mechanism + +## Overview + +The StableStake module facilitates leveraged liquidity provision (LP) positions by allowing users to borrow funds against their collateral. This process involves interactions between the user, a stable stake pool, and an Automated Market Maker (AMM) pool. The module ensures efficient and secure fund management, enabling users to maximize their liquidity provisioning potential. Additionally, users can bond and unbond their USDC to earn rewards from the interest paid by ongoing leveraged LP positions. + +## Components + +### Symbols and Definitions + +- **Collateral**: The amount of assets provided by the user as security for the borrowed funds. +- **Borrowed Amount**: The funds provided by the stable stake pool for leverage. +- **Position Address**: The designated address handling position-specific funds. +- **AMM Pool**: The decentralized exchange pool where liquidity is provided. +- **Stable Stake Pool**: The source of borrowed funds for leverage. + +### Key Entities + +- **User**: The entity initiating the opening and closing of leveraged LP positions. +- **Position Owner**: The user who owns the collateral and manages the position. +- **StableStake Module**: The system managing the stable stake pool and the borrowed funds. +- **AMM Module**: The system managing the liquidity provision and trading in the AMM pool. +- **LeverageLP Module**: The module facilitating leveraged liquidity provision positions. + +## Workflow + +### 1. Opening a Leveraged LP Position + +#### Step 1: Initiate Position Opening + +- **Action**: User decides to open a leveraged LP position. +- **Trigger**: User sends a request to open a position. + +#### Step 2: Send Collateral Amount + +- **Action**: The user sends a collateral amount from their address to the position address. +- **Details**: + - **Source**: User's wallet (position owner) + - **Destination**: Position address + - **Amount**: Collateral specified by the user + +#### Step 3: Send Borrowed Amount + +- **Action**: The system sends the borrowed amount from the stable stake pool to the position address. +- **Details**: + - **Source**: Stable stake pool + - **Destination**: Position address + - **Amount**: Borrowed funds required for leverage + +#### Step 4: Join AMM Pool + +- **Action**: The system joins the AMM pool with the combined collateral and borrowed amounts. +- **Details**: + - **Source**: Position address + - **Destination**: AMM pool + - **Amount**: Collateral + Borrowed funds + +### 2. Closing a Leveraged LP Position + +#### Step 1: Initiate Position Closing + +- **Action**: User decides to close the leveraged LP position. +- **Trigger**: User sends a request to close the position. + +#### Step 2: Exit AMM Pool + +- **Action**: The system exits the AMM pool to retrieve both the collateral and borrowed amounts towards the position address. +- **Details**: + - **Source**: AMM pool + - **Destination**: Position address + - **Amount**: Collateral + Borrowed funds + +#### Step 3: Send Borrowed and Debts Amounts + +- **Action**: The system sends both borrowed and debt amounts from the position address to the stable stake pool. +- **Details**: + - **Source**: Position address + - **Destination**: Stable stake pool + - **Amount**: Borrowed funds + Accrued interest/debts + +#### Step 4: Return Remaining Amount + +- **Action**: The system sends the remaining amount back to the position owner. +- **Details**: + - **Source**: Position address + - **Destination**: User's wallet (position owner) + - **Amount**: Remaining collateral after settling the debt + +## Sequence of Actions + +### Bonding and Unbonding USDC + +- Bonding: Users can bond their USDC to the stable stake pool to earn rewards. The rewards are generated from the interest paid by users on their leveraged LP positions. +- Unbonding: Users can unbond their USDC from the stable stake pool, allowing them to retrieve their tokens along with any accrued rewards. + +### Opening Position + +1. User sends a request to open a leveraged LP position. +2. Collateral is transferred from the user's wallet to the position address. +3. Borrowed funds are transferred from the stable stake pool to the position address. +4. The position address joins the AMM pool with the total funds. + +### Closing Position + +1. User sends a request to close the leveraged LP position. +2. The position address exits the AMM pool, retrieving the collateral and borrowed amounts. +3. Borrowed and debt amounts are transferred from the position address to the stable stake pool. +4. Remaining collateral is sent back to the user's wallet. diff --git a/x/stablestake/spec/02_usage.md b/x/stablestake/spec/03_usage.md similarity index 98% rename from x/stablestake/spec/02_usage.md rename to x/stablestake/spec/03_usage.md index 7d9c8ee07..aae3c4177 100644 --- a/x/stablestake/spec/02_usage.md +++ b/x/stablestake/spec/03_usage.md @@ -1,5 +1,5 @@ # Usage diff --git a/x/stablestake/spec/03_keeper.md b/x/stablestake/spec/04_keeper.md similarity index 99% rename from x/stablestake/spec/03_keeper.md rename to x/stablestake/spec/04_keeper.md index 66c3d37c0..679b26ab1 100644 --- a/x/stablestake/spec/03_keeper.md +++ b/x/stablestake/spec/04_keeper.md @@ -1,5 +1,5 @@ # Keeper diff --git a/x/stablestake/spec/04_protobuf_definitions.md b/x/stablestake/spec/05_protobuf_definitions.md similarity index 99% rename from x/stablestake/spec/04_protobuf_definitions.md rename to x/stablestake/spec/05_protobuf_definitions.md index d53431ac5..65070b365 100644 --- a/x/stablestake/spec/04_protobuf_definitions.md +++ b/x/stablestake/spec/05_protobuf_definitions.md @@ -1,5 +1,5 @@ # Protobuf Definitions diff --git a/x/stablestake/spec/05_functions.md b/x/stablestake/spec/06_functions.md similarity index 99% rename from x/stablestake/spec/05_functions.md rename to x/stablestake/spec/06_functions.md index 0a79c1148..001e31710 100644 --- a/x/stablestake/spec/05_functions.md +++ b/x/stablestake/spec/06_functions.md @@ -1,5 +1,5 @@ # Functions diff --git a/x/stablestake/spec/README.md b/x/stablestake/spec/README.md index 359e13502..c62311785 100644 --- a/x/stablestake/spec/README.md +++ b/x/stablestake/spec/README.md @@ -3,10 +3,11 @@ ## Contents 1. **[Concepts](01_concepts.md)** -2. **[Usage](02_usage.md)** -3. **[Keeper](03_keeper.md)** -4. **[Protobuf Definitions](04_protobuf_definitions.md)** -5. **[Functions](05_functions.md)** +2. **[Mechanism](02_mechanism.md)** +3. **[Usage](03_usage.md)** +4. **[Keeper](04_keeper.md)** +5. **[Protobuf Definitions](05_protobuf_definitions.md)** +6. **[Functions](06_functions.md)** ## References