-
Notifications
You must be signed in to change notification settings - Fork 11
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
feat: Clawback Continuous Vesting Account #195
Conversation
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.
Just commenting since I'm not a cosmos expert.
It looks like we are replacing the original ContinousVestingAccoutns with Clawbackable ones. I thought we wanted both, more so for users than us; our personal main priority is Clawbacks for launch.
As for the legal stuff bc of licensing clash @jasperdg @mariocao I think GPLv3 is compatible with Apache 2. I believe this means we need to also include the Apache license. But might need to do more than that...
// NOTE: This code was taken from | ||
// https://github.com/agoric-labs/cosmos-sdk/blob/f42d86980ddfc07869846c391a03622cbd7e9188/x/staking/keeper/delegation.go#L701 | ||
// with slight modifications. |
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.
IDK who the right person to ask this question to is, but are we in the OK with their licensing and ours not conflicting?
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.
Ah yeah, they are Apache, and we are GPL. I think we have to include a copy of the Apache license now. But I'm no expert
} | ||
|
||
// MsgCreateVestingAccount defines a message that creates a vesting account. | ||
message MsgCreateVestingAccount { |
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.
Same question of does this prevent creating an original continuous vesting account? We still want that behavior(although less priority I suppose), on top of being able to create a clawback one.
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.
Or is this a entirely different vesting thing that just additionally gets added?
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.
Currently it cannot create an original continuous vesting account. Adding that would be quite simple though, as we can just add a boolean field to the message to indicate clawback or not.
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.
Honestly, I'm not positive if we want it or not, but I figured from a user perspective, to be able to do both might be nice. idk thoughts @mariocao?
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.
If it is so simple, yes, why not :)
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.
added a flag for disabling clawback.
Good points. We can support both SDK's |
When I run If you run breakpoints or add a panic like below in This confirms that the operation had failed in |
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.
Looks great. Particularly the core logic in func (m msgServer) Clawback
.
if err != nil { | ||
return errors.New("funder of vesting account must be provided using from flag") | ||
} |
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.
The error message is a bit ambiguous to me. "invalid funder address"
would make more sense imo. funder
on line 118 would be ""
if no funder address was provided in the flag.
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.
Also need to add a check for vestingStart > vestingEnd
.
// funder_address is the address which funded the account. | ||
string funder_address = 1; | ||
// account_address is the address of the vesting to claw back from. | ||
string account_address = 2; |
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.
Would be nice, almost necessary to add a dest_address
like Agoric did. Funder could've either rotated her keys, or had her original compromised. We need to give them an option to clawback the funds even if the original key was no longer accessible.
repeated cosmos.base.v1beta1.Coin clawed_unbonded = 1 [ | ||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", | ||
(gogoproto.nullable) = false | ||
]; | ||
|
||
repeated cosmos.base.v1beta1.Coin clawed_unbonding = 2 [ | ||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", | ||
(gogoproto.nullable) = false | ||
]; | ||
|
||
repeated cosmos.base.v1beta1.Coin clawed_bonded = 3 [ | ||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", | ||
(gogoproto.nullable) = false | ||
]; |
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.
nice addition!
|
||
// NOTE: errors checked during msg validation | ||
vestingAccAddr := sdk.MustAccAddressFromBech32(msg.AccountAddress) | ||
funderAddr := sdk.MustAccAddressFromBech32(msg.FunderAddress) |
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.
inb4 would be good to add a destination address like Agoric does.
|
||
toClawBack := coinsMin(vestingAccount.GetVestingCoins(ctx.BlockTime()), total) // might have been slashed | ||
|
||
// Write now now so that the bank module sees unvested tokens are unlocked. |
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.
duplicate now
func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*types.MsgClawbackResponse, error) { | ||
ctx := sdk.UnwrapSDKContext(goCtx) | ||
|
||
// NOTE: errors checked during msg validation |
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 is this msg validation?
Motivation
This PR implements a custom vesting account type
ClawbackContinuousVestingAccount
that wraps the SDK'sContinuousVestingAccount
to provide an additional feature of "clawing back" funds to the funder of the account. Note that now this custom type is the only vesting account type our chain supports.Explanation of Changes
The sender of the
create-vesting-account
transaction is registered as thefunder
of the vesting account so that when thefunder
later sends aclawback
transaction, the vesting (= unvested) funds are returned back to thefunder
. The implementation is complicated by the fact that the funds can be in various states. The funds are clawed-back from different sources in the following order: Unbonded (through standard bank module transfer) -> Unbonding delegations -> Bonded delegations (which may also be going through redelegation process). The transfer logic is taken from Agoric'sTransferDelegation
andTransferUnbonding
. To integrate these staking keeper methods, we wire to the app the custom staking module that wraps the SDK's staking module. However, as evident inx/staking/module.go
, the SDK's default staking handles the remaining functionalities of the staking module, and most of the code present in the custom staking module such as thecreate-validator-vrf
transaction remains unactivated.The clawed back amount is guaranteed to be all of the currently vesting amount, unless the vesting account's delegation has been slashed, and the account doesn't have sufficient unbonded funds to make up for the loss.
How to use the transactions:
tx create-vesting-account [to_address] [amount] [end_time]
for creating aClawbackContinuousVestingAccount
--disable-clawback
to disallow clawback. If this flag is present, thefunder
field of the vesting account will be empty.tx clawback [address]
Testing
Integration testing and simulation testing
Related PRs and Issues
Closes #194