-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Application] feat: app stake transfer (#743)
## Summary - Add `MsgTransferApplicationStake`. - Implement application stake transfer to new "beneficiary" application (unstakes original application). ## Dependents - #788 - #789 ## Issue - #657 ## Type of change Select one or more: - [x] New feature, functionality or library - [ ] Bug fix - [ ] Code health or cleanup - [ ] Documentation - [ ] Other (specify) ## Testing **Documentation changes** (only if making doc changes) - [ ] `make docusaurus_start`; only needed if you make doc changes **Local Testing** (only if making code changes) - [x] **Unit Tests**: `make go_develop_and_test` - [x] **LocalNet E2E Tests**: `make test_e2e` - See [quickstart guide](https://dev.poktroll.com/developer_guide/quickstart) for instructions **PR Testing** (only if making code changes) - [x] **DevNet E2E Tests**: Add the `devnet-test-e2e` label to the PR. - **THIS IS VERY EXPENSIVE**, so only do it after all the reviews are complete. - Optionally run `make trigger_ci` if you want to re-trigger tests without any code changes - If tests fail, try re-running failed tests only using the GitHub UI as shown [here](https://github.com/pokt-network/poktroll/assets/1892194/607984e9-0615-4569-9452-4c730190c1d2) ## Sanity Checklist - [x] I have tested my changes using the available tooling - [x] I have commented my code - [x] I have performed a self-review of my own code; both comments & source code - [ ] I create and reference any new tickets, if applicable - [x] I have left TODOs throughout the codebase, if applicable --------- Co-authored-by: Daniel Olshansky <[email protected]>
- Loading branch information
1 parent
f7b5794
commit bad0e8a
Showing
15 changed files
with
2,196 additions
and
206 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
Feature: App Stake Transfer Namespace | ||
|
||
Scenario: User can transfer Application stake to non-existing application address | ||
Given the user has the pocketd binary installed | ||
# Unstake the applications in case they're already staked. | ||
And this test ensures the "application" for account "app2" is not staked | ||
And this test ensures the "application" for account "app3" is not staked | ||
# Stake with 1 uPOKT more than the current stake used in genesis to make | ||
# the transaction succeed. | ||
And the account "app2" has a balance greater than "1000070" uPOKT | ||
And an account exists for "app3" | ||
And the user successfully stakes a "application" with "1000070" uPOKT for "anvil" service from the account "app2" | ||
When the user transfers the "application" stake from account "app2" to account "app3" | ||
Then the user should be able to see standard output containing "txhash:" | ||
And the user should be able to see standard output containing "code: 0" | ||
And the pocketd binary should exit without error | ||
And the user should wait for the "application" module "TransferApplicationStake" message to be submitted | ||
And the "application" for account "app3" is staked with "1000070" uPOKT | ||
And the account balance of "app3" should be "0" uPOKT "less" than before | ||
And the user verifies the "application" for account "app2" is not staked | ||
And the account balance of "app2" should be "0" uPOKT "more" than before |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
//go:build e2e | ||
|
||
package e2e | ||
|
||
import ( | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func (s *suite) TheUserSuccessfullyStakesAWithUpoktForServiceFromTheAccount(actorType string, amount int64, serviceId, accName string) { | ||
s.TheUserStakesAWithUpoktForServiceFromTheAccount(actorType, amount, serviceId, accName) | ||
s.TheUserShouldBeAbleToSeeStandardOutputContaining("txhash:") | ||
s.TheUserShouldBeAbleToSeeStandardOutputContaining("code: 0") | ||
s.ThePocketdBinaryShouldExitWithoutError() | ||
s.TheUserShouldWaitForTheModuleMessageToBeSubmitted("application", "StakeApplication") | ||
s.TheForAccountIsStakedWithUpokt(actorType, accName, amount) | ||
s.TheAccountBalanceOfShouldBeUpoktThanBefore(accName, amount, "less") | ||
} | ||
|
||
func (s *suite) TheUserTransfersTheStakeFromAccountToAccount(actorType, fromAccName, toAccName string) { | ||
fromAddr, fromAddrIsFound := accNameToAddrMap[fromAccName] | ||
require.Truef(s, fromAddrIsFound, "account name %s not found in accNameToAddrMap", fromAccName) | ||
|
||
toAddr, toAddrIsFound := accNameToAddrMap[toAccName] | ||
require.Truef(s, toAddrIsFound, "account name %s not found in accNameToAddrMap", toAccName) | ||
|
||
args := []string{ | ||
"tx", | ||
actorType, | ||
"transfer", | ||
fromAddr, | ||
toAddr, | ||
"--from", | ||
fromAccName, | ||
keyRingFlag, | ||
chainIdFlag, | ||
"-y", | ||
} | ||
res, err := s.pocketd.RunCommandOnHost("", args...) | ||
require.NoError(s, err) | ||
|
||
s.pocketd.result = res | ||
} | ||
|
||
// This helper ensures that the actor is unstaked if it was staked when this step ran. | ||
func (s *suite) ThisTestEnsuresTheForAccountIsNotStaked(actorType, accName string) { | ||
if _, ok := s.getStakedAmount(actorType, accName); ok { | ||
s.TheUserUnstakesAFromTheAccount(actorType, accName) | ||
s.TheUserShouldBeAbleToSeeStandardOutputContaining("txhash:") | ||
s.TheUserShouldBeAbleToSeeStandardOutputContaining("code: 0") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
x/application/keeper/msg_server_transfer_application_stake.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package keeper | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/pokt-network/poktroll/telemetry" | ||
"github.com/pokt-network/poktroll/x/application/types" | ||
) | ||
|
||
// TransferApplicationStake transfers the stake (held in escrow in the application | ||
// module account) from a source to a (new) destination application account . | ||
func (k msgServer) TransferApplicationStake(ctx context.Context, msg *types.MsgTransferApplicationStake) (*types.MsgTransferApplicationStakeResponse, error) { | ||
isSuccessful := false | ||
defer telemetry.EventSuccessCounter( | ||
"transfer_application_stake", | ||
telemetry.DefaultCounterFn, | ||
func() bool { return isSuccessful }, | ||
) | ||
|
||
logger := k.Logger().With("method", "TransferApplicationStake") | ||
|
||
if err := msg.ValidateBasic(); err != nil { | ||
return nil, err | ||
} | ||
|
||
// Ensure destination application does not already exist. | ||
_, isDstFound := k.GetApplication(ctx, msg.GetDestinationAddress()) | ||
if isDstFound { | ||
return nil, types.ErrAppDuplicateAddress.Wrapf("destination application (%q) exists", msg.GetDestinationAddress()) | ||
} | ||
|
||
// Ensure source application exists. | ||
srcApp, isAppFound := k.GetApplication(ctx, msg.GetSourceAddress()) | ||
if !isAppFound { | ||
return nil, types.ErrAppNotFound.Wrapf("source application %q not found", msg.GetSourceAddress()) | ||
} | ||
|
||
// Ensure source application is not already unbonding. | ||
// TODO_TEST: Add E2E coverage to assert that an unbonding app cannot be transferred. | ||
if srcApp.IsUnbonding() { | ||
return nil, types.ErrAppIsUnstaking.Wrapf("cannot transfer stake of unbonding source application %q", msg.GetSourceAddress()) | ||
} | ||
|
||
// Create a new application derived from the source application. | ||
dstApp := srcApp | ||
dstApp.Address = msg.GetDestinationAddress() | ||
|
||
// TODO_NEXT(#789): Reconcile app unbonding logic with the new transfer stake logic. | ||
// I.e., the source should not immediately be transferred. | ||
|
||
// TODO_TEST: add E2E coverage to assert #DelegateeGatewayAddresses and #PendingUndelegations | ||
// are present and correct on the dstApp application. | ||
|
||
// Update the dstApp in the store | ||
k.SetApplication(ctx, dstApp) | ||
logger.Info(fmt.Sprintf("Successfully transferred application stake from (%s) to (%s)", srcApp.Address, dstApp.Address)) | ||
|
||
// Remove the transferred app from the store | ||
k.RemoveApplication(ctx, srcApp.GetAddress()) | ||
logger.Info(fmt.Sprintf("Successfully removed the application: %+v", srcApp)) | ||
|
||
isSuccessful = true | ||
|
||
return &types.MsgTransferApplicationStakeResponse{ | ||
Application: &dstApp, | ||
}, nil | ||
} |
Oops, something went wrong.