Skip to content

Commit

Permalink
#1263 implement as per request, still keeping bips as an option but f…
Browse files Browse the repository at this point in the history
…or now it all goes to the recipient, see comment // AssessCustomMsgFeeBips is the bips the recipient will get

	// This should be a message level data (present in TypeAssessCustomMsgFee = assess_custom_msg_fee) i think so that it can be defined by the smart contract writer
	// or at the very least it can be a module param.
	// for now i am hard coding it to avoid breaking any clients and because of this ticket #1263
	AssessCustomMsgFeeBips = 10_000
  • Loading branch information
arnabmitra committed Dec 15, 2022
1 parent 6354efc commit c50f8cb
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 36 deletions.
6 changes: 2 additions & 4 deletions docs/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5602,10 +5602,8 @@ MsgAssessCustomMsgFeeRequest defines an sdk.Msg type
| ----- | ---- | ----- | ----------- |
| `name` | [string](#string) | | optional short name for custom msg fee, this will be emitted as a property of the event |
| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount of additional fee that must be paid |
| `recipient` | [string](#string) | | optional recipient address, the amount is split 50/50 between recipient and fee module. If |
| `from` | [string](#string) | | empty, whole amount goes to fee module

the signer of the msg |
| `recipient` | [string](#string) | | optional recipient address, the total amount is given to the recipient, if present. |
| `from` | [string](#string) | | the signer of the msg |



Expand Down
5 changes: 4 additions & 1 deletion internal/handlers/msg_service_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,10 @@ func (msr *PioMsgServiceRouter) consumeMsgFees(ctx sdk.Context, req sdk.Msg) err
}

msgTypeURL := sdk.MsgTypeURL(req)
feeGasMeter.ConsumeFee(feeDist.AdditionalModuleFees, msgTypeURL, "")
// since AccessMsgFee is not always split 50/50 anymore, this fee can be nil when recipients are specified.
if feeDist.AdditionalModuleFees != nil {
feeGasMeter.ConsumeFee(feeDist.AdditionalModuleFees, msgTypeURL, "")
}
for _, recipient := range sortedKeys(feeDist.RecipientDistributions) {
coins := feeDist.RecipientDistributions[recipient]
feeGasMeter.ConsumeFee(coins, msgTypeURL, recipient)
Expand Down
87 changes: 82 additions & 5 deletions internal/handlers/msg_service_router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ func TestMsgServiceAssessMsgFee(tt *testing.T) {
addr1AfterBalance := app.BankKeeper.GetAllBalances(ctx, addr1).String()
addr2AfterBalance := app.BankKeeper.GetAllBalances(ctx, addr2).String()
assert.Equal(t, "1000hotdog,1000stake", addr1AfterBalance, "addr1AfterBalance")
assert.Equal(t, "87500000nhash", addr2AfterBalance, "addr2AfterBalance")
assert.Equal(t, "175000000nhash", addr2AfterBalance, "addr2AfterBalance") // addr2 gets all the fee as recipient

expEvents := []abci.Event{
NewEvent(sdk.EventTypeTx,
Expand All @@ -717,15 +717,92 @@ func TestMsgServiceAssessMsgFee(tt *testing.T) {
NewAttribute(sdk.AttributeKeyFeePayer, addr1.String())),
NewEvent("provenance.msgfees.v1.EventMsgFees",
NewAttribute("msg_fees", jsonArrayJoin(
msgFeesEventJSON("/provenance.msgfees.v1.MsgAssessCustomMsgFeeRequest", 1, 87500000, "nhash", ""),
msgFeesEventJSON("/provenance.msgfees.v1.MsgAssessCustomMsgFeeRequest", 1, 87500000, "nhash", addr2.String())))),
//msgFeesEventJSON("/provenance.msgfees.v1.MsgAssessCustomMsgFeeRequest", 1, 87500000, "nhash", ""),
msgFeesEventJSON("/provenance.msgfees.v1.MsgAssessCustomMsgFeeRequest", 1, 175000000, "nhash", addr2.String())))),
}
// fee charge in antehandler
expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), feeModuleAccount.GetAddress().String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 1015500001)))...)
// fee charged for msg based fee to fee module on assess msg split
expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), feeModuleAccount.GetAddress().String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 87500000)))...)
//expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), feeModuleAccount.GetAddress().String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 87500000)))...)
// fee charged for msg based fee to recipient from assess msg split
expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), addr2.String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 87500000)))...)
expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), addr2.String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 175000000)))...)
// swept amount
expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), feeModuleAccount.GetAddress().String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 1015500001)))...)

assertEventsContains(t, res.Events, expEvents)
})
}

func TestMsgServiceAssessMsgFeeNoRecipient(tt *testing.T) {
pioconfig.SetProvenanceConfig("", 0)
pioconfig.ChangeMsgFeeFloorDenom(1, sdk.DefaultBondDenom)

encCfg := sdksim.MakeTestEncodingConfig()
priv, _, addr1 := testdata.KeyTestPubAddr()
_, _, addr2 := testdata.KeyTestPubAddr()
acct1 := authtypes.NewBaseAccount(addr1, priv.PubKey(), 0, 0)
acct1Balance := sdk.NewCoins(
sdk.NewInt64Coin("hotdog", 1000),
sdk.NewInt64Coin(sdk.DefaultBondDenom, 101000),
sdk.NewInt64Coin(NHash, 1_190_500_001),
)
app := piosimapp.SetupWithGenesisAccounts(tt, "msgfee-testing",
[]authtypes.GenesisAccount{acct1},
banktypes.Balance{Address: addr1.String(), Coins: acct1Balance},
)
ctx := app.BaseApp.NewContext(false, tmproto.Header{ChainID: "msgfee-testing"})
app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams())
feeModuleAccount := app.AccountKeeper.GetModuleAccount(ctx, authtypes.FeeCollectorName)

// Check both account balances before we start.
addr1beforeBalance := app.BankKeeper.GetAllBalances(ctx, addr1).String()
addr2beforeBalance := app.BankKeeper.GetAllBalances(ctx, addr2).String()
assert.Equal(tt, "1000hotdog,1190500001nhash,101000stake", addr1beforeBalance, "addr1beforeBalance")
assert.Equal(tt, "", addr2beforeBalance, "addr2beforeBalance")
stopIfFailed(tt)
tt.Run("assess custom msg fee", func(t *testing.T) {
msgFeeCoin := sdk.NewInt64Coin(msgfeestypes.UsdDenom, 7)
msg := msgfeestypes.NewMsgAssessCustomMsgFeeRequest("test", msgFeeCoin, "", addr1.String())
fees := sdk.NewCoins(
sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000),
sdk.NewInt64Coin(NHash, 1_190_500_001),
)
txBytes, err := SignTxAndGetBytes(NewTestGasLimit(), fees, encCfg, priv.PubKey(), priv, *acct1, ctx.ChainID(), &msg)
require.NoError(t, err, "SignTxAndGetBytes")
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.Equal(t, abci.CodeTypeOK, res.Code, "res=%+v", res)

addr1AfterBalance := app.BankKeeper.GetAllBalances(ctx, addr1).String()
//addr2AfterBalance := app.BankKeeper.GetAllBalances(ctx, addr2).String()
assert.Equal(t, "1000hotdog,1000stake", addr1AfterBalance, "addr1AfterBalance")
//assert.Equal(t, "175000000nhash", addr2AfterBalance, "addr2AfterBalance") // addr2 gets all the fee as recipient

expEvents := []abci.Event{
NewEvent(sdk.EventTypeTx,
NewAttribute(sdk.AttributeKeyFee, "1190500001nhash,100000stake"),
NewAttribute(sdk.AttributeKeyFeePayer, addr1.String())),
NewEvent(sdk.EventTypeTx,
NewAttribute(antewrapper.AttributeKeyMinFeeCharged, "100000stake"),
NewAttribute(sdk.AttributeKeyFeePayer, addr1.String())),
NewEvent(msgfeestypes.EventTypeAssessCustomMsgFee,
NewAttribute(msgfeestypes.KeyAttributeName, "test"),
NewAttribute(msgfeestypes.KeyAttributeAmount, "7usd"),
NewAttribute(msgfeestypes.KeyAttributeRecipient, "")),
NewEvent(sdk.EventTypeTx,
NewAttribute(antewrapper.AttributeKeyAdditionalFee, "175000000nhash"),
NewAttribute(antewrapper.AttributeKeyBaseFee, "1015500001nhash,100000stake"),
NewAttribute(sdk.AttributeKeyFeePayer, addr1.String())),
NewEvent("provenance.msgfees.v1.EventMsgFees",
NewAttribute("msg_fees", jsonArrayJoin(
msgFeesEventJSON("/provenance.msgfees.v1.MsgAssessCustomMsgFeeRequest", 1, 175000000, "nhash", "")))),
//msgFeesEventJSON("/provenance.msgfees.v1.MsgAssessCustomMsgFeeRequest", 1, 175000000, "nhash", addr2.String())))),
}
// fee charge in antehandler
expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), feeModuleAccount.GetAddress().String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 1015500001)))...)
// fee charged for msg based fee to fee module on assess msg split
//expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), feeModuleAccount.GetAddress().String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 87500000)))...)
// fee charged for msg based fee to recipient from assess msg split
//expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), addr2.String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 175000000)))...)
// swept amount
expEvents = append(expEvents, CreateSendCoinEvents(addr1.String(), feeModuleAccount.GetAddress().String(), sdk.NewCoins(sdk.NewInt64Coin("nhash", 1015500001)))...)

Expand Down
5 changes: 2 additions & 3 deletions proto/provenance/msgfees/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ message MsgAssessCustomMsgFeeRequest {

string name = 1; // optional short name for custom msg fee, this will be emitted as a property of the event
cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false]; // amount of additional fee that must be paid
string recipient = 3; // optional recipient address, the amount is split 50/50 between recipient and fee module. If
// empty, whole amount goes to fee module
string from = 4; // the signer of the msg
string recipient = 3; // optional recipient address, the total amount is given to the recipient, if present.
string from = 4; // the signer of the msg
}

// MsgAssessCustomMsgFeeResponse defines the Msg/AssessCustomMsgFeee response type.
Expand Down
36 changes: 19 additions & 17 deletions x/msgfees/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ func (s *TestSuite) TestCalculateAdditionalFeesToBePaid() {
s.Run("send and custom with recipient", func() {
expected := types.MsgFeesDistribution{
TotalAdditionalFees: nhashCoins(2_000_000_000),
AdditionalModuleFees: nhashCoins(1_500_000_000),
AdditionalModuleFees: nhashCoins(1_000_000_000),
RecipientDistributions: map[string]sdk.Coins{
"recipient1": nhashCoins(500_000_000),
"recipient1": nhashCoins(1_000_000_000),
},
}
assessFee := types.NewMsgAssessCustomMsgFeeRequest("", oneHash, "recipient1", someAddress.String())
Expand All @@ -254,10 +254,10 @@ func (s *TestSuite) TestCalculateAdditionalFeesToBePaid() {
s.Run("send and two customs with different recipients", func() {
expected := types.MsgFeesDistribution{
TotalAdditionalFees: nhashCoins(2_500_000_000),
AdditionalModuleFees: nhashCoins(1_750_000_000),
AdditionalModuleFees: nhashCoins(1_000_000_000), // only gets 1 hash from msgfees.
RecipientDistributions: map[string]sdk.Coins{
"recipient1": nhashCoins(500_000_000),
"recipient2": nhashCoins(250_000_000),
"recipient1": nhashCoins(1_000_000_000), // gets 1 hash
"recipient2": nhashCoins(500_000_000), // gets 0.5 hash
},
}
assessFee1 := types.NewMsgAssessCustomMsgFeeRequest("", oneHash, "recipient1", someAddress.String())
Expand All @@ -270,9 +270,9 @@ func (s *TestSuite) TestCalculateAdditionalFeesToBePaid() {
s.Run("send and two customs with same recipient", func() {
expected := types.MsgFeesDistribution{
TotalAdditionalFees: nhashCoins(2_500_000_000),
AdditionalModuleFees: nhashCoins(1_750_000_000),
AdditionalModuleFees: nhashCoins(1_000_000_000), // 1 hash from msg fees.
RecipientDistributions: map[string]sdk.Coins{
"recipient1": nhashCoins(750_000_000),
"recipient1": nhashCoins(1_500_000_000), // 1.5 hash from MsgAssessCustomMsgFee
},
}
assessFee1 := types.NewMsgAssessCustomMsgFeeRequest("", oneHash, "recipient1", someAddress.String())
Expand Down Expand Up @@ -301,15 +301,17 @@ func (s *TestSuite) TestCalculateAdditionalFeesToBePaid() {

s.Run("send and two customs all with fees and same recipient", func() {
// The Send will have a fee of 750_000_000 to the module and 250_000_000 to sendrecipient.
// The 1st assess will have a fee of 900_000_000 to the module, and 100_000_000 to sendrecipient.
// then it will send 500_000_000 to the module and 500_000_000 to sendrecipient
// The 1st assess will have a fee of 900_000_000 to the module, and 100_000_000 to sendrecipient.(this still holds)
// then it will send 0 to the module and 1_000_000_000 to sendrecipient
// The 2nd assess will have a fee of 900_000_000 to the module, and 100_000_000 to sendrecipient.
// then it will send 250_000_000 to the module and 250_000_000 to sendrecipient
// then it will send 0 to the module and 500_000_000 to sendrecipient
// module = (900_000_000 +750_000_000+ 900_000_000=2_550_000_000)
// recipient = (250_000_000 + 100_000_000 + 1_000_000_000+ 100_000_000 + 500_000_000 = 1_950_000_000)
expected := types.MsgFeesDistribution{
TotalAdditionalFees: nhashCoins(4_500_000_000),
AdditionalModuleFees: nhashCoins(3_300_000_000),
AdditionalModuleFees: nhashCoins(2_550_000_000),
RecipientDistributions: map[string]sdk.Coins{
"sendrecipient": nhashCoins(1_200_000_000),
"sendrecipient": nhashCoins(1_950_000_000),
},
}
assessFee1 := types.NewMsgAssessCustomMsgFeeRequest("", oneHash, "sendrecipient", someAddress.String())
Expand All @@ -324,14 +326,14 @@ func (s *TestSuite) TestCalculateAdditionalFeesToBePaid() {
s.Run("send and custom all different recipients", func() {
// The Send will have a fee of 750_000_000 to the module and 250_000_000 to sendrecipient.
// The 1st assess will have a fee of 900_000_000 to the module, and 100_000_000 to customrecipient.
// then it will send 500_000_000 to the module and 500_000_000 to anotherrecipient
// then it will send 0 to the module and 1_000_000_000 to anotherrecipient
expected := types.MsgFeesDistribution{
TotalAdditionalFees: nhashCoins(3_000_000_000),
AdditionalModuleFees: nhashCoins(2_150_000_000),
AdditionalModuleFees: nhashCoins(1_650_000_000),
RecipientDistributions: map[string]sdk.Coins{
"sendrecipient": nhashCoins(250_000_000),
"customrecipient": nhashCoins(100_000_000),
"anotherrecipient": nhashCoins(500_000_000),
"anotherrecipient": nhashCoins(1_000_000_000),
},
}
assessFee1 := types.NewMsgAssessCustomMsgFeeRequest("", oneHash, "anotherrecipient", someAddress.String())
Expand Down Expand Up @@ -359,9 +361,9 @@ func (s *TestSuite) TestCalculateAdditionalFeesToBePaid() {
s.Run("with fee on custom assess too do send and custom with recipient", func() {
expected := types.MsgFeesDistribution{
TotalAdditionalFees: nhashCoins(3_000_000_000),
AdditionalModuleFees: nhashCoins(2_500_000_000),
AdditionalModuleFees: nhashCoins(2_000_000_000),
RecipientDistributions: map[string]sdk.Coins{
"recipient1": nhashCoins(500_000_000),
"recipient1": nhashCoins(1_000_000_000), // 1 hash goes to recipient1
},
}
assessFee := types.NewMsgAssessCustomMsgFeeRequest("", oneHash, "recipient1", someAddress.String())
Expand Down
12 changes: 11 additions & 1 deletion x/msgfees/types/fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ const (
)

// SplitCoinByBips returns split to recipient and fee module based on basis points for recipient
// keeping this method, even though bips is being hardcoded to 100bips to recipient for now(12/14/2022)
func SplitCoinByBips(coin sdk.Coin, bips uint32) (recipientCoin sdk.Coin, feePayoutCoin sdk.Coin, err error) {
if bips > 10_000 {
return recipientCoin, feePayoutCoin, ErrInvalidBipsValue.Wrapf("invalid: %v", bips)
}
// nothing to calculate, short circuit
if bips == 10_000 {
recipientCoin = coin
feePayoutCoin = sdk.NewCoin(coin.Denom, sdk.NewInt(0))
return recipientCoin, feePayoutCoin, nil
}
numerator := sdk.NewDec(int64(bips))
denominator := sdk.NewDec(10_000)
decAmount := sdk.NewDec(coin.Amount.Int64())
Expand Down Expand Up @@ -55,7 +62,10 @@ func (d *MsgFeesDistribution) Increase(coin sdk.Coin, bips uint32, recipient str
}

d.RecipientDistributions[recipient] = d.RecipientDistributions[recipient].Add(recipientCoin)
d.AdditionalModuleFees = d.AdditionalModuleFees.Add(feePayoutCoin)
// fee payout for module for now will be zero, keeping it still here if we goto split bips as a param or even at the message level
if !feePayoutCoin.IsZero() {
d.AdditionalModuleFees = d.AdditionalModuleFees.Add(feePayoutCoin)
}

return nil
}
8 changes: 5 additions & 3 deletions x/msgfees/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (

const (

// AssessCustomMsgFeeBips is the hardcoded value for bips the recipient will receive while remainder will go to fee module
// 5,000 bips is 50:50 to recipient and fee module
AssessCustomMsgFeeBips = 5_000
// AssessCustomMsgFeeBips is the bips the recipient will get
// This should be a message level data (present in TypeAssessCustomMsgFee = "assess_custom_msg_fee") i think so that it can be defined by the smart contract writer
// or at the very least it can be a module param.
// for now i am hard coding it to avoid breaking any clients and because of this ticket https://github.com/provenance-io/provenance/issues/1263
AssessCustomMsgFeeBips = 10_000

TypeAssessCustomMsgFee = "assess_custom_msg_fee"
)
Expand Down
3 changes: 1 addition & 2 deletions x/msgfees/types/tx.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c50f8cb

Please sign in to comment.