diff --git a/.gitignore b/.gitignore index d896d3bd..d94fc81d 100644 --- a/.gitignore +++ b/.gitignore @@ -28,5 +28,5 @@ # ignore visual studio code dev container config .devcontainer -# ignore build directory +# ignore build dir build \ No newline at end of file diff --git a/app/upgrades/v3/consts.go b/app/upgrades/v3/consts.go index 2000f358..38b8b689 100644 --- a/app/upgrades/v3/consts.go +++ b/app/upgrades/v3/consts.go @@ -2,6 +2,7 @@ package v3 import ( sdkmath "cosmossdk.io/math" + "github.com/sge-network/sge/app/upgrades" ) diff --git a/app/upgrades/v8/consts.go b/app/upgrades/v8/consts.go index 6c28f595..686ccb5f 100644 --- a/app/upgrades/v8/consts.go +++ b/app/upgrades/v8/consts.go @@ -6,8 +6,8 @@ import ( "github.com/sge-network/sge/app/upgrades" ) -// UpgradeName defines the on-chain upgrade name for the v1.6.1 upgrade. -const UpgradeName = "v1.6.1" +// UpgradeName defines the on-chain upgrade name for the v1.6.2 upgrade. +const UpgradeName = "v1.6.2" var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, diff --git a/app/upgrades/v8/upgrades.go b/app/upgrades/v8/upgrades.go index c6bbbb93..c9b38084 100644 --- a/app/upgrades/v8/upgrades.go +++ b/app/upgrades/v8/upgrades.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/sge-network/sge/app/keepers" "github.com/sge-network/sge/x/reward/types" ) @@ -17,42 +18,52 @@ func CreateUpgradeHandler( k *keepers.AppKeepers, ) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { - allCampaigns := k.RewardKeeper.GetAllCampaign(ctx) - promoters := make(map[string]struct{}) - for _, c := range allCampaigns { - c.CapCount = 0 // infinite cap for all campaigns - c.Pool.Withdrawn = sdkmath.ZeroInt() - k.RewardKeeper.SetCampaign(ctx, c) - promoters[c.Promoter] = struct{}{} - } + allPromoters := k.RewardKeeper.GetAllPromoter(ctx) + promoterUID := "f0630627-9e4e-48f3-8cd5-1422b46d2175" + if len(allPromoters) == 0 { + allCampaigns := k.RewardKeeper.GetAllCampaign(ctx) + promoters := make(map[string]struct{}) + for _, c := range allCampaigns { + c.CapCount = 0 // infinite cap for all campaigns + c.Pool.Withdrawn = sdkmath.ZeroInt() + k.RewardKeeper.SetCampaign(ctx, c) + promoters[c.Promoter] = struct{}{} + } - promoterAddresses := []string{} - for addr := range promoters { - promoterAddresses = append(promoterAddresses, addr) - } - sort.Strings(promoterAddresses) - - if len(promoterAddresses) > 0 { - promoterUID := "f0630627-9e4e-48f3-8cd5-1422b46d2175" - k.RewardKeeper.SetPromoter(ctx, types.Promoter{ - Creator: promoterAddresses[0], - UID: promoterUID, - Addresses: promoterAddresses, - Conf: types.PromoterConf{ - CategoryCap: []types.CategoryCap{ - {Category: types.RewardCategory_REWARD_CATEGORY_SIGNUP, CapPerAcc: 1}, - }, - }, - }) + promoterAddresses := []string{} + for addr := range promoters { + promoterAddresses = append(promoterAddresses, addr) + } + sort.Strings(promoterAddresses) - for _, addr := range promoterAddresses { - k.RewardKeeper.SetPromoterByAddress(ctx, types.PromoterByAddress{ - PromoterUID: promoterUID, - Address: addr, + if len(promoterAddresses) > 0 { + promoterUID := promoterUID + k.RewardKeeper.SetPromoter(ctx, types.Promoter{ + Creator: promoterAddresses[0], + UID: promoterUID, + Addresses: promoterAddresses, + Conf: types.PromoterConf{ + CategoryCap: []types.CategoryCap{ + {Category: types.RewardCategory_REWARD_CATEGORY_SIGNUP, CapPerAcc: 1}, + }, + }, }) + + for _, addr := range promoterAddresses { + k.RewardKeeper.SetPromoterByAddress(ctx, types.PromoterByAddress{ + PromoterUID: promoterUID, + Address: addr, + }) + } } } + allByCat := k.RewardKeeper.GetAllRewardsOfReceiverByPromoterAndCategory(ctx) + for _, rc := range allByCat { + k.RewardKeeper.RemoveRewardOfReceiverByPromoterAndCategory(ctx, "", rc) + k.RewardKeeper.SetRewardOfReceiverByPromoterAndCategory(ctx, promoterUID, rc) + } + return mm.RunMigrations(ctx, configurator, fromVM) } } diff --git a/docs/specs/Bet/01_Overview.md b/docs/specs/Bet/01_Overview.md index be87ee09..e1b32178 100644 --- a/docs/specs/Bet/01_Overview.md +++ b/docs/specs/Bet/01_Overview.md @@ -1,5 +1,16 @@ # **Overview** -The Bet module is responsible for receiving and processing requests to wager and settle bets. In the case of wagering, it validates the request and places the bet. +The **Bet module** handles requests related to betting and bet settlement. Let's break it down: -For the settlement, blockchain automatically queries resolved markets then for each of these markets, checks the result of the market, determines the bet result, and settles the bet using `orderbook` module. +- **Wagering**: + - When a user places a bet, the Bet module validates the request. + - It then processes the bet and records it. + +- **Settlement**: + - After a market is resolved, the blockchain automatically queries the results. + - For each market, the Bet module: + - Checks the outcome. + - Determines the bet result. + - Settles the bet using the `orderbook` module. + +In summary, the Bet module ensures smooth betting interactions and accurate settlement based on market outcomes. diff --git a/docs/specs/Bet/02_Concepts.md b/docs/specs/Bet/02_Concepts.md index ce8f5107..9553d1dc 100644 --- a/docs/specs/Bet/02_Concepts.md +++ b/docs/specs/Bet/02_Concepts.md @@ -1,52 +1,70 @@ # **Concepts** -Bet module is tasked with placement and settlement of the bets. the user can place bet on a same market multiple times with different or equal odds through commandline or singing and broadcasting the bet placement message. +The **Bet module** is responsible for handling the placement and settlement of bets. Users can place bets on the same market multiple times, either with different or equal odds, using the command line or by singing and broadcasting the bet placement message. -> Wagering will be done using a ticket containing odds info signed by a trusted source. Verifying this ticket will be done in the placement state itself. -> Bet amount can not be less than a minimum amount which is defined for each market. A module parameter is used for this purpose. -> Also, a betting fee has been defined for each market, A module parameter is used for this purpose. +Here are some key points about the betting process: + +1. **Wagering and Ticket Verification**: + - Wagering is facilitated through a ticket that contains odds information, signed by a trusted source. + - The verification of this ticket occurs during the placement state itself. + +2. **Minimum Bet Amount**: + - Each market defines a minimum bet amount. + - Users cannot place bets below this minimum threshold. + - A module parameter controls this requirement. + +3. **Betting Fee**: + - For each market, a specific betting fee has been established. + - Again, a module parameter governs this fee. --- -Before accepting bet some validation should take place: +**Before Accepting a Bet, Validation Steps:** + +1. **Market-Level Validation:** + - Ensure the market is active for bet placement. + - Verify that the market is neither resolved nor canceled. + - Confirm that the bet amount (after deducting the betting fee) meets the minimum allowed bet amount. -- Market level validation: - - Market is active for bet placement. - - Market is not already resolved or canceled. - - Bet amount (deducted by betting fee) is not less than the minimum allowed bet amount. -- Bet level validation: - - Provided UUID is valid. - - Odds Value and the validations according to the American, British and decimal odds. - - Check if the max loss multiplier is positive and less than 1. -- OVM level validation: - - All data provided in placement request is valid e.g. odds value. -- KYC Validation: - - If Ignore is false in bet ticket payload, then the status of kyc approval should be true and tx signer and kyc id should be same for a bet to be placed. - - If Ignore is true in bet ticket payload, then kyc validation is not required and bet can be placed without kyc check. +2. **Bet-Level Validation:** + - Validate the provided UUID. + - Check odds values and apply validations based on American, British, and decimal odds. + - Ensure the max loss multiplier is positive and less than 1. -Wager Assumptions: +3. **OVM-Level Validation:** + - Validate all data provided in the placement request, including odds values. -- For bet placement user can raise a request to place a single bet, it can be done for a single bet only. -- When a user is raising a transaction to place a bet, the creator of the transaction is the owner of the bet. +4. **KYC Validation:** + - If the "Ignore" flag in the bet ticket payload is false: + - Verify that KYC approval status is true. + - Confirm that the transaction signer and KYC ID match for the bet to be placed. + - If the "Ignore" flag is true, KYC validation is not required, and the bet can proceed without further checks. -After a bet is accepted: +**Wager Assumptions:** -- Bet amount transfer to the `orderbook_liquidity_pool` module account this is done by the `orderbook` module. -- Betting fee will be transferred to the `bet_fee_collector` module account. this is done by the `orderbook` module. -- Bet fulfillments are being processed by `orderbook` module in the `ProcessWager` keeper's method. +- Users can request to place a single bet only. +- The creator of the transaction is considered the owner of the bet. + +**After Bet Acceptance:** + +- The bet amount is transferred to the `orderbook_liquidity_pool` module account by the `orderbook` module. +- Betting fees are transferred to the `bet_fee_collector` module account, also managed by the `orderbook` module. +- Bet fulfillments are processed by the `orderbook` module using the `ProcessWager` keeper's method. ## Supported Odds Types -> Note: Let bet_amount be 3564819 +**Note:** Let `bet_amount` be 3,564,819. -- ***Decimal(European):*** Calculated as `bet_amount * oddsValue` ex. `3564819 * 1.29 = 4598616.51`. -- ***Fractional(British):*** Calculated as `bet_amount + (bet_amount * fraction)` ex. `3564819 + (3564819 * 2/7) = 4583338.71`. -- ***Moneyline(American):*** Calculated as: - - Positive odds value: `bet_amount + (bet_amount * |oddsValue/100|)` ex. `3564819 + 3564819 * |+350/100| = 16041685.50` the result will be rounded to floor. - - Negative odds value: `bet_amount + (bet_amount * |100/oddsValue|)` ex. `3564819 + 3564819 * |100/-350| = 4583338.71` the result will be rounded to floor. +- **Decimal (European):** Calculated as `bet_amount * oddsValue`. For example, `3,564,819 * 1.29 = 4,598,616.51`. +- **Fractional (British):** Calculated as `bet_amount + (bet_amount * fraction)`. For instance, `3,564,819 + (3,564,819 * 2/7) = 4,583,338.71`. +- **Moneyline (American):** Calculated as follows: + - For positive odds value: `bet_amount + (bet_amount * |oddsValue/100|)`. For instance, with odds of +350, `3,564,819 + 3,564,819 * |350/100| = 16,041,685.50` (rounded down). + - For negative odds value: `bet_amount + (bet_amount * |100/oddsValue|)`. For example, with odds of -350, `3,564,819 + 3,564,819 * |100/-350| = 4,583,338.71` (rounded down). ### Precision -Some of the Online Calculators round the division result to two-digit precision in Fractional and Moneyline calculations. In other words, these online calculators try to convert Moneyline and Fractional odds to Decimal odds and then calculate the payout according to the calculated rounded decimal value. This approach makes a big difference in the resulting payout. SGE-Network is accepting bets with usge that may have a high value in the market. For this kind of value, it is better to have a high-precision calculation in the blockchain code. +Some online calculators employ a two-digit precision when rounding division results in Fractional and Moneyline calculations. Specifically, these tools convert Moneyline and Fractional odds to Decimal odds and then compute the payout based on the rounded decimal value. This approach significantly impacts the resulting payout. + +SGE-Network currently accepts bets with the `usge` currency, which may have substantial value in the market. For such high-value scenarios, it is advisable to perform high-precision calculations within the blockchain code. -> Note: The final calculated payout amounts are rounded to 2 digit float values, so we have a small portion of lost benefits/payouts. +> **Note:** The final calculated payout amounts are rounded to two-digit float values, resulting in a slight loss of benefits or payouts. diff --git a/docs/specs/Bet/03_Accounts.md b/docs/specs/Bet/03_Accounts.md index d1f5b4fd..56a972f2 100644 --- a/docs/specs/Bet/03_Accounts.md +++ b/docs/specs/Bet/03_Accounts.md @@ -1,16 +1,16 @@ -# **Accounts** +# **Account Details** -There is one account in the Bet module. +Within the Bet module, there exists a single account: -- Betting Fee Collector: This account holds the betting fee transferred from the bettor to the `bet_fee_collector` module account. +- **Betting Fee Collector**: This account receives the betting fee transferred from the bettor to the `bet_fee_collector` module account. -During bet placement, betting fee is transferred from the bettor's account to the bet module account in the Bet module. +When placing a bet, the betting fee is moved from the bettor's account to the bet module account in the Bet module. ## Wager Transfer -The bet amount (deducted by betting fee) is transferred to the `orderbook_liquidity_pool` module account in `orderbook` module. +The bet amount (after deducting the betting fee) is then transferred to the `orderbook_liquidity_pool` module account within the `orderbook` module. ## Settlement Transfer -- if the user is winner, the bet amount and payout profit will be transferred from `orderbook_liquidity_pool` module account to the winner's account. -- If the user is loser, the bet amount and fee will not go back to bettor's account. +- If the user is a winner, both the bet amount and the payout profit are transferred from the `orderbook_liquidity_pool` module account to the winner's account. +- However, if the user is a loser, the bet amount and fee remain with the bettor and do not return to their account. diff --git a/docs/specs/Bet/04_State.md b/docs/specs/Bet/04_State.md index 0110a758..265a6167 100644 --- a/docs/specs/Bet/04_State.md +++ b/docs/specs/Bet/04_State.md @@ -2,24 +2,23 @@ ## **KVStore** -State in bet module is defined by its KVStore. This KVStore has five prefixes: +The state in the bet module is defined by its **KVStore**. This KVStore consists of five prefixes: -1. All bets of a certain creator, using this pattern, blockchain is able to return list of all bets, bets of a certain creator and a single bet. The key prefix is created dynamically using this combination: `BetListPrefix`+`{Creator Address}`+`{Secuential Bet ID}` - -2. Map of BetID and BetUID. this helps to get corresponding ID of the bet by issuing the UID. The keys are UIDs of bets and the values are sequencial generated IDs by blockchain. -3. Pending bets of a certain Market to help batch settlement. -4. Settled bets of a block height to keep track of the settled bets for the oracle services. -5. Bet statistics that contains the count of the total bets used to create next sequencial BetID. +1. **All Bets of a Certain Creator**: Using this pattern, the blockchain can retrieve a list of all bets, bets of a specific creator, and individual bets. The key prefix is dynamically created by combining `BetListPrefix`, the `{Creator Address}`, and the `{Sequential Bet ID}`. +2. **Mapping of BetID to BetUID**: This mapping helps retrieve the corresponding bet ID by issuing the UID. The keys represent UIDs of bets, and the values are sequentially generated IDs by the blockchain. +3. **Pending Bets of a Certain Market**: This prefix assists with batch settlement. +4. **Settled Bets of a Block Height**: Used to track settled bets for oracle services. +5. **Bet Statistics**: Contains the total count of bets, which is used to create the next sequential BetID. The bet model in the Proto files is as below: ## **Params** -1. `batch_settlement_count`: is the count of bets to be automatically settlement in end-blocker. -2. `max_bet_by_uid_query_count`: is the max count of bets to be returned in the bets by uids query. -3. `constraints` contains criteria of the bet placement. - - `min_amount` minimum bet amount while placement. - - `fee` bet fee amount payable by bettor. +1. **`batch_settlement_count`** represents the number of bets that will be automatically settled during the end-blocker process. +2. **`max_bet_by_uid_query_count`** specifies the maximum number of bets to be returned in the query for bets by user IDs. +3. **`constraints`** section includes the criteria for placing bets: + - **`min_amount`**: This is the minimum bet amount required during placement. + - **`fee`**: The bet fee amount payable by the bettor. ```proto // Params defines the parameters for the module. @@ -40,7 +39,7 @@ message Params { ## **Constraints** -Holds bet placement constraints of the bet module. +Holds wager constraints of the bet module. ```proto // Constraints is the bet constrains type for the bets diff --git a/docs/specs/Bet/05_State_Transitions.md b/docs/specs/Bet/05_State_Transitions.md index 23823371..1c58cd43 100644 --- a/docs/specs/Bet/05_State_Transitions.md +++ b/docs/specs/Bet/05_State_Transitions.md @@ -1,14 +1,12 @@ # **State Transitions** -This section defines the state transitions of the bet module's KVStore in all scenarios: +## **Wager State Transitions** -## **Wager** +When processing the wager, the following state transitions occur in the `Bet` module's KVStore: -When this is processed: - -- If the ticket is valid a new bet will be created with the given data and will be added to the `Bet` module state. -- The pending bet, ID map and statistics will update accordingly. -- `orderbook` module bet placement processor will calculate and transfer bet amount and bet fee to the corresponding module accounts. +1. If the ticket is valid, a new bet is created using the provided data and added to the `Bet` module state. +2. The pending bet, ID map, and statistics are updated accordingly. +3. The `orderbook` module's bet placement processor calculates and transfers the bet amount and fee to the corresponding module accounts. ```go newBet := &types.Bet{ @@ -29,44 +27,45 @@ newBet := &types.Bet{ --- -## **Settle bet** +## **Bet Settlement Process** -When this is processed: +When processing a bet: -- If corresponding market is aborted or canceled, the bet will be updated in the `Bet` module state as below: +1. If the corresponding market is aborted or canceled, update the `Bet` module state as follows: ```go bet.Result = types.Bet_RESULT_REFUNDED bet.Status = types.Bet_STATUS_SETTLED ``` - and the `RefundBettor` method of the `orderbook` module will be called to refund the bet amount and bet fee. + Additionally, invoke the `RefundBettor` method from the `orderbook` module to refund the bet amount and bet fee. -- Resolve the bet result based on the market result, and update field `Result` to indicate won or lost, and field `Status` to indicate result is declared. For Example: +2. Determine the bet result based on the market outcome. Update the `Result` field to indicate whether the bet was won or lost, and set the `Status` field to reflect that the result has been declared. For example: ```go bet.Result = types.Bet_RESULT_WON // or types.Bet_RESULT_LOST bet.Status = types.Bet_STATUS_RESULT_DECLARED ``` -- Call `orderbook` module `BettorLoses` or `BettorWins` methods to unlock fund and payout user based on the bet's result, and update the bet's `Status` field to indicate it is settled: +3. Call the `BettorLoses` or `BettorWins` methods from the `orderbook` module to unlock funds and pay out users based on the bet result. Update the bet's `Status` field to indicate that it has been settled: ```go bet.Status = types.Bet_STATUS_SETTLED ``` -- If the market result is declared, the `WithdrawBetFee` method of the `orderbook` module is being called and transfers the bet fee to the market creator's account balance. -- Store the updated bet in the state. +4. If the market result is declared, invoke the `WithdrawBetFee` method from the `orderbook` module to transfer the bet fee to the market creator's account balance. + +5. Finally, store the updated bet information in the state. --- -## **Batch bet settlement** +## Batch Bet Settlement -Batch bet settlement happens in the end-blocker of the bet module: +Batch bet settlement occurs during the final block of the bet module. Follow these steps: -1. Get resolved markets that have the unsettled bets. - - for each market: - 1. Settle the bets one by by querying the market bets. - 2. Remove the resolved market from the list if there is no more active bet. - 3. Call orderbook's win/lose methods to transfer the appropriate amounts. -2. Check the `BatchSettlementCount` parameter of bet module and let the rest of bets for the nex block. +1. Identify resolved markets that still have unsettled bets. + - For each market: + 1. Settle the bets by querying the market's bet data. + 2. If there are no more active bets in the market, remove it from the list. + 3. Use the orderbook's win/lose methods to transfer the appropriate amounts. +2. Verify the `BatchSettlementCount` parameter in the bet module and handle the remaining bets in the next block. diff --git a/docs/specs/Bet/06_Messages.md b/docs/specs/Bet/06_Messages.md index 22e1ff3b..c3adb25c 100644 --- a/docs/specs/Bet/06_Messages.md +++ b/docs/specs/Bet/06_Messages.md @@ -1,7 +1,6 @@ # **Messages** -In this section, we describe the processing of the Bet messages. the transaction message -handler endpoints is as follows +In this section, we delve into the handling of Bet messages. The endpoints for transaction message handlers are outlined below. ```proto // Msg defines the Msg service. @@ -13,7 +12,7 @@ service Msg { ## **MsgWager** -Within this message, the user specifies the bet information they wish to place. +In this message, users provide the details of the bet they want to place. ```proto // MsgWager defines a message to place a bet with the given data @@ -71,27 +70,29 @@ message MsgWagerResponse { WagerProps props = 1; } } ``` -### **Wager Failure cases** - -The transaction will fail if: - -- Basic validation fails: - - Invalid creator address - - Empty or invalid bet UID - - Empty amount - - Non positive amount - - Empty or invalid ticket (containing space) -- Provided bet UID is already set -- Empty or invalid odds UID in ticket -- Empty, negative or invalid odds value in ticket -- There is no any market with the given marketUID -- The market is not active for accepting bet (it's not active or status in not `PENDING`) -- The market has expired -- The market does not contain the selected odds -- Bet amount is less than minimum allowed amount -- The creator address is not valid -- There is an error in `ProcessWager` in `orderbook` module - -### **What Happens if bet placement fails** - -- The input data will not be stored in the `Bet` module and a meaningfull error will be returned to the client. +### **Possible Reasons for Wager Failure** + +The transaction may fail due to the following reasons: + +1. **Basic Validation Failures**: + - Invalid creator address + - Empty or invalid bet UID + - Empty amount + - Non-positive amount + - Empty or invalid ticket (containing spaces) + +2. **Specific Conditions**: + - Provided bet UID is already set + - Empty or invalid odds UID in the ticket + - Empty, negative, or invalid odds value in the ticket + - No market exists with the given market UID + - The market is not active for accepting bets (status is not `PENDING`) + - The market has expired + - The market does not contain the selected odds + - Bet amount is less than the minimum allowed amount + - The creator address is not valid + - An error occurs in the `ProcessWager` function within the `orderbook` module + +### **Handling Failed Bet Placement** + +If bet placement fails, the input data will not be stored in the `Bet` module. Instead, a meaningful error message will be returned to the client. diff --git a/docs/specs/Bet/07_Events.md b/docs/specs/Bet/07_Events.md index 793d7e59..bf30521d 100644 --- a/docs/specs/Bet/07_Events.md +++ b/docs/specs/Bet/07_Events.md @@ -1,6 +1,6 @@ # **Events** -The Bet module emits the following events +The **Bet module** generates the subsequent events: ## *MsgWager* diff --git a/docs/specs/House/01_Overview.md b/docs/specs/House/01_Overview.md index 3f304ac6..f4964178 100644 --- a/docs/specs/House/01_Overview.md +++ b/docs/specs/House/01_Overview.md @@ -1,3 +1,3 @@ # **Overview** -The House module facilitates users to participate as a house for a specific market. +The **House module** enables users to **act as a representative** for a particular market. diff --git a/docs/specs/House/02_Concepts.md b/docs/specs/House/02_Concepts.md index 4f792548..a2157be4 100644 --- a/docs/specs/House/02_Concepts.md +++ b/docs/specs/House/02_Concepts.md @@ -1,20 +1,16 @@ # **Concepts** -The House is tasked with accepting deposits from the users and faciliatates them to act as a house -for a specific market for a small amount of fees. A portion of these fees will be consumed to cover -the transaction costs associated with posting/resolving markets. +The House serves as a platform for accepting user deposits and acts as a facilitator for specific markets, charging nominal fees. A portion of these fees covers transaction costs related to market posting and resolution. -The user can withdraw the deposited tokens at any point of time. The tokens that has been -used to accept bets for the house, along with the unused tokens if not withdrawn, will be settled at the -resolution of the market. +Users can withdraw their deposited tokens at any time. Tokens used for accepting bets on behalf of the house, along with any unused tokens, are settled upon market resolution. ## **KYC Validation** -- If Ignore is false in deposit/withdraw ticket payload, then the status of kyc approval should be true and tx signer and kyc id should be same for a deposit/withdraw to be set. -- If Ignore is true in deposit/withdraw ticket payload, then kyc validation is not required and deposit/withdraw can be happen without kyc check. +- When `Ignore` is set to false in the deposit/withdraw ticket payload, KYC approval status must be true, and the transaction signer's KYC ID should match the deposit/withdrawal request. +- If `Ignore` is true, KYC validation is not required, allowing deposit/withdrawal without further checks. ## **Authorization** -Authorization is being validated in each deposit and withdraw request that includes `depositor_address` in the ticket, This can be useful if and account has willing to deposit/withdraw on behalf of another accounts. -To grant deposit/withdraw permission, granter needs to grant permission using the `authz` module of the Cosmos-SDK. -After each deposit or withdrawal success, the spend or withdraw limit is being updated. If the spend limit gets zero, the grant record will remove from the authz state completely. +Authorization is verified for each deposit and withdrawal request that includes the `depositor_address` in the ticket. This feature is useful when an account wishes to deposit/withdraw on behalf of other accounts. +To grant deposit/withdrawal permissions, the granter utilizes the `authz` module in the Cosmos-SDK. +After each successful deposit or withdrawal, the spend or withdrawal limit is updated. If the spend limit reaches zero, the grant record is completely removed from the authz state. diff --git a/docs/specs/House/03_State.md b/docs/specs/House/03_State.md index 074a83a5..6dedb226 100644 --- a/docs/specs/House/03_State.md +++ b/docs/specs/House/03_State.md @@ -2,8 +2,8 @@ ## **Params** -1. `min_deposit`: is the minimum allowed amount of deposit. -2. `house_participation_fee`: os the percentage of deposit amount to be paid as deposit fee. +1. `min_deposit`: This represents the smallest allowable deposit amount. +2. `house_participation_fee`: This fee is calculated as a percentage of the deposit amount and is paid as part of the deposit. ```proto // Params define the parameters for the house module. @@ -30,7 +30,7 @@ message Params { ## **Deposit** -The deposit keeps track of the deposits made by the users who want to participate as house. +The deposit monitors the contributions made by users who wish to participate as house members. ```proto // Deposit represents the deposit against a market held by an account. @@ -98,7 +98,7 @@ message Deposit { ## **Withdrawal** -The withdrawal keeps track of the withdrawals made by the depositor accounts. +The withdrawal system monitors the withdrawals initiated by depositor accounts. ```proto // Withdrawal represents the withdrawal against a deposit. diff --git a/docs/specs/House/04_State_Transitions.md b/docs/specs/House/04_State_Transitions.md index b1aeb34f..511eb143 100644 --- a/docs/specs/House/04_State_Transitions.md +++ b/docs/specs/House/04_State_Transitions.md @@ -1,17 +1,16 @@ # **State Transitions** -This section defines the state transitions of the house module's KVStore in all scenarios: +This section outlines the state transitions within the house module's KVStore across various scenarios: -## **Despoit** +## **Deposit** -Validations before modifiying the state: +Before modifying the state, the following validations are performed: -- If the sanity checks for making a deposit passes -- If authorization grant found for the depositor address and creator -- If the authorization spend limit exceeded. +1. If the sanity checks for making a deposit pass. +2. If authorization grants are found for both the depositor address and creator. +3. If the authorization spend limit has not been exceeded. -a new deposit will be created with the given data and will be added to the `House` module state. -the order book participation will create in the background and its index will be assigned to the deposit. +Upon meeting these conditions, a new deposit is created with the provided data and added to the `House` module state. Additionally, an order book participation is created in the background, and its index is assigned to the deposit. ### **Input data** @@ -33,13 +32,13 @@ newDeposit := &types.Deposit{ ## **Withdraw** -Validations before modifiying the state: +Before modifying the state, the following validations will be performed: -- If the amount is withdrawable -- If authorization grant found for the depositor address and creator -- If the authorization withdraw limit exceeded. +1. Check if the amount is withdrawable. +2. Verify if an authorization grant exists for both the depositor address and the creator. +3. Ensure that the authorization withdraw limit has not been exceeded. -The following changes will be made to the deposit +The deposit will be updated based on these criteria. ```go deposit.WithdrawalCount++ diff --git a/docs/specs/House/05_Messages.md b/docs/specs/House/05_Messages.md index b3d64893..2f3d2880 100644 --- a/docs/specs/House/05_Messages.md +++ b/docs/specs/House/05_Messages.md @@ -1,10 +1,10 @@ # **Messages** -In this section, we describe the processing of the House messages. +Within this section, we outline the handling of House messages. ## **MsgDeposit** -Within this message, the user specifies the deposit information they wish to make. +In this message, the user outlines the deposit details they want to provide. ```proto // Msg defines the house Msg service. @@ -57,7 +57,7 @@ message MsgDepositResponse { ## **Deposit Ticket Payload** -This ticket is being used for validating the KYC and authorization. +This ticket serves the purpose of KYC validation and authorization. ```proto // DepositTicketPayload indicates data of the deposit ticket. @@ -72,19 +72,19 @@ message DepositTicketPayload { ### **Deposit Failure cases** -The transaction will fail if: +The transaction will not succeed under the following conditions: -- Basic validation fails: - - Invalid creator address - - Empty or invalid market uid - - Invalid amount - - No Authorization grant found for the grantee (creator) and granter (depositor) +- If basic validation encounters issues: + - An invalid creator address + - An empty or invalid market UID + - An invalid amount + - No authorization grant is found for the grantee (creator) and granter (depositor). --- ## **MsgWithddraw** -Within this message, the user provides a deposit UID they wish to make a withdrawal against. +In this message, the user specifies a deposit UID against which they intend to make a withdrawal. ```proto // Msg defines the Msg service. @@ -146,7 +146,7 @@ message MsgWithdrawResponse { ## **Withdraw Ticket Payload** -This ticket is being used for validating the KYC and authorization. +This ticket serves the purpose of KYC validation and authorization. ```proto // WithdrawTicketPayload indicates data of the withdrawal ticket. diff --git a/docs/specs/House/06_Events.md b/docs/specs/House/06_Events.md index 96521f88..8889b7f8 100644 --- a/docs/specs/House/06_Events.md +++ b/docs/specs/House/06_Events.md @@ -1,6 +1,6 @@ # **Events** -The House module emits the following events +The **House module** emits the subsequent events. ## *MsgDeposit* diff --git a/docs/specs/Market/01_Overview.md b/docs/specs/Market/01_Overview.md index 6762c478..bba9b3fe 100644 --- a/docs/specs/Market/01_Overview.md +++ b/docs/specs/Market/01_Overview.md @@ -1,9 +1,8 @@ # **Overview** -The `market` module is responsible for -*Creating*, *Updating*, *Reading* and *Resolution* of the markets. +The **Market Module** is responsible for: -This module will validate the markets and register them in the market module state, -Users will be able to view all of the active markets and place bets/become house using the `Bet` and `House` modules. - -Once the market is recorded on the chain It will make it tamper-proof and can always be cross validated. +- **Creating**, **Updating**, **Reading**, and **Resolution** of the markets. +- This module validates the markets and registers them in the market module state. +- Users can view all active markets and place bets or become house participants using the **Bet** and **House** modules. +- Once the market is recorded on the chain, it becomes tamper-proof and can always be cross-validated. diff --git a/docs/specs/Market/02_State.md b/docs/specs/Market/02_State.md index cfb9790a..09b31d92 100644 --- a/docs/specs/Market/02_State.md +++ b/docs/specs/Market/02_State.md @@ -2,7 +2,7 @@ ## **Params** -The market module does not have any parameters. +The **Market Module** does not have any parameters. --- @@ -59,25 +59,16 @@ message Market { } ``` -**UID**: universal unique market ID. - -**StartTS**: Timestamp when this market will start. - -**EndTS**: Timestamp when this market will be over. - -**Odds**: Array of all the associated values of type ***Odds*** with this market. - -**WinnerOddsUids**: Array of all the Odds Uids which won this market, this would be a ***subset*** of the above provided OddsUidsArray. - -**Status**: current state of the market. - -**ResolutionTS**: Timestamp when the market came to a resolution i.e. we received a resolution request for an market. - -**Creator**: Account responsible to create this market. - -**Meta**: Human-Readable data of the market. - -**BookID** The ID of the created order book +- **UID**: Universal Unique Market ID. +- **Start Timestamp (`start_ts`)**: Indicates when this market will begin. +- **End Timestamp (`end_ts`)**: Indicates when this market will conclude. +- **Odds (`odds`)**: An array containing all associated values of type ***Odds*** for this market. +- **Winner Odds UIDs (`winner_odds_uids`)**: A subset of the above-provided Odds UIDs, representing the winning outcomes for this market. +- **Market Status (`status`)**: The current state of the market. +- **Resolution Timestamp (`resolution_ts`)**: The timestamp when the market was resolved (e.g., upon receiving a resolution request). +- **Market Creator (`creator`)**: The account responsible for creating this market. +- **Market Metadata (`meta`)**: Human-readable data associated with the market. +- **Order Book ID (`book_uid`)**: The unique identifier for the created order book. --- @@ -127,7 +118,7 @@ message Odds { ## **Statistics** -Keeps track of statistics of the market module including the resolved unsettled markets. +Keeps track of statistics of the **Market Module** including the resolved unsettled markets. ```proto // MarketStats holds statistics of the market diff --git a/docs/specs/Market/03_Messages.md b/docs/specs/Market/03_Messages.md index 69214648..352652bd 100644 --- a/docs/specs/Market/03_Messages.md +++ b/docs/specs/Market/03_Messages.md @@ -1,6 +1,6 @@ # **Messages** -The Market module exposes the following services: +The **Market Module** exposes the following services: - AddMarket - ResolveMarket @@ -19,7 +19,7 @@ service Msg { ## **MsgAdd** -This message is used to add new market to the chain +This message is used to add new market to the blockchain state. ```proto message MsgAdd { @@ -99,7 +99,7 @@ message MarketAddTicketPayload { ## **MsgUpdate** -This message is used to update already existent markets on the chain +This message serves to provide updates to existing markets within the blockchain's state. ```proto // MsgUpdate is the message type for updating market data. @@ -157,7 +157,7 @@ message MarketUpdateTicketPayload { ## **MarketResponse** -This is the common response to all the messages +This is the common response to all the messages. ```proto // MsgAddResponse response for adding market. @@ -173,7 +173,7 @@ message MsgAddResponse { ## **MsgResolve** -This message is used to resolve already existent markets on the chain +This message is utilized to address existing markets within the blockchain state. ```proto // MsgResolve is the message type for resolving a market. diff --git a/docs/specs/Market/04_State_Transitions.md b/docs/specs/Market/04_State_Transitions.md index e799d0e3..11064aa0 100644 --- a/docs/specs/Market/04_State_Transitions.md +++ b/docs/specs/Market/04_State_Transitions.md @@ -1,21 +1,19 @@ # **State Transitions** -This section defines the state transitions of the `market` module state in all scenarios: +This section outlines the state transitions for the `market` module across various scenarios: -## **Add Market** +## **Adding a Market** -Validations: +**Validations:** -- Validate the creator address and validate the ticket format. -- Call the OVM module to validate the ticket internals and to retrieve the - contents of the ticket. -- If the ticket is valid, check if the market already exists. +- Verify the creator's address and validate the ticket format. +- Utilize the OVM module to validate the ticket internals and retrieve the ticket's contents. +- If the ticket is valid, check whether the market already exists. -Modifications: +**Modifications:** -- If the market does not already exist, a new market should be - created with the given data and will be added to the module state. -- Initiate order book for the market. +- If the market does not exist, create a new market with the provided data and add it to the module state. +- Initialize the order book for the market. ```go newMarket := &type.Market{ @@ -34,37 +32,34 @@ newMarket := &type.Market{ --- -## **Update Market** +## **Updating a Market** -Validations: +**Validations:** -- Validate the creator address and validate the ticket format. -- Call the OVM module to validate the ticket internals and to retrieve the - contents of the ticket. -- If the ticket is valid, check that the market already exists or not. -- The market status should be active or inactive to be updatable, if not -returns appropriate error. +- Validate the creator's address and verify the ticket format. +- Use the OVM module to validate the ticket internals and retrieve the ticket's contents. +- If the ticket is valid, check whether the market already exists. +- Ensure that the market status is either active or inactive for it to be updatable; otherwise, return an appropriate error. -Modifications: +**Modifications:** -- Then update the market in the module state. +- Update the market in the module state. --- -## **Resolve Market** +## **Resolving a Market** -Validations: +**Validations:** -- Validate the creator address and validate the ticket format. -- Call the OVM module to validate the ticket internals and to retrieve the - contents of the ticket. -- If the ticket is valid, check that the market already exist or not. -- The market should exist and the status should be active otherwise proper error returned. +- Validate the creator's address and verify the ticket format. +- Leverage the OVM module to validate the ticket internals and retrieve the ticket's contents. +- If the ticket is valid, check whether the market exists. +- The market must exist, and its status should be active; otherwise, return an appropriate error. -Modifications: +**Modifications:** -- Then resolve the market and set in the module state. -- Modify list of resolved markets and add newly resolved. +- Resolve the market and update it in the module state. +- Adjust the list of resolved markets by adding the newly resolved ones. ```go resolvedMarket := types.ResolutionMarket{ diff --git a/docs/specs/Market/05_Events.md b/docs/specs/Market/05_Events.md index 8301ca84..e1d21b2c 100644 --- a/docs/specs/Market/05_Events.md +++ b/docs/specs/Market/05_Events.md @@ -1,6 +1,6 @@ # **Events** -The Market module emits the following events: +The **Market Module** emits the following events: ## *MsgAdd* diff --git a/docs/specs/Mint/01_Overview.md b/docs/specs/Mint/01_Overview.md index a3fb94b7..43716ff7 100644 --- a/docs/specs/Mint/01_Overview.md +++ b/docs/specs/Mint/01_Overview.md @@ -1,3 +1,3 @@ # **Overview** -The `mint` module is responsible for minting tokens to reward validators and delegators for helping secure the chain. The `mint` module is responsible for the on-chain inflation rate manipulation. +The **Mint Module** plays a crucial role in creating new tokens to reward validators and delegators who contribute to the security of the blockchain. Additionally, the **Mint Module** handles the manipulation of the on-chain inflation rate. diff --git a/docs/specs/Mint/02_Concepts.md b/docs/specs/Mint/02_Concepts.md index 8c09cdb5..9de62526 100644 --- a/docs/specs/Mint/02_Concepts.md +++ b/docs/specs/Mint/02_Concepts.md @@ -1,14 +1,13 @@ # **Concepts** -Unlike the default `mint` Module of Cosmos-SDK which can vary the inflation rate dynamically based on the ratio of bonded and unbonded tokens at any point in time, the `mint` module of the SGE-Network chain follows a strict regime of inflation rates defined as phases +In contrast to the default **Mint Module** in Cosmos-SDK, which dynamically adjusts the inflation rate based on the ratio of bonded and unbonded tokens, the **Mint Module** of the SGE-Network chain adheres to a strict regime of inflation rates defined as **phases**. -Phases are nothing but specific discreet time frames during which a certain inflation rate holds. Phases have two components: +These phases represent discrete time frames during which a specific inflation rate remains constant. Each phase has two key components: -- duration: The duration is defined as the year_coefficient. It defines the time in years for which a phase will hold. For example a yearcoefficient of 0.75 means that the phase will last for 9 months, that is, 3/4th of a year. +1. **Duration**: The duration is measured by the **year coefficient**, representing the number of years the phase will last. For instance, a year coefficient of 0.75 corresponds to a phase lasting 9 months (3/4th of a year). -- inflation: This parameter defines the inflation rate of the chain for the phase in question. Inflation is defined as a decimal. That is, inflation of 0.10000 means an inflation rate of 10%. +2. **Inflation**: This parameter specifies the inflation rate for the given phase. Inflation is expressed as a decimal; for example, an inflation value of 0.10000 corresponds to a 10% inflation rate. -The duration and inflation rate of phases can be modified via governance. +Governance mechanisms allow adjustments to both the duration and inflation rate of these phases. -> If all the specified phases are over, the chain enters a special phase called the final_phase, where the phase duration is infinite and the phase inflation is zero. -> Note that the inflation rate does not depend on the number of bonded and unbonded tokens +Furthermore, once all specified phases conclude, the chain enters a special phase known as the **final phase**. In this phase, the duration is infinite, and the inflation rate becomes zero. Notably, the inflation rate remains independent of the number of bonded and unbonded tokens. diff --git a/docs/specs/Mint/03_State.md b/docs/specs/Mint/03_State.md index 66ce7fd3..61ffab9e 100644 --- a/docs/specs/Mint/03_State.md +++ b/docs/specs/Mint/03_State.md @@ -2,7 +2,7 @@ ## **Minter** -The minter is a space for holding the current phase and inflation information. +The minter serves as a repository for storing the present phase and inflation data. ```proto // Minter represents the minting state. @@ -33,19 +33,19 @@ message Minter { ## **Params** -Minting params are held in the global params store. +The **minter** stores minting parameters in the global params store. Let's break down the key parameters: -1. Mint Denom: This parameter represents the denomination of the minted token +1. **Mint Denom**: This parameter specifies the denomination of the minted token. -2. Blocks Per Year: This parameter is used to signify how many blocks will comprise 1 year. Note that the phases, which are defined as a coefficient of years, will also be based on this parameter. For example, if the year_coefficient is defined as 0.5, and the blocks_per_year is defined as 1000, that means the phase will last for 500 blocks. +2. **Blocks Per Year**: It indicates how many blocks constitute one year. The phases, which are coefficients of years, depend on this parameter. For instance, if the `year_coefficient` is 0.5 and `blocks_per_year` is 1000, a phase will last for 500 blocks. -3. Phases: Phases are defined as specific discreet time frames during which a certain inflation rate holds. +3. **Phases**: These represent discrete time frames during which a specific inflation rate applies. - a. duration: The duration is defined as the year_coefficient. It defines the time in years for which a phase will hold. For example a yearcoefficient of 0.75 means that the phase will last for 9 months, that is, 3/4th of a year. + - **Duration**: The duration corresponds to the `year_coefficient`. It defines the phase's duration in years. For example, a `year_coefficient` of 0.75 means the phase lasts for 9 months (3/4th of a year). - b. inflation: This parameter defines the inflation rate of the chain for the phase in question. Inflation is defined as a decimal. That is, inflation of 0.10000 means an inflation rate of 10%. + - **Inflation**: This parameter sets the inflation rate for the given phase. Inflation is expressed as a decimal; for instance, an inflation of 0.10000 corresponds to a 10% inflation rate. -4. Exclude Amount: This parameter defines the number of tokens that will not incur inflation. +4. **Exclude Amount**: This parameter specifies the number of tokens exempt from inflation. ```proto // Params defines the parameters for the module. diff --git a/docs/specs/Mint/04_Begin_Block.md b/docs/specs/Mint/04_Begin_Block.md index d2638a26..7f77c7a7 100644 --- a/docs/specs/Mint/04_Begin_Block.md +++ b/docs/specs/Mint/04_Begin_Block.md @@ -1,10 +1,10 @@ # **Begin-Block** -Minting parameters are recalculated and inflation is paid at the beginning of each block. +Minting parameters are recalculated, and inflation is disbursed at the start of every block. ## **Detect Current Phase** -Check if the chain has moved from one phase to another, including the final phase: +Verify whether the chain has transitioned between phases, including the ultimate phase: ```go // CurrentPhase returns current phase of the inflation @@ -45,7 +45,7 @@ func (m Minter) CurrentPhase(params Params, currentBlock int64) (Phase, int) { } ``` -If the phase has changed, set the minter with the changed parameters: +If there has been a phase change, update the minter with the modified parameters: ```go // set the new minter properties if the phase has changed or inflation has changed @@ -72,7 +72,7 @@ If the phase has changed, set the minter with the changed parameters: ## **Next Phase Provision** -Since the SGE-Network chain is predominantly reliant on phases for its inflation model, the phase_provision keeps track of the total amount of tokens to be distributed in the current phase. This value is calculated every time there is a phase change. +Given that the SGE-Network chain heavily relies on phases for its inflation model, the phase_provision mechanism monitors the overall token distribution in the current phase. This value is recalculated whenever a phase transition occurs. ```go // NextPhaseProvisions returns the phase provisions based on current total @@ -94,7 +94,21 @@ func (m Minter) NextPhaseProvisions(totalSupply sdkmath.Int, excludeAmount sdkma ## **Block Provision** -Calculate the provisions generated for each block based on current phase provisions. The provisions are then minted by the `mint` module's ModuleMinterAccount and then transferred to the auth's FeeCollector ModuleAccount. +1. **Inflation Calculation**: + - At the beginning of each block, the inflation parameters are recalculated. + - The target annual inflation rate is adjusted based on the current bonded ratio (the ratio of bonded tokens to the total supply). + - The inflation rate can change positively or negatively depending on how close it is to the desired ratio (usually 85%). + - The maximum rate change per year is capped at 10%. + - The annual inflation is then calculated, ensuring it falls between 5% and 10%. + +2. **Annual Provisions**: + - Next, we calculate the annual provisions based on the current total supply and the inflation rate. + - This parameter is computed once per block. + +3. **Block Provisions**: + - The provisions generated for each block are derived from the annual provisions. + - These provisions are minted by the **Mint module's ModuleMinterAccount**. + - Finally, they are transferred to the **FeeCollector ModuleAccount** within the authentication system. ```go // BlockProvisions returns the provisions for a block based on the phase diff --git a/docs/specs/Mint/05_Events.md b/docs/specs/Mint/05_Events.md index 5e57fc17..e4b52c3b 100644 --- a/docs/specs/Mint/05_Events.md +++ b/docs/specs/Mint/05_Events.md @@ -1,6 +1,6 @@ # **Events** -The `mint` module emits the following events: +The **Mint Module** emits the following events: ## **BeginBlocker** diff --git a/docs/specs/Mint/06_Parameters.md b/docs/specs/Mint/06_Parameters.md index b8df7397..002045a3 100644 --- a/docs/specs/Mint/06_Parameters.md +++ b/docs/specs/Mint/06_Parameters.md @@ -1,6 +1,6 @@ # **Parameters** -The minting module contains the following parameters: +The **Mint module** contains the following parameters: | Key | Type | Example | |:-------------: |:---------------: |:---------: | diff --git a/docs/specs/OVM/01_Overview.md b/docs/specs/OVM/01_Overview.md index 562f4016..a8791134 100644 --- a/docs/specs/OVM/01_Overview.md +++ b/docs/specs/OVM/01_Overview.md @@ -1,7 +1,7 @@ # **Overview** -The SGE-Network chain relies on external off-chain data of matches, markets and KYC validation of the bettors and depositors. To push this data reliably to the chain, some kind of origin verification is required. The `ovm` module essentially fills this role in the SGE-Network chain. The `ovm` module verifies the following data: +The SGE-Network chain depends on external off-chain data concerning matches, markets, and KYC validation of both bettors and depositors. Ensuring the reliable transmission of this data to the chain necessitates some form of origin verification. Within the SGE-Network chain, the `ovm` module serves this essential function. It verifies the following types of data: -- Market data pushed by the House to the chain -- Validity of Odds data using proposed ticket data during bet placement by user -- Depositor's KYC validation +- Market data transmitted from the House to the chain +- The legitimacy of Odds data by cross-referencing proposed ticket data during user bet placement +- KYC validation of depositors diff --git a/docs/specs/OVM/02_Concepts.md b/docs/specs/OVM/02_Concepts.md index cd7b99c1..f5c04ac4 100644 --- a/docs/specs/OVM/02_Concepts.md +++ b/docs/specs/OVM/02_Concepts.md @@ -1,29 +1,13 @@ # **Concepts** -To verify the origin of the data, a simple mechanism of signing and verifiction with a private key and the correponding public key respectively is performed. +A straightforward process is undertaken to ensure the data's authenticity: signing with a private key and subsequent verification with the corresponding public key. -The data that needs to be pushed into the chain is first signed by the private key of a trusted source. This process occurs off chain. Essentially, we create an encrypted `ticket` with the trusted private key. The curve used for signing and verification of the ticket is the [Edwards-curve Digital Signature Algorithm](https://en.wikipedia.org/wiki/EdDSA). This algorithm has been chosen for the following benefits: +Initially, the data slated for insertion into the chain undergoes signing using a trusted private key, a step executed off-chain. Essentially, this results in the creation of an encrypted 'ticket' using the trusted private key. The chosen curve for signing and verifying these tickets is the Edwards-curve Digital Signature Algorithm (EdDSA), selected for its various advantages including fast single-signature verification, efficient batch verification, rapid signing, and high security levels. Further details on this algorithm can be found [here](https://ed25519.cr.yp.to/). -- Fast single-signature verification -- Fast batch verification -- Very fast signing -- Fast key generation -- High security level -- Foolproof session keys -- Collision resilience -- No secret array indices -- No secret branch conditions -- Small signatures -- Small keys +Once the encrypted signed ticket is generated, it becomes part of the transactions. These transactions cover actions such as adding/editing betting markets on the chain and verifying odds when users engage with these markets. Each ticket includes an expiry timestamp to invalidate it after a set duration, preventing the use of old or expired tickets. -Details of the algorithm can be found [here](https://ed25519.cr.yp.to/) +The **OVM module** maintains a catalog of trusted public keys, counterparts to the private keys used for off-chain signing and encryption of tickets. When a transaction requiring data origin verification occurs, the corresponding module calls upon the **OVM module** for verification and decryption. Serving as an interface, the **OVM module** decodes any signed data supplied to it, given the encryption algorithm and decrypted type. This design eliminates the need for OVM structural changes with ticket structure alterations, enabling the OVM to function as a universal verification module. ---- +Upon invocation, the OVM initially verifies the data signature against the registered public keys. If the leader public key (the primary element in the public keys slice in the key vault store) successfully verifies the signature, the OVM decrypts the data into the provided structure and returns it. Failure of signature verification, ticket expiration, or mismatching decrypted structure results in verification failure, prompting an error returned to the invoking module and consequently transaction failure. -After generating the encrypted signed `ticket`, this signature data is included in the transactions. This includes transactions for adding/editing betting markets on the chain, as well as verifying odds when the user places on these markets. All tickets come with an expiry timestamp which invalidates the ticket after a certain duration. This facility prevents the use or abuse of old and expired tickets. - -The `ovm` module essentially stores a list of trusted public keys. These public keys are just the counterpart to the private keys that were used to sign and encrypt the tickets off-chain. When a transaction is made to the chain that necessitates verification of the origin of the data, the corresponding module invokes the OVM module for verification and decryption purpose. The OVM Module works as an interface, which can decode any signed data passed to it when supplied with the encryption algorithm and the decrypted type. This design completely nullifies the need to change the structure of the OVM if the ticket structure changes. This essentially enables the OVM to be a global verification module. - -When the OVM is invoked, it first attempts to verify the signature of the data against the list of registered public keys. If the signature is verified successfully by the leader public key (the first element in the public keys slice in the key vault store), the OVM decrypts the data into the provided structure and returns it to the invoking module. In case the signature verification fails, or the ticket seems to have expired, or the decrypted structure does not match with the expected structure, the verification is considered to be a failure and a corresponding error is returned to the invoking module, which consequently results in failure of the transaction. - -The OVM Leader is the public key that is being used for the verification of the tickets, The first element of the Key Vault public keys is the leader. If the private key of the leader's public key gets corrupt/hacked/leaked, The holders of the rest of the public keys can create a pub keys-change proposal to replace the leaked public key with a new one and choose the new leader key. Each proposal needs at least 66.67% "yes" or 2 "no" to make blockchain code to decide about the proposal's approval or rejection, the modification happens in the end blocker if the condition of votes is satisfied. +The OVM Leader, the public key used for ticket verification, resides as the initial element in the Key Vault public keys. If the leader's private key becomes compromised, holders of the remaining public keys can propose a key change, selecting a new leader. Each proposal requires at least 66.67% 'yes' votes or 2 'no' votes for blockchain code to decide its approval or rejection. Modification occurs in the end blocker upon satisfying vote conditions. diff --git a/docs/specs/OVM/04_Messages.md b/docs/specs/OVM/04_Messages.md index 599c7eca..2217b36b 100644 --- a/docs/specs/OVM/04_Messages.md +++ b/docs/specs/OVM/04_Messages.md @@ -17,7 +17,7 @@ service Msg { ### **MsgSubmitPubkeysChangeProposalRequest** -This message can be sent by any of the current registered public key owners, If any of the current private keys get compromised, we can use this message to replace the corrupt public key and set the new leader. +Any of the presently registered public key owners can send this message. In case any of the current private keys are compromised, we can utilize this message to substitute the compromised public key and designate a new leader. ```proto // MsgPubkeysChangeProposalRequest is the type of request for modification of @@ -96,4 +96,4 @@ message ProposalVotePayload { } ``` -> **NOTE:** In the absence of public keys, signatures cannot be verified for any transaction. +> **NOTE:** Without public keys, signatures cannot be authenticated for any transaction. diff --git a/docs/specs/OVM/05_Events.md b/docs/specs/OVM/05_Events.md index d851ee04..82662d16 100644 --- a/docs/specs/OVM/05_Events.md +++ b/docs/specs/OVM/05_Events.md @@ -1,6 +1,6 @@ # **Events** -The OVM module emits the following events: +The **OVM module** emits the following events: ## *MsgSubmitPubkeysChangeProposalRequest* diff --git a/docs/specs/OrderBook/01_Overview.md b/docs/specs/OrderBook/01_Overview.md index 636cda23..771b9dbf 100644 --- a/docs/specs/OrderBook/01_Overview.md +++ b/docs/specs/OrderBook/01_Overview.md @@ -1,3 +1,3 @@ # **Overview** -The `orderbook` module maintains order books for markets and their corresponding participations and fund management of the module accounts, bettors, market creators and depositors of house. +The **Orderbook Module** oversees market order books and manages the participation, funds, and accounts of module users, bettors, market creators, and house depositors. diff --git a/docs/specs/OrderBook/02_Concepts.md b/docs/specs/OrderBook/02_Concepts.md index 1901576a..4fe81a73 100644 --- a/docs/specs/OrderBook/02_Concepts.md +++ b/docs/specs/OrderBook/02_Concepts.md @@ -1,20 +1,14 @@ # **Concepts** -The `orderbook` is tasked with maintaining the order book, participations, exposures and order book settlement, -each order book will be created as a one-to-one dependency of market. in action, `market` module calls -order book initiation method of the `orderbook` module to create the corresponding order book, participation and odds exposures. -The created order book for the market initiated will be maintained until the market marked as settled. +The **Orderbook Module** is responsible for managing order books, participations, exposures, and order book settlements. Each order book is created as a one-to-one dependency of a market. In practice, the **Market Module** invokes the order book initiation method of the **Orderbook Module** to establish the corresponding order book, participation, and odds exposures. Once created, the order book for an initiated market remains active until the market is marked as settled. -When an orderbook is being created, There is no fund available to cover the payout profit payment of the bets, so at least 1 deposit is needed to be made on the order book to enable `bet` module to accept bets. +During the order book creation process, there are no available funds to cover the payout profit payment for bets. Therefore, at least one deposit is required on the order book to enable the **Bet Module** to accept bets. -Once the `orderbook` has initiated an order book for a market, users can either bet against the house or -become a part of the house by deposition of chosen amount through the House module. When a user deposits chosen -amount through the `house` module, the `house` module will call the `orderbook` module to update the order book -and set the participation for the user on the requested market. +After the **Orderbook Module** initializes an order book for a market, users have two options: they can either bet against the house or become part of the house by depositing a chosen amount through the **House Module**. When a user makes a deposit via the **House Module**, the **Orderbook Module** updates the order book and sets the user's participation for the requested market. -The deposit amount of order book participants is used to facilitate betting on the market. +The deposit amounts from order book participants facilitate betting on the market. -The payout that need to be paid by the system is named Exposure, there are two types of bet odds exposures: +System payouts are referred to as "Exposure," which comes in two types of bet odds exposures: -- The odds exposure are the payouts that expected to be paid. -- The participation exposure are the payout that is guaranteed to be paid by the participation. +1. **Odds Exposure**: These are the expected payouts. +2. **Participation Exposure**: These payouts are guaranteed based on participation. diff --git a/docs/specs/OrderBook/03_State.md b/docs/specs/OrderBook/03_State.md index 662d4fbb..5e26763a 100644 --- a/docs/specs/OrderBook/03_State.md +++ b/docs/specs/OrderBook/03_State.md @@ -2,8 +2,9 @@ ## **Params** -1. `max_book_participations`: is the maximum participations allowed for a book. -2. `batch_settlement_count`: is the count of bets to be automatically settlement in `orderbook`. +1. **Max Orderbook Participations**: is the maximum participations allowed for a book. +2. **Batch Settlement Count**: is the count of bets to be automatically settlement in `orderbook`. +3. **Requeue Threshold**: the minimum amount that the fulfillment queue will be refreshed. ```proto // Params defines the parameters for the orderbook module. diff --git a/docs/specs/OrderBook/04_State_Transitions.md b/docs/specs/OrderBook/04_State_Transitions.md index 7ebef2aa..79dc8f88 100644 --- a/docs/specs/OrderBook/04_State_Transitions.md +++ b/docs/specs/OrderBook/04_State_Transitions.md @@ -1,13 +1,13 @@ # **State Transitions** -This section defines the state transitions of the `orderbook` module's KVStore in all scenarios: +This section outlines the state transitions of the **KVStore** in the **Orderbook Module** across various scenarios: ## **Order Book Initialization** -When a market is being created: +Upon creation of a market: -1. Creates an order book corresponding to the market -2. Set the exposures for the bet odds. +1. Establishes an order book for the respective market. +2. Sets the exposures for the bet odds. ```go newOrderBook := &types.Deposit{ @@ -22,64 +22,63 @@ newOrderBook := &types.Deposit{ ## **Initiate Participation** -When a user deposits tokens: +Upon depositing tokens: -1. Retrieve the market and the order book. -2. Check if the market is active, if not return error. -3. Check if the order book is active, if not return error. -4. Check if maximum allowed participant is reached or not. -5. Set the participation equal to the liquidity amount of the deposition. +1. Fetch the market and its order book. +2. Verify market activity; return error if inactive. +3. Confirm order book activity; return error if inactive. +4. Check if the maximum allowed participants have been reached. +5. Set participation equal to the deposited liquidity amount. 6. Transfer the liquidity amount to the `orderbook_liquidity_pool` module account. 7. Transfer the deposition fee to the `house_fee_collector` module account. -8. Update the order book odds exposures and add the participation into the fulfillment queue. -9. Initialize the participation exposure as zero for round as 1 and set to the state. +8. Update the order book odds exposures and add the participation to the fulfillment queue. +9. Initialize the participation exposure as zero for round one and set it to the state. --- ## **Process Wager** -1. Get order book and odds exposures. -2. Check all fulfillment queue items: - 1. Get participations and participation exposures +1. Retrieve order book and odds exposures. +2. Iterate through all fulfillment queue items: + 1. Obtain participations and participation exposures. 2. Check available liquidity and process fulfillment. - 3. Set the Participation and exposures into the state. + 3. Update the state with participations and exposures. 3. Remove the fulfillment queue item from the order book. -4. Transfer bet fee to `bet_fee_collector` module account. +4. Transfer bet fee to the `bet_fee_collector` module account. 5. Transfer fulfilled bet amount to the `orderbook_liquidity_pool` account. -6. Set the bet as paid out bet. +6. Mark the bet as paid out. ## **Process Bet Settlement** -1. BettorWins(called by the `bet` module): - - For all bet fulfilments: - 1. Get participation. - 2. Transfer bet amount and payout profit to the bettor's account address from `orderbook_liquidity_pool` module account. - 3. Set actual profit of the participation that fulfilled this bet. - 4. Set the participation in the state. -2. Bettor Loses(called by the `bet` module): - - For all bet fulfilments: - 1. Get participation. - 2. Update actual profit to the paticipations. - 3. Set the participation in the state. - -3. Refund bettor(called by the `bet` module): - 1. Transfer bet fee to the bettor's account address from `bet_fee_collector` module account. - 2. Transfer bet amount to the bettor's account address from `orderbook_liquidity_pool` module account.address. +1. When the bettor wins (called by the `bet` module): + - For each bet fulfillment: + 1. Retrieve participation. + 2. Transfer bet amount and payout profit to the bettor's account address from the `orderbook_liquidity_pool` module account. + 3. Set the actual profit of the participation that fulfilled this bet. + 4. Update the participation in the state. +2. When the bettor loses (called by the `bet` module): + - For each bet fulfillment: + 1. Retrieve participation. + 2. Update actual profit for the participation. + 3. Update the participation in the state. +3. Refund bettor (called by the `bet` module): + 1. Transfer bet fee to the bettor's account address from the `bet_fee_collector` module account. + 2. Transfer bet amount to the bettor's account address from the `orderbook_liquidity_pool` module account. --- ## **Batch order book settlement** -Batch bet settlement happens in the end-blocker of the `orderbook` module: +Batch bet settlement occurs in the end-blocker of the `orderbook` module: -1. Get resolved orderbooks that have no unsettled bets. - - for each orderbook(market): +1. Identify resolved order books with no unsettled bets. + - For each order book (market): - If the market is canceled or aborted: - 1. Refund depositor the original deposit liquidity from `orderbook_liquidity_pool` module account. - 2. Refund depositor the original deposit fee from `house_fee_collector` module account. - 3. Set the participation as settled in the module state. - - If market result is declared and settled: - 1. Refund depositor the original deposit liquidity plus the actual profit gained in fulfillment from `orderbook_liquidity_pool` module account. - 2. Refund depositor the original deposit fee from `house_fee_collector` module account if the participation not participated in the bet fulfillment process. - 3. Set the participation as settled in the module state. -2. Check the `BatchSettlementCount` parameter of `orderbook` module and let the rest of order books for the nex block. + 1. Refund the depositor the original deposit liquidity from the `orderbook_liquidity_pool` module account. + 2. Refund the depositor the original deposit fee from the `house_fee_collector` module account. + 3. Mark the participation as settled in the module state. + - If the market result is declared and settled: + 1. Refund the depositor the original deposit liquidity plus the actual profit gained in fulfillment from the `orderbook_liquidity_pool` module account. + 2. Refund the depositor the original deposit fee from the `house_fee_collector` module account if the participation did not participate in the bet fulfillment process. + 3. Mark the participation as settled in the module state. +2. Check the `BatchSettlementCount` parameter of the `orderbook` module and proceed with the remaining order books for the next block. diff --git a/docs/specs/OrderBook/05_Messages.md b/docs/specs/OrderBook/05_Messages.md index 7c892516..2b15725d 100644 --- a/docs/specs/OrderBook/05_Messages.md +++ b/docs/specs/OrderBook/05_Messages.md @@ -1,3 +1,3 @@ # **Messages** -The `orderbook` module does not emit any messages. +The **Orderbook Module** does not emit any messages. diff --git a/docs/specs/OrderBook/06_Events.md b/docs/specs/OrderBook/06_Events.md index 2209e33b..bc74a7b0 100644 --- a/docs/specs/OrderBook/06_Events.md +++ b/docs/specs/OrderBook/06_Events.md @@ -1,3 +1,13 @@ # **Events** -The `orderbook` module does not emit any events. +The **Orderbook Module** emits the following events: + +## *Participation Settlement* + +| **Type** | **Attribute Key** | **Attribute Value** | +|----------------------------|-------------------------------|---------------------------------| +| participation_settlement | market_uid | {market_uid} | +| participation_settlement | participation_index | {participation_index} | +| participation_settlement | participation_reimbursed_fee | {participation_reimbursed_fee} | +| participation_settlement | participation_returned_amount | {participation_returned_amount} | +| participation_settlement | participation_actual_profit | {participation_actual_profit} | diff --git a/docs/specs/Reward/01_Overview.md b/docs/specs/Reward/01_Overview.md index cc9e336a..dc628341 100644 --- a/docs/specs/Reward/01_Overview.md +++ b/docs/specs/Reward/01_Overview.md @@ -1,5 +1,5 @@ # **Overview** -The Reward module is responsible for Campaign state management and reward validation and application. +The **Reward Module** oversees Campaign state management, reward validation, and application. -To grant rewards, this module uses `subaccount` module methods to TopUp the sub account balance and withdraw it when there is a withdraw request or wager or house deposit. +To distribute rewards, this module leverages **Subaccount Module** methods to top up the sub-account balance and process withdrawals in response to withdrawal requests, wagers, or house deposits. diff --git a/docs/specs/Reward/02_Concepts.md b/docs/specs/Reward/02_Concepts.md index c20183ac..49e75738 100644 --- a/docs/specs/Reward/02_Concepts.md +++ b/docs/specs/Reward/02_Concepts.md @@ -1,23 +1,21 @@ # **Concepts** -Reward module is tasked with create and update of campaigns and reward application (allocation). the user can create a campaign through command-line or singing and broadcasting the campaign create message. +The **Reward Module** is responsible for creating and updating campaigns, as well as managing reward allocation. Users can create campaigns either through the command-line interface or by broadcasting a campaign creation message. -## **Campaign** +## Campaigns -Campaigns are being distinguished by their UID, We can have multiple campaigns with a same reward type at the same time. so, reward application is depend on the campaign that is being defined. +Campaigns are uniquely identified by their UID. It's possible to have multiple campaigns with the same reward type running concurrently. The application of rewards depends on the specific campaign being defined. -## **Reward Types** +## Reward Types -### **SignUp Rewards** +### SignUp Rewards -#### **1. SignUp** +1. **SignUp** + - This reward is granted when a user creates an account by signing up in the system. The reward is stored in the `subaccount` balance and can be used for betting or other house functionalities. -This reward can be given when a user is creating an account by signing up in system, the reward is in `subaccount` balance and can be used for betting or be the house functionalities. +2. **Referral** + - Users receive this reward when they are referred to the system by another user. Similar to the SignUp reward, the referee's reward is also in the `subaccount` balance and can be utilized for betting or other purposes. -#### **2. Referral** +### Referral Rewards -This reward can be given when a user is referred by another user to the system, the referee reward is in `subaccount` balance and can be used for betting or be the house functionalities. - -### **Referral** - -This reward can be given when a user is referring another new user to the system, the referrer reward is in `subaccount` balance and can be used for betting or be the house functionalities. +- Referral rewards are given to users who refer new users to the system. The referrer's reward is stored in the `subaccount` balance and can be used for betting or other house functionalities. diff --git a/docs/specs/Reward/03_Accounts.md b/docs/specs/Reward/03_Accounts.md index 71085561..80c44577 100644 --- a/docs/specs/Reward/03_Accounts.md +++ b/docs/specs/Reward/03_Accounts.md @@ -1,11 +1,11 @@ # **Accounts** -There is one account in the Reward module. +Within the **Reward Module**, there exists a solitary account. -- Reward Pool: This account holds the reward amount transferred from the campaign `promoter` to the `reward_pool` module account. +- Reward Pool: This particular account stores the sum of rewards transferred from the `promoter` campaign account to the `reward_pool` module account. -During the campaign creation the pool amount will be transferred to the reward pool module account. +Upon campaign creation, the pool sum will be directed to the reward pool module account. -## **Grant Reward Transfer** +## **Transfer of Granted Rewards** -The reward would be transferred to the reward receiver main account (or sub account) according to the ticket payload of the grant reward transaction endpoint. +The rewards are then transferred to the main (or sub) account of the reward receiver, based on the ticket payload of the grant reward transaction endpoint. diff --git a/docs/specs/Reward/04_State.md b/docs/specs/Reward/04_State.md index b485fd35..e3f7c5f8 100644 --- a/docs/specs/Reward/04_State.md +++ b/docs/specs/Reward/04_State.md @@ -2,27 +2,34 @@ ## **KVStore** -State in Reward module is defined by its KVStore. This KVStore has one prefix: +The state in the **Reward module** is determined by its KVStore, which contains the following prefixes: -1. All campaigns including active and expired items. +1. All campaigns, including active and expired items. +2. All promoters. +3. Promoters indexed by their addresses. +4. All rewards. +5. Rewards categorized by category and the receiving accounts. +6. Rewards for a specific campaign. +7. Statistics of reward grants for a campaign. -The Reward model in the Proto files is as below: +The Reward model in the Proto files is outlined as follows: ## **Campaign** -1. `creator`: is the creator account(message signer of the CreateCampaign). -2. `uid`: is the universal unique identifier of the campaign. -3. `promoter`: The account address that is responsible for paying the campaign pool balance. -4. `start_ts`: The time that campaign would be started and receive apply reward message. -5. `end_ts`: The time that campaign would be ended and is not able tor receive apply reward message. -6. `reward_category`: Defines the general category of reward that is defined for the campaign. -7. `reward_type`: Defines the type of reward that is defined for the campaign. -8. `reward_amount_type`: Defines the type of reward amount allocation that is defined for the campaign. -9. `reward_amount`: Defines the amount of reward that is defined for the campaign to be granted to main or sub account. -10. `pool`: Information of the current pool balance. -11. `is_active`: Is active/inactive status of the campaign. -12. `claims_per_category`: Maximum number of reward grant transaction per category. -13. `meta`: Contains a string metadata that can be a simple description or a json. +1. `creator`: The account that signed the CreateCampaign message, serving as the creator. +2. `uid`: The universally unique identifier of the campaign. +3. `promoter`: The account address responsible for managing the campaign pool balance. +4. `start_ts`: The start time of the campaign, indicating when it starts receiving apply reward messages. +5. `end_ts`: The end time of the campaign, after which it stops receiving apply reward messages. +6. `reward_category`: The general category defining the campaign's rewards. +7. `reward_type`: The type of reward designated for the campaign. +8. `reward_amount_type`: The allocation type for the reward amount. +9. `reward_amount`: The amount of reward specified for the campaign to be granted to the main or sub account. +10. `pool`: Information regarding the current pool balance. +11. `is_active`: Indicates the active/inactive status of the campaign. +12. `meta`: Contains metadata in the form of a string, which could be a simple description or JSON data. +13. `cap_count`: The maximum count of reward grants for a specific account. +14. `constraints`: Contains campaign constraints, a nullable field used for campaigns like *Bet Bonus*. ```proto // Campaign is type for defining the campaign properties. @@ -73,13 +80,15 @@ message Campaign { // is_active is the flag to check if the campaign is active or not. bool is_active = 11; - // claims_per_category is the number of times a user can claim a - // reward for category of this campaign. - uint64 claims_per_category = 12; - // meta is the metadata of the campaign. // It is a stringified base64 encoded json. string meta = 13; + + // cap_count is the maximum allowed grant for a certain account. + uint64 cap_count = 14; + + // constraints is the constrains of a campaign. + CampaignConstraints constraints = 15; } // Pool tracks funds assigned and spent to/for a campaign. @@ -94,6 +103,20 @@ message Pool { (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"spent\"" ]; + string withdrawn = 3 [ + (gogoproto.customtype) = "cosmossdk.io/math.Int", + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"spent\"" + ]; +} + +// CampaignConstraints contains campaign constraints and criteria. +message CampaignConstraints { + string max_bet_amount = 1 [ + (gogoproto.customtype) = "cosmossdk.io/math.Int", + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"max_bet_amount\"" + ]; } // RewardType defines supported types of rewards in reward module. @@ -174,13 +197,13 @@ enum RewardAmountType { ## **Reward** -1. `uid`: is the unique universal identifier of the granted reward. -2. `creator`: is the creator account(message signer of the CreateCampaign). -3. `receiver`: is the string address of the main account. -4. `campaign_uid`: is the unique identifier of the associated campaign. -5. `reward_amount`: is the amount to be deducted from main and sub account balances. -6. `source_uid`: is the source of reward grant universal unique identifier. -7. `meta`: is the metadata related to the granted reward, can be a string or json. +1. `uid`: Represents the universally unique identifier assigned to the granted reward. +2. `creator`: Identifies the account that signed the CreateCampaign message, serving as the creator. +3. `receiver`: Denotes the string address of the primary account. +4. `campaign_uid`: Serves as the unique identifier for the associated campaign. +5. `reward_amount`: Specifies the amount to be deducted from the balances of the main and sub accounts. +6. `source_uid`: Indicates the unique identifier of the source of the reward grant. +7. `meta`: Contains metadata pertaining to the granted reward, which can be either a string or JSON. ```proto // Reward is the type for transaction made to reward a user @@ -231,14 +254,14 @@ message Reward { // RewardAmount message RewardAmount { - // main_account_reward amount transferred to main account address + // main_account_amount transferred to main account address string main_account_amount = 1 [ (gogoproto.customtype) = "cosmossdk.io/math.Int", (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"main_account_amount\"" ]; - // sub_account reward amount transferred to subaccount address + // subaccount_amount transferred to subaccount address string subaccount_amount = 2 [ (gogoproto.customtype) = "cosmossdk.io/math.Int", (gogoproto.nullable) = false, @@ -251,5 +274,49 @@ message RewardAmount { (gogoproto.jsontag) = "unlock_period", json_name = "unlock_period" ]; + + // main_account_percentage transferred to main account address + string main_account_percentage = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"main_account_percentage\"" + ]; + + // subaccount_percentage amount transferred to subaccount address + string subaccount_percentage = 5 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"subaccount_percentage\"" + ]; +} + +// RewardByCategory +message RewardByCategory { + // uid is the unique identifier for a reward. + string uid = 1 [ + (gogoproto.customname) = "UID", + (gogoproto.jsontag) = "uid", + json_name = "uid" + ]; + // addr is the address of the reward receiver. + string addr = 2; + // reward_category is the category of the reward. + RewardCategory reward_category = 3; +} + +// RewardByCampaign +message RewardByCampaign { + // uid is the unique identifier for a reward. + string uid = 1 [ + (gogoproto.customname) = "UID", + (gogoproto.jsontag) = "uid", + json_name = "uid" + ]; + // campaign_uid is the unique identifier of the campaign. + string campaign_uid = 2 [ + (gogoproto.customname) = "CampaignUID", + (gogoproto.jsontag) = "campaign_uid", + json_name = "campaign_uid" + ]; } ``` diff --git a/docs/specs/Reward/05_State_Transitions.md b/docs/specs/Reward/05_State_Transitions.md index bc02f7f8..154c96e4 100644 --- a/docs/specs/Reward/05_State_Transitions.md +++ b/docs/specs/Reward/05_State_Transitions.md @@ -1,12 +1,13 @@ # **State Transitions** -This section defines the state transitions of the reward module's KVStore in all scenarios: +This segment delineates the state transitions of the **KVStore** within the **Reward module** across various situations: -## **Create Campaign** +## **Creating a Campaign** -When this is processed: +Upon processing: -- If the ticket is valid a new campaign will be created with the given data and will be added to the `Reward` module state. +1. In case of a valid ticket, a new campaign will be generated using the provided data and integrated into the **Reward Module** state. +2. The total pool amount will be subtracted from the promoter's account balance and retained within the pool module account. ```go newCampaign := &types.Campaign{ @@ -21,8 +22,9 @@ newCampaign := &types.Campaign{ reward_amount: msg.ticket.RewardAmount, Pool: Pool{ Total: msg.Ticket.TotalFunds }, is_active: msg.ticket.IsActive, - claims_per_category:msg.ticket.ClaimsPerCategory, meta: msg.ticket.Meta, + cap_count: msg.ticket.CapCount, + constraints: msg.ticket.Constraints } ``` @@ -30,22 +32,15 @@ newCampaign := &types.Campaign{ ## **Grant Reward** -When this is processed: +Upon processing: -- If the corresponding campaign exists and is not expired, continue the process. +1. If the corresponding campaign exists and is not expired, proceed with the process. +2. Determine the distribution of rewards based on the defined reward amounts in the campaign, as well as the reward type and category. +3. Verify the availability of the pool balance for the campaign. +4. Allocate the rewards according to the calculated distributions. +5. Update the campaign pool based on the distribution. +6. Record the reward in the module state. +7. Record the reward by receiver in the module state. +8. Record the reward by campaign in the module state. -- Calculate reward distribution according to the reward amounts defined int the campaign and the reward type and category. - -- Validate availability of the pool balance for the campaign. - -- Distribute the rewards according to the calculated distributions. - -- Update the campaign pool according to the distribution. - -- Set Reward into the module state. - -- Set Reward by receiver into the module state. - -- Set Reward by campaign into the module state. - -> Note: The reward application modifies the campaign pool balance and accounts balances, but does not store reward application in the module state. +> Note: The reward application alters the campaign pool balance and accounts balances but does not store the reward application in the module state. diff --git a/docs/specs/Reward/06_Messages.md b/docs/specs/Reward/06_Messages.md index 9c17ee46..0313e018 100644 --- a/docs/specs/Reward/06_Messages.md +++ b/docs/specs/Reward/06_Messages.md @@ -1,10 +1,13 @@ # **Messages** -In this section, we describe the processing of the Reward messages. the transaction message -handler endpoints is as follows +In the following section, we outline the handling of Reward messages. Below are the endpoints for the transaction message handler. ```proto service Msg { + // SetPromoterConf is a method to set the configurations of a promoter. + rpc SetPromoterConf(MsgSetPromoterConf) returns (MsgSetPromoterConfResponse); + // CreatePromoter is a method to create a promoter + rpc CreatePromoter(MsgCreatePromoter) returns (MsgCreatePromoterResponse); // CreateCampaign is a method to create a campaign rpc CreateCampaign(MsgCreateCampaign) returns (MsgCreateCampaignResponse); // UpdateCampaign is a method to update campaign @@ -16,9 +19,45 @@ service Msg { } ``` +## **MsgCreatePromoter** + +In this message, the information of the promoter which will be created, should be included. + +```proto +// MsgCreatePromoter is msg to create a promoter. +message MsgCreatePromoter { + // creator is the address of message signer account. + string creator = 1; + // ticket is the payload data. + string ticket = 2; +} + +// MsgCreatePromoterResponse promoter create message response type. +message MsgCreatePromoterResponse {} +``` + +## **MsgSetPromoterConf** + +In this message, to modify the configurations of a promoter, this message will be broadcasted. + +```proto +// MsgSetPromoterConf is msg to set promoter configuration. +message MsgSetPromoterConf { + // creator is the address of message signer account. + string creator = 1; + // uid is the unique identifier of the promoter. + string uid = 2; + // ticket is the payload data. + string ticket = 3; +} + +// MsgCreateCampaignResponse campaign create message response type. +message MsgSetPromoterConfResponse {} +``` + ## **MsgCreateCampaign** -Within this message, the user specifies the campaign information they wish to create. +In this message, users provide the campaign information they aim to create. ```proto // MsgCreateCampaign is msg to create a reward campaign @@ -57,8 +96,11 @@ message MsgCreateCampaignResponse {} "unlock_period": 136318754373 }, "is_active": true, - "claims_per_category": 1, "meta": "custom metadata", + "cap_count": 1, + "constraints": { + "max_bet_amount": "300", + }, "exp": 1667863498866062000, "iat": 1667827498, "iss": "Oracle", @@ -126,9 +168,9 @@ message MsgGrantReward { message MsgApplyRewardResponse {} ``` -### MsgGrantRewardTicket Payloads +### **MsgGrantRewardTicket Payloads** -#### Common ticket payload type +#### **Common ticket payload type** This is a common type that should be present in all of the ticket payloads @@ -151,6 +193,9 @@ message RewardPayloadCommon { // meta is the metadata of the campaign. // It is a stringified base64 encoded json. string meta = 3; + + // kyc_data contains the details of user kyc. + sgenetwork.sge.type.KycDataPayload kyc_data = 4; } ``` @@ -245,6 +290,79 @@ message GrantSignupReferrerRewardPayload { } ``` +#### **3. Affiliate** + +- The `source_uid` should be empty. +- The `affiliatee` should contain the address of lead generator who is referring the user. + +```proto +// GrantSignupAffiliatorRewardPayload is the type for signup affiliator reward +// grant payload. +message GrantSignupAffiliatorRewardPayload { + // common is the common properties of a reward + RewardPayloadCommon common = 1 [ (gogoproto.nullable) = false ]; + + // affiliatee is the address of the account that used this affiliator's + // address as source_uid + string affiliatee = 2; +} +``` + +#### **Sample Affiliate Grant Reward ticket** + +```json +{ + "common": { + "receiver": "sge1rk85ptmy3gkphlp6wyvuee3lyvz88q6x59jelc", + "source_uid": "", + "meta": "custom grant metadata" + }, + "affiliatee": "{account address of the user which brought to the system by the lead generator}", + "exp": 1667863498866062000, + "iat": 1667827498, + "iss": "Oracle", + "sub": "GrantReward" +} +``` + +#### **4. Bet Bonus** + +- The `source_uid` should be empty. +- The `bet_uid` should contain the UID of the bet which were chosen to grant the reward for. + +```proto +// GrantBetBonusRewardPayload is the type for bet bonus reward +// grant payload. +message GrantBetBonusRewardPayload { + // common is the common properties of a reward + RewardPayloadCommon common = 1 [ (gogoproto.nullable) = false ]; + + // bet_uid is the list of uids + string bet_uid = 2 [ + (gogoproto.customname) = "BetUID", + (gogoproto.jsontag) = "bet_uid", + json_name = "bet_uid" + ]; +} +``` + +#### **Sample Bet Bonus Grant Reward ticket** + +```json +{ + "common": { + "receiver": "sge1rk85ptmy3gkphlp6wyvuee3lyvz88q6x59jelc", + "source_uid": "", + "meta": "custom grant metadata" + }, + "bet_uid": "{uid of the bet which the reward will be grantor to the bettor for}", + "exp": 1667863498866062000, + "iat": 1667827498, + "iss": "Oracle", + "sub": "GrantReward" +} +``` + ## **MsgWithdrawFunds** Within this message, the user specifies the reward application information they wish to apply. diff --git a/docs/specs/SubAccount/01_Overview.md b/docs/specs/SubAccount/01_Overview.md index e667c84d..71e22469 100644 --- a/docs/specs/SubAccount/01_Overview.md +++ b/docs/specs/SubAccount/01_Overview.md @@ -1,5 +1,5 @@ # **Overview** -The Sub Account module is responsible for creating, and funding a special accounts named `subaccount` that have different address from the main(owner) account, this type of account fund/refund is only allowed by this module transaction endpoints and events, the owner is not able to transfer any funds from this account manually using the `bank` module. +The **Subaccount Module** handles the creation and funding of special accounts called `subaccounts`. These subaccounts have distinct addresses separate from the main (owner) account. Only the **Subaccount module’s** transaction endpoints and events allow for funding or refunding of these accounts. The owner cannot manually transfer funds from this account using the **Bank Module**. -Reward module uses this module's methods internally to grant rewards to corresponding sub account of the reward receiver main account. +Internally, the Reward module utilizes methods from the **Subaccount Module** to grant rewards to the corresponding subaccount of the reward receiver’s main account. diff --git a/docs/specs/SubAccount/02_Concepts.md b/docs/specs/SubAccount/02_Concepts.md index 49779a59..51110129 100644 --- a/docs/specs/SubAccount/02_Concepts.md +++ b/docs/specs/SubAccount/02_Concepts.md @@ -1,25 +1,23 @@ # **Concepts** -Sub Account module is tasked with create, topup and fund/refund of a sub account. +The **Subaccount Module** is responsible for creating, topping up, and managing the funds of sub accounts. -## **Sub Account** +## Sub Account -Sub Account is a special type of account that manipulating its balance can be done by the blockchain code logic and nobody can use `bank` or `staking` modules to transfer or use the `subaccount` balance to delegate. +A sub account is a special type of account whose balance can be manipulated by the blockchain code logic. Unlike regular accounts, it cannot be accessed or transferred using the **Bank** or **Staking** modules. Each sub account has a one-to-one relationship with its owner account, meaning a normal account can either be associated with a sub account or have no sub account at all. -> There is a One(None)-To-One relationship between a `subaccount` and its owner account, so a normal account is able to have a `subaccount` associated with it or no `subaccount` associated. +## TopUp -## **TopUp** +Sub Account balances can be topped up on demand using the transaction endpoints provided by the sub account module. -Sub Account balance can be topped up on demand and can be done by the transaction endpoints of the sub account module. +## Withdrawal -## **Withdrawal** +Unlocked balances from a sub account can be withdrawn to the owner's main account balance. This operation is facilitated through the transaction endpoints of the sub account module. -Sub Account unlocked balance can be withdrawn to the owner's account balance. this can be done by the transaction endpoints of the sub account module. +## Wager -## **Wager** +Owners can use the **Subaccount Module** transaction message interfaces to wager using the sub account module's balance. This process automatically withdraws both unlocked and locked balances from the sub account, utilizing the main account address and balance for placing bets. -Using the `subaccount` module transaction message interfaces, the owner is able to wager using the sub account module's balance, it concludes automatic withdrawal of unlocked and locked balance of the `subaccount` then use the main account address and balance to place a bet. +## House Deposit/Withdraw -## **HouseDeposit/Withdraw** - -Using the `subaccount` module transaction message interfaces, the owner is able to deposit/withdraw to the house module using the sub account module's balance. +The **Subaccount Module** also allows owners to deposit to or withdraw from the house module using the sub account module's balance. diff --git a/docs/specs/SubAccount/03_State.md b/docs/specs/SubAccount/03_State.md index 547b3943..e26b0ada 100644 --- a/docs/specs/SubAccount/03_State.md +++ b/docs/specs/SubAccount/03_State.md @@ -2,18 +2,18 @@ ## **KVStore** -State in sub account module is defined by its KVStore. This KVStore has five prefixes: +The state within the **Subaccount Module** is defined by its KVStore, which consists of five prefixes: -1. Sub account sequential ID store to track the last generated ID of the sub accounts. -2. Sub account owner, that makes a 1-1 relation between main account and the `subaccount`. -3. Sub account address, enable the blockchain to get the `subaccount` info by `subaccount` address itself. -4. Locked balance of each `subaccount` address at a certain time. -5. Locked balance of each `subaccount`. +1. **Sub Account Sequential ID Store**: This prefix keeps track of the last generated ID for sub accounts. +2. **Sub Account Owner**: Establishes a one-to-one relationship between the main account and its associated `subaccount`. +3. **Sub Account Address**: Enables the blockchain to retrieve `subaccount` information directly using the `subaccount` address. +4. **Locked Balance of Each Subaccount Address**: Records the locked balance of each `subaccount` at a specific point in time. +5. **Locked Balance of Each Subaccount**: Stores the overall locked balance for each `subaccount`. -## **Params** +## Parameters -1. `wager_enabled`: determines if the wager via `subaccount` is enabled or not. -2. `deposit_enabled`: determines if the deposit to be a house via `subaccount` is enabled or not. +1. **Wager Enabled**: Determines whether wagering via `subaccount` is enabled. +2. **Deposit Enabled**: Indicates whether depositing to the house via `subaccount` is allowed. ```proto // Params defines the parameters for the module. diff --git a/docs/specs/SubAccount/04_State_Transitions.md b/docs/specs/SubAccount/04_State_Transitions.md index 0390eccd..3bd6e49c 100644 --- a/docs/specs/SubAccount/04_State_Transitions.md +++ b/docs/specs/SubAccount/04_State_Transitions.md @@ -1,64 +1,66 @@ # **State Transitions** -This section defines the state transitions of the Sub Account module's KVStore in all scenarios: +This section outlines the state transitions of the KVStore within the **Subaccount Module** across various scenarios: -## **Create Sub Account** +## **Creating a Sub Account** -When this is processed: +Upon processing this: -- Sum the unlock balances according to the input locked balances. -- Check if there is an existing `subaccount` for the proposed owner address. -- Generate new account using account module of the Cosmos-SDK. +- Aggregate the unlocked balances based on the provided locked balances. +- Verify if a `subaccount` already exists for the designated owner address. +- Generate a new account using the Cosmos-SDK account module. - Transfer the calculated balance to the newly created account. -- Set Sub account owner in the state. -- Set locked balance in the state. -- Set balance in the state. +- Update the state with the sub account owner. +- Update the state with the locked balance. +- Update the state with the balance. --- -## **Top Up Sub Account** +## **Topping Up a Sub Account** -When this is processed: +Upon processing this: -- Sum the unlock balances according to the input locked balances. -- Get `subaccount` by owner address from the state. -- Increase the deposited amount of the balance. -- Set locked balance in the state. -- Set balance in the state. +- Aggregate the unlocked balances based on the provided locked balances. +- Retrieve the `subaccount` associated with the owner address from the state. +- Increment the deposited amount of the balance. +- Update the state with the locked balance. +- Update the state with the balance. --- -## **Wager** +## **Wagering** -When this is processed: +Upon processing this: -- Get `subaccount` by Owner Address from the state. -- Call bet module's method to prepare the bet object. -- Get `subaccount` balance from the state. -- Withdraw `subaccount` locked/unlocked balance according to the input proportion. -- Call bet module's wager method to set the bet. -- Set the new balance of the sub account module in the state. +- Retrieve the `subaccount` associated with the owner address from the state. +- Invoke the bet module's method to prepare the bet object. +- Retrieve the balance of the `subaccount` from the state. +- Withdraw locked/unlocked balances of the `subaccount` based on the input proportion. +- Invoke the wager method of the **Bet Module** to establish the bet. +- Update the state with the new balance of the **Subaccount Module**. --- ## **House Deposit** -When this is processed: +Upon processing this: -- Get `subaccount` by Owner Address from the state. -- Get `subaccount` balance from the state. -- Call house module's method to parse the ticket and validate. +- Retrieve the `subaccount` associated with the owner address from the state. +- Retrieve the balance of the `subaccount` from the state. +- Invoke the method of the **House Module** to parse the ticket and validate. - Deduct the deposit amount from the sub account balance. -- Call house module's Deposit method to set the participation. -- Set the new balance of the sub account module in the state. +- Invoke the Deposit method of the **House Module** to record the participation. +- Update the state with the new balance of the **Subaccount Module**. -## **House Withdraw** +--- + +## **House Withdrawal** -When this is processed: +Upon processing this: -- Get `subaccount` by Owner Address from the state. -- Get `subaccount` balance from the state. -- Call house module's method to parse the ticket and validate. +- Retrieve the `subaccount` associated with the owner address from the state. +- Retrieve the balance of the `subaccount` from the state. +- Invoke the method of the **House Module** to parse the ticket and validate. - Return the withdrawal amount from the sub account balance. -- Call house module's Deposit method to set the participation. -- Set the new balance of the sub account module in the state. +- Invoke the Deposit method of the **House Module** to record the participation. +- Update the state with the new balance of the **Subaccount Module**. diff --git a/docs/specs/SubAccount/06_Events.md b/docs/specs/SubAccount/06_Events.md index 361b34e4..359b64f3 100644 --- a/docs/specs/SubAccount/06_Events.md +++ b/docs/specs/SubAccount/06_Events.md @@ -1,6 +1,6 @@ # **Events** -The Sub Account module emits the following events +The **Subaccount Module** emits the following events ## *MsgCreate* diff --git a/x/bet/types/params.go b/x/bet/types/params.go index 75bb0d48..2fd04c27 100644 --- a/x/bet/types/params.go +++ b/x/bet/types/params.go @@ -6,7 +6,6 @@ import ( "gopkg.in/yaml.v2" sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) @@ -134,7 +133,7 @@ func validateConstraints(i interface{}) error { return fmt.Errorf("%s: %T", ErrTextInvalidParamType, i) } - if v.MinAmount.LTE(sdk.OneInt()) { + if v.MinAmount.LTE(sdkmath.OneInt()) { return fmt.Errorf("minimum bet amount must be more than one: %d", v.MinAmount.Int64()) } diff --git a/x/house/types/params.go b/x/house/types/params.go index ad192a3d..dd35dfd2 100644 --- a/x/house/types/params.go +++ b/x/house/types/params.go @@ -6,7 +6,6 @@ import ( yaml "gopkg.in/yaml.v2" sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) @@ -97,7 +96,7 @@ func validateMinimumDeposit(i interface{}) error { return fmt.Errorf("invalid parameter type: %T", i) } - if v.LTE(sdk.OneInt()) { + if v.LTE(sdkmath.OneInt()) { return fmt.Errorf("minimum deposit must be positive and more than one: %d", v) } diff --git a/x/mint/simulation/genesis_test.go b/x/mint/simulation/genesis_test.go index 61bd123d..5cb12aa9 100644 --- a/x/mint/simulation/genesis_test.go +++ b/x/mint/simulation/genesis_test.go @@ -11,7 +11,6 @@ import ( sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -57,7 +56,7 @@ func TestRandomizedGenState(t *testing.T) { require.Equal( t, "0.000000000000000000", - mintGenesis.Minter.NextPhaseProvisions(sdk.OneInt(), types.DefaultExcludeAmount, types.NonePhase()). + mintGenesis.Minter.NextPhaseProvisions(sdkmath.OneInt(), types.DefaultExcludeAmount, types.NonePhase()). String(), ) require.Equal(t, "0.229787234042553191", params.GetPhaseAtStep(1).Inflation.String()) diff --git a/x/reward/keeper/reward.go b/x/reward/keeper/reward.go index 28473a72..2eee883a 100644 --- a/x/reward/keeper/reward.go +++ b/x/reward/keeper/reward.go @@ -54,12 +54,33 @@ func (k Keeper) GetAllRewards(ctx sdk.Context) (list []types.Reward) { return } +// GetAllRewardsOfReceiverByPromoterAndCategory returns all reward by promoter and category +func (k Keeper) GetAllRewardsOfReceiverByPromoterAndCategory(ctx sdk.Context) (list []types.RewardByCategory) { + store := k.getRewardByReceiverAndCategoryStore(ctx) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.RewardByCategory + k.cdc.MustUnmarshal(iterator.Value(), &val) + list = append(list, val) + } + + return +} + func (k Keeper) SetRewardOfReceiverByPromoterAndCategory(ctx sdk.Context, promoterUID string, rByCategory types.RewardByCategory) { store := k.getRewardByReceiverAndCategoryStore(ctx) b := k.cdc.MustMarshal(&rByCategory) store.Set(types.GetRewardsOfReceiverByPromoterAndCategoryKey(promoterUID, rByCategory.Addr, rByCategory.RewardCategory, rByCategory.UID), b) } +func (k Keeper) RemoveRewardOfReceiverByPromoterAndCategory(ctx sdk.Context, promoterUID string, rByCategory types.RewardByCategory) { + store := k.getRewardByReceiverAndCategoryStore(ctx) + store.Delete(types.GetRewardsOfReceiverByPromoterAndCategoryKey(promoterUID, rByCategory.Addr, rByCategory.RewardCategory, rByCategory.UID)) +} + // GetRewardsOfReceiverByPromoterAndCategory returns all rewards by address and category. func (k Keeper) GetRewardsOfReceiverByPromoterAndCategory( ctx sdk.Context, diff --git a/x/subaccount/keeper/subaccount_test.go b/x/subaccount/keeper/subaccount_test.go index ad79f73e..73900e66 100644 --- a/x/subaccount/keeper/subaccount_test.go +++ b/x/subaccount/keeper/subaccount_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/require" sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/sge-network/sge/testutil/sample" "github.com/sge-network/sge/x/subaccount/types" @@ -96,7 +95,7 @@ func TestSetBalances(t *testing.T) { DepositedAmount: sdkmath.ZeroInt(), SpentAmount: sdkmath.ZeroInt(), WithdrawnAmount: sdkmath.ZeroInt(), - LostAmount: sdk.OneInt(), + LostAmount: sdkmath.OneInt(), } subAccAddr := types.NewAddressFromSubaccount(1)