Skip to content

Commit

Permalink
added coin transfers
Browse files Browse the repository at this point in the history
  • Loading branch information
trevormil committed Apr 8, 2024
1 parent 2d6acca commit 41317d6
Show file tree
Hide file tree
Showing 10 changed files with 937 additions and 136 deletions.
3 changes: 1 addition & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ func New(
app.IBCKeeper.ChannelKeeper,
&app.IBCKeeper.PortKeeper,
scopedBadgesKeeper,
app.BankKeeper,
app.AccountKeeper,
)
badgesModule := badgesmodule.NewAppModule(appCodec, app.BadgesKeeper, app.AccountKeeper, app.BankKeeper)
Expand Down Expand Up @@ -633,8 +634,6 @@ func New(
badgesIBCModule := badgesmodule.NewIBCModule(app.BadgesKeeper)

wasmxModule := wasmx.NewAppModule(app.WasmxKeeper, app.AccountKeeper, app.BankKeeper)


scopedAnchorKeeper := app.CapabilityKeeper.ScopeToModule(anchormoduletypes.ModuleName)
app.ScopedAnchorKeeper = scopedAnchorKeeper
app.AnchorKeeper = *anchormodulekeeper.NewKeeper(
Expand Down
16 changes: 14 additions & 2 deletions proto/badges/transfers.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "gogoproto/gogo.proto";
import "badges/permissions.proto";
import "badges/address_lists.proto";
import "badges/balances.proto";
import "cosmos/base/v1beta1/coin.proto";

option go_package = "github.com/bitbadges/bitbadgeschain/x/badges/types";

Expand Down Expand Up @@ -304,6 +305,13 @@ message ZkProofSolution {
string proof = 2;
}

message CoinTransfer {
// The address of the recipient of the transfer.
string to = 1;
// The sdk.Coins to be transferred.
repeated cosmos.base.v1beta1.Coin coins = 2;
}

// ApprovalCriteria defines the criteria for approving transfers.
message ApprovalCriteria {
// List of badges that the user must own for approval.
Expand All @@ -318,6 +326,8 @@ message ApprovalCriteria {
MaxNumTransfers maxNumTransfers = 5;
// The ZKPs that need to be solved for approval.
repeated ZkProof zkProofs = 6;
// The sdk.Coins that need to be transferred for approval.
repeated CoinTransfer coinTransfers = 7;

// Require the "to" address to be equal to the "initiated by" address for approval.
bool requireToEqualsInitiatedBy = 9;
Expand All @@ -332,8 +342,6 @@ message ApprovalCriteria {
bool overridesFromOutgoingApprovals = 13;
// Overrides the user's incoming approvals for approval.
bool overridesToIncomingApprovals = 14;


}

// OutgoingApprovalCriteria defines the criteria for approving outgoing transfers.
Expand All @@ -350,6 +358,8 @@ message OutgoingApprovalCriteria {
MaxNumTransfers maxNumTransfers = 5;
// The ZKPs that need to be solved for approval.
repeated ZkProof zkProofs = 6;
// The sdk.Coins that need to be transferred for approval.
repeated CoinTransfer coinTransfers = 7;

// Require the "to" address to be equal to the "initiated by" address for approval.
bool requireToEqualsInitiatedBy = 9;
Expand All @@ -371,6 +381,8 @@ message IncomingApprovalCriteria {
MaxNumTransfers maxNumTransfers = 5;
// The ZKPs that need to be solved for approval.
repeated ZkProof zkProofs = 6;
// The sdk.Coins that need to be transferred for approval.
repeated CoinTransfer coinTransfers = 7;

// Require the "from" address to be equal to the "initiated by" address for approval.
bool requireFromEqualsInitiatedBy = 10;
Expand Down
3 changes: 3 additions & 0 deletions testutil/keeper/badges.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
"github.com/stretchr/testify/require"

bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"

accountkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
)

Expand Down Expand Up @@ -89,6 +91,7 @@ func BadgesKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
badgesPortKeeper{},
capabilityKeeper.ScopeToModule("BadgesScopedKeeper"),
//accountKeeper,
bankkeeper.BaseSendKeeper{},
accountkeeper.AccountKeeper{},
)

Expand Down
54 changes: 44 additions & 10 deletions x/badges/keeper/approved_transfers.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func (k Keeper) DeductAndGetUserApprovals(
})
}
}

//Keep a running tally of all the badges we still have to handle
remainingBalances := []*types.Balance{
{
Expand Down Expand Up @@ -191,6 +192,25 @@ func (k Keeper) DeductAndGetUserApprovals(
//return []*UserApprovalsToCheck{}, sdkerrors.Wrapf(ErrDisallowedTransfer, "transfer disallowed because to != initiatedBy: %s", transferStr)
}

//simulate the sdk.Coin transfers
coinTransfers := approvalCriteria.CoinTransfers
spendableCoins := k.bankKeeper.SpendableCoins(ctx, sdk.AccAddress(initiatedBy))
underflows := false
for _, coinTransfer := range coinTransfers {
toTransfer := coinTransfer.Coins
for _, coin := range toTransfer {
newCoins, underflow := spendableCoins.SafeSub(*coin)
if underflow {
underflows = true
}
spendableCoins = newCoins
}
}

if underflows {
continue
}

//Assert that initiatedBy owns the required badges
failedMustOwnBadges := false
for _, mustOwnBadge := range approvalCriteria.MustOwnBadges {
Expand Down Expand Up @@ -347,7 +367,7 @@ func (k Keeper) DeductAndGetUserApprovals(
}

//here, we assert the transfer is good for each level of approvals and increment if necessary
maxPossible, err := k.GetMaxPossible(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.OverallApprovalAmount, approvalCriteria.MaxNumTransfers.OverallMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "overall", "", true, )
maxPossible, err := k.GetMaxPossible(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.OverallApprovalAmount, approvalCriteria.MaxNumTransfers.OverallMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "overall", "", true)
if err != nil {
continue
}
Expand All @@ -356,7 +376,7 @@ func (k Keeper) DeductAndGetUserApprovals(
continue
}

maxPossible, err = k.GetMaxPossible(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerToAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerToAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "to", toAddress, true, )
maxPossible, err = k.GetMaxPossible(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerToAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerToAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "to", toAddress, true)
if err != nil {
continue
}
Expand All @@ -365,7 +385,7 @@ func (k Keeper) DeductAndGetUserApprovals(
continue
}

maxPossible, err = k.GetMaxPossible(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerFromAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerFromAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "from", fromAddress, true, )
maxPossible, err = k.GetMaxPossible(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerFromAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerFromAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "from", fromAddress, true)
if err != nil {
continue
}
Expand All @@ -374,7 +394,7 @@ func (k Keeper) DeductAndGetUserApprovals(
continue
}

maxPossible, err = k.GetMaxPossible(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerInitiatedByAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerInitiatedByAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "initiatedBy", initiatedBy, true, )
maxPossible, err = k.GetMaxPossible(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerInitiatedByAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerInitiatedByAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "initiatedBy", initiatedBy, true)
if err != nil {
continue
}
Expand All @@ -389,25 +409,25 @@ func (k Keeper) DeductAndGetUserApprovals(
}

//here, we assert the transfer is good for each level of approvals and increment if necessary
err = k.IncrementApprovalsAndAssertWithinThreshold(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.OverallApprovalAmount, approvalCriteria.MaxNumTransfers.OverallMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "overall", "", true, )
err = k.IncrementApprovalsAndAssertWithinThreshold(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.OverallApprovalAmount, approvalCriteria.MaxNumTransfers.OverallMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "overall", "", true)
if err != nil {
continue
//return []*UserApprovalsToCheck{}, sdkerrors.Wrapf(err, "exceeded overall approvals: %s", transferStr)
}

err = k.IncrementApprovalsAndAssertWithinThreshold(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerToAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerToAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "to", toAddress, true, )
err = k.IncrementApprovalsAndAssertWithinThreshold(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerToAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerToAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "to", toAddress, true)
if err != nil {
continue
//return []*UserApprovalsToCheck{}, sdkerrors.Wrapf(err, "exceeded to approvals: %s", transferStr)
}

err = k.IncrementApprovalsAndAssertWithinThreshold(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerFromAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerFromAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "from", fromAddress, true, )
err = k.IncrementApprovalsAndAssertWithinThreshold(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerFromAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerFromAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "from", fromAddress, true)
if err != nil {
continue
//return []*UserApprovalsToCheck{}, sdkerrors.Wrapf(err, "exceeded from approvals: %s", transferStr)
}

err = k.IncrementApprovalsAndAssertWithinThreshold(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerInitiatedByAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerInitiatedByAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "initiatedBy", initiatedBy, true, )
err = k.IncrementApprovalsAndAssertWithinThreshold(ctx, transferVal, approvalCriteria, overallTransferBalances, collection, approvalCriteria.ApprovalAmounts.PerInitiatedByAddressApprovalAmount, approvalCriteria.MaxNumTransfers.PerInitiatedByAddressMaxNumTransfers, transferBalancesToCheck, challengeNumIncrements, approverAddress, approvalLevel, "initiatedBy", initiatedBy, true)
if err != nil {
continue
//return []*UserApprovalsToCheck{}, sdkerrors.Wrapf(err, "exceeded initiatedBy approvals: %s", transferStr)
Expand All @@ -419,6 +439,20 @@ func (k Keeper) DeductAndGetUserApprovals(
continue
}

//execute the sdk.Coin transfers
coinTransfers = approvalCriteria.CoinTransfers
for _, coinTransfer := range coinTransfers {
coinsToTransfer := coinTransfer.Coins
toAddressAcc := sdk.AccAddress(coinTransfer.To)
fromAddressAcc := sdk.AccAddress(initiatedBy)
for _, coin := range coinsToTransfer {
err := k.bankKeeper.SendCoins(ctx, fromAddressAcc, toAddressAcc, sdk.NewCoins(*coin))
if err != nil {
return []*UserApprovalsToCheck{}, sdkerrors.Wrapf(err, "error sending coins after simulation: %s", transferStr)
}
}
}

//If the approval has challenges, we need to check that a valid solutions is provided for every challenge
//If the challenge specifies to use the leaf index for the number of increments, we use this value for the number of increments later
// If so, useLeafIndexForNumIncrements will be true
Expand Down Expand Up @@ -758,15 +792,15 @@ func (k Keeper) IncrementApprovalsAndAssertWithinThreshold(
(predeterminedBalances != nil && predeterminedBalances.OrderCalculationMethod.UsePerToAddressNumTransfers && trackerType == "to") ||
(predeterminedBalances != nil && predeterminedBalances.OrderCalculationMethod.UsePerFromAddressNumTransfers && trackerType == "from") ||
(predeterminedBalances != nil && predeterminedBalances.OrderCalculationMethod.UsePerInitiatedByAddressNumTransfers && trackerType == "initiatedBy") {

maxNumTransfersTrackerDetails.NumTransfers = maxNumTransfersTrackerDetails.NumTransfers.Add(sdkmath.NewUint(1))
//only check exceeds if maxNumTransfers is not 0 (because 0 means no limit)
if maxNumTransfers.GT(sdkmath.NewUint(0)) {
if maxNumTransfersTrackerDetails.NumTransfers.GT(maxNumTransfers) {
return sdkerrors.Wrapf(ErrDisallowedTransfer, "exceeded max transfers allowed - %s", maxNumTransfers.String())
}
}

}

if needToFetchApprovalTrackerDetails && !simulate {
Expand Down
Loading

0 comments on commit 41317d6

Please sign in to comment.