-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TEST-7: add exchange rate #17
Conversation
Can you add more detail in the summary on the specific files / functions to pay attention to in this PR? It would make it easier for me to give a good review, it's hard to do so when so many LOC have changed (especially when the logic is sensitive). Thought Vishal did a good job of this here as an example! #14 |
Is the content of TEST-7 in Jira what you're looking for? https://stridelabs.atlassian.net/jira/software/projects/TEST/boards/2?selectedIssue=TEST-7. Generally been putting much more detail there than the PRs but happy to copy over or format like Vishal's #14 if that makes things easier |
This should be a cleaner PR now that I moved third_party to its own branch |
Ticket has the high level context yeah - a couple of bullet point style pointers from the ticket tasks to files / places in code that implement the relevant logic would still be helpful so that I know which parts of the code require the most attention as a reviewer (especially on large PRs that have >1k LOC) |
Thanks this makes a lot of sense. Updated the comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool to see this coming together! Realize this is a draft but left a few comments
const ( | ||
HostZoneKey = "HostZone-value-" | ||
HostZoneCountKey = "HostZone-count-" | ||
prefixZone = iota + 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think iota
just resolves to 0, are all of these keys 1? Should they be strings?
repeated Validator blacklistedValidators = 4; | ||
repeated ICAAccount rewardsAccount = 5; | ||
repeated ICAAccount feeAccount = 6; | ||
uint64 id = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing proto field ids around like this is risky in production (had a similar comment on another PR that went into depth here) but probably ok given we haven't launched any testnet / mainnet yet
string channelId = 4; | ||
string connectionID = 5; | ||
repeated Validator validators = 6; | ||
repeated ICAAccount delegationAccounts = 7; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a rewardsAccount
and a feeAccount
here? Also, commented on another PR that all of these ICAAccount
s should be singular fields (I think)
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", | ||
(gogoproto.nullable) = false | ||
]; | ||
string totalAllBalances = 12 [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
string totalAllBalances = 12 [ | |
string totalBalances = 12 [ |
} | ||
|
||
switch query_type { | ||
case "totalBalance": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does the syntax for these queries come from? Looks like we're using camelcase?
) | ||
|
||
// is this the right keeper? | ||
func (k Keeper) getStTokenExchRate(ctx sdk.Context, hostZone types.HostZone, inclOutstandingRewards bool) (sdk.Dec, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func (k Keeper) getStTokenExchRate(ctx sdk.Context, hostZone types.HostZone, inclOutstandingRewards bool) (sdk.Dec, error) { | |
func (k Keeper) updateStTokenExchRate(ctx sdk.Context, hostZone types.HostZone, inclOutstandingRewards bool) (sdk.Dec, error) { |
suggest this name change so that it's clear this updates the store, and the exchange rate can then be fetched from the store
supplyOfStTokens := k.bankKeeper.GetSupply(ctx, hostZone.StDenom) | ||
k.Logger(ctx).Info("stAsset outstanding supply:", supplyOfStTokens) | ||
|
||
exchRate := balOfVirtualPoolOnHost.Quo(supplyOfStTokens.Amount.ToDec()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than returning an exchange rate, should this just update a variable in the store? That way, we could put this call in the BeginBlocker
or EndBlocker
(or even in an epoch) and just update the exchange rate on some cadence
k.Logger(ctx).Error("Unable to unmarshal validators info for zone", "zone", zone.ChainId, "err", err) | ||
return err | ||
} | ||
hostZone.TotalAllBalances = sdk.Dec(queryRes.Balances.AmountOf(hostZone.BaseDenom)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this update will have any effect on the store (if that's the intention), I think you need to update the variable then set it in the store.
Also not totally sure whether this variable is scoped to the cbTotalBalance
function or if updates persist outside that scope
Closing this as it's subsumed by TEST-50 |
DO NOT MERGE, LOGIC NOT FINISHED YET
Summary:
Implemented logic to calculate the exchange rate between stToken/Token at deposit and unbonding. The main complication along the way is not being able to figure out how to get return values out of asynchronous ICQ calls, so having to write the result to state rather than handle it in-memory. This required the creation of interchainstaking store variables.
We need rigorous testing in this code (it’s exploitable); this is just a v0 of the logic.
Pointers for review:
stride/x/stakeibc/keeper/exchange_rate.go
, where two functions live:-
getStTokenExchRate
calcalates the exchange rate between stAsset/Asset using as a helper theICQQueryHostBalance
function. We useBankKeeper
'sGetSupply
function to calculate supply of stAsset (same approach as QS to calculating stAsset supply). For deposits,inclOutstandingRewards
param should be true, for withdrawals, false.-
ICQQueryHostBalance
submits an ICQ call to measure the amount of tokens on host chain either across all delegation accounts, delegated, or in outstanding accrued rewards. Results are written to the host_zone state rather than returned (due to technical limitations described in summary).proto/stakeibc/host_zone.proto
, addedconnectionID
, denominations and state variables used to calc exchange rate (they're updated to measure host zone delegations and balances). RemovedrewardsAccount
.stride/proto/stakeibc/params.proto
, remove unusedica_account.proto
importstride/x/stakeibc/keeper/exchange_rate.go
, replace BinaryCodec with Codec (the former does not allow forcdc.UnmarshalJSON
calls required in exchange_rate calc, the latter does. Also, addbankKeeper
for exchange_rate stAsset supply calcs.stride/x/stakeibc/keeper/zones.go
, containing helpers for zones. We could move these functions tozones.go
to simplify. <==**TODO
move to zones.go **stride/x/stakeibc/types/keys.go
, added prefixes. We may not need these. <==**TODO
remove these **For more details see Jira TEST-7
Note I had to add third_party folder to get this working