-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
Total Supply Feature #3972
Comments
Call with alessio: |
@rigelrozanski can you provide more details on the "registry" of coins held by each module ? |
@fedekunze The bank module needs to expose special functions which each module can inform the bank module's supply that is holding tokens. For example, when a proposal has funds deposited into it the func (k bank.Keeper) RequestTokens(module string, amount sdk.Coins) error {
... cause error if not enough tokens in supply as requested
}
func (k bank.Keeper) RelinquishTokens(module string, amount sdk.Coins) error {
... cause error if not enough tokens are held by that module to relinquish
}
// additionally the minting module would need to be allowed to "create" tokens
// which would be held with that module (hence they could be Relinquished)
func (k bank.Keeper) CreateTokens(module string, amount sdk.Coins) error {
} These functions are implicitly permissioned by each module by including these functions in their expected keeper for |
Just had a cool design thought. Rather than the functions I'd suggested up there. We could implement special structures which permission func TokenHolder struct {
moduleName // not-exposed
}
func (t TokenHolder) RequestTokens(amount sdk.Coins) error {
}
func (t TokenHolder) RelinquishTokens(amount sdk.Coins) error {
}
func TokenMinter struct {
moduleName // not-exposed
}
func (t TokenHolder) CreateTokens(amount sdk.Coins) error {
}
func (t TokenHolder) RelinquishTokens(amount sdk.Coins) error {
} Then in govTokenHolder := bank.NewTokenHolder(gov.ModuleName)
govKeeper := gov.NewKeeper(...., govTokenHolder, ...) |
@rigelrozanski would that require an extra parameter for each of the modules' genesis ? If we want to calculate the total supply from all the holdings, we need to expose that, right ? |
fede
|
I mean ideally we should just iterate all objects and populate each modules accounting during genesis. Meaning that each module would also be required to fulfill an interface: type TokenHolder interface {
func CalculateTokenHoldings() sdk.Coin
} also related, this would mean that each modules' keeper will require an extra argument (of the keepers which need to mint coins or store coins aka: |
Also based on conversations with @alessio and I - it seems logical that this feature should actually be a unique module - not sure what to call it though. Maybe let's call it |
I like |
So we're proposing a new module, called |
@rigelrozanski would accounts balance's coins fall under some sort of |
|
@fedekunze please look at the staking code which already does this... they should be passively accounted for by @alexanderbez so the rational behind having a new module in my mind is that the functionality of bank is completely independent of the supply feature - bank functions without supply. Following the module pattern we have going it would seem reasonable to include this feature in a new module which then allows other projects to take advantage of the |
I still don't quite understand the abstraction and separation of
This is the current case yes, but one that does not make intuitive sense to me. Also, with regards to the conversation above. When sending tokens or tracking tokens via modules, would it be possible to perhaps use module accounts (where no individual controls the private key) instead of this "request" or "relinquish" logic? EDIT: After some thinking, I see what you mean by the module pattern. The separation of tl;dr: If modularity is what we're going for, then this makes sense and we can have these micro-modules. |
I like the idea of having a couple (holder, minter) special account types for module to use... I wonder if there is a nice way to allow bank to use multiple account types simultaneously? This said, we still need a way to passively track token flow from user accounts to special accounts and vice versa. Which means that these types of special module accounts would be required to have the logic to "take" tokens from the senders address (right now modules effectively just burn these tokens and then credit an internal tracking system and then later create new tokens in accounts) I like this idea though |
Since the account keeper returns an
Hmm, can you elaborate on what you mean by "passively track" and "take"? Would it not suffice to just do a |
"take" - currently when gov or staking executes a transaction, it removes tokens from the sender account and adds it to a new accounting mechanism - here the staking transaction is "taking" coins from this account. This means that these module accounts are not accounts that you send tokens too, they operate by taking coins from the sender within the module. hence it actually would not suffice to just do a "passively track" - the side note staking would need two of these module accounts, one for bonded tokens held in staking protocol, and one for unbonded tokens held in staking protocol |
Got it, makes sense. Thanks @rigelrozanski |
Conclusion thoughts from some of this discussion. I think we can really go two ways on this feature.
based on this thinking I think it makes sense to build out in a separate module, Additionally, I foresee both options being comparable to implement so I suggest we implement the module accounts option from the get-go. |
Great, thanks for the feedback @rigelrozanski. It seems we can incorporate ideas from both proposals. A separate module (for modularity/composability) and first-class citizen account types for modules (taker/maker). |
Seems like ACs need update then |
@rigelrozanski What I don't fully understand is when you request tokens (via
Cool, I'll move the supply logic into a new module then.
Agree, @rigelrozanski @alessio @alexanderbez Could you help me clarifying all the remaining TODOs based on our recent discussion ? |
Meanwhile, moving this back to |
@fedekunze This said again let's not implement this original design, and instead develop the module-account design as has been discussed.
I can't do all the werk :P ! wanna create a new altered TODO list based on the module-account design? |
there's an issue using accounts since if we use them it will cause a circular dependency between |
Why are we tracking vesting supply? We're not right now afaik.
Can we not use the "expected keepers" pattern we've been using? ie. |
Indeed, but if we want to track circulating supply we need to track the supply update when the vesting period ends. Imho the original implementation without accounts is simpler if we want to track changes in the supply. cc: @rigelrozanski @alessio what do you think |
More discussions with @fedekunze around design All the functionality of permissioning whether or not an account can create tokens should not be done through the module account - but through the // (different that bank!)
type SendKeeper interface {
ViewKeeper
SendCoinsToAccount(ctx sdk.Context, module string, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error
SendCoinsToModule(ctx sdk.Context, fromModule, toModule string, amt sdk.Coins) sdk.Error
MintCoins(ctx sdk.Context, module) sdk.Error // panic if used with with holder account
GetSendEnabled(ctx sdk.Context) bool
SetSendEnabled(ctx sdk.Context, enabled bool)
}
// same as regular bank module (probably just reference the bank module interface directly)
type ViewKeeper interface {
GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool
Codespace() sdk.CodespaceType
} This is just a first stab at this idea, while implementing there may be a better way to separate the |
Description
The bank module should be in charge of calculating the total supply of coins, not staking. This is important so that other modules (such as governance) can store coins in non-account objects (and register these changes with the total-supply-calculator)
Blocks #3628, #1980
Relevant work was completed here: #2939
Acceptance Criteria
AC1
Given a module's keeper that has access to a
supply
module keeperWhen the module's keeper calls a
supply
keeper'sHoldCoins(coins sdk.Coins)
methodThen the
supply
module keeper can keep track of it.AC2
Given a module's keeper that has access to a
supply
module keeperWhen the module's keeper calls a
supply
keeper'sReleaseCoins(coins sdk.Coins)
methodThen the
supply
module keeper can keep track of it.Technical Details
bank/keepers/supply.go
:func GetTotalSupply(ctx sdk.Context) sdk.Coins
: returns total supply of all the coins in the networkfunc GetTotalSupplyByCoin(denom string) sdk.Int, sdk.Error
: returns the supply per coin denom or errorsfunc SetTotalSupplyByCoin(ctx sdk.Context, coin sdk.Coin)
: sets the total supply of a specific coin denom.(keeper BaseKeeper) InflateSupply(ctx sdk.Context, mintedCoins sdk.Coins)
: adds new minted coins to supplyinflateSupply(ctx sdk.Context, mintedCoin sdk.Coin) sdk.Error
: adds the minted coin to the current supply for that coin and sets the total to the param store.Add invariance check
The text was updated successfully, but these errors were encountered: