Proposer Bid Reward [ENG-534] (#24)
This commit is contained in:
parent
fdfd12a81d
commit
99b4bc2da2
@ -8,7 +8,9 @@ import "amino/amino.proto";
|
||||
option go_package = "github.com/skip-mev/pob/x/auction/types";
|
||||
|
||||
// GenesisState defines the genesis state of the x/auction module.
|
||||
message GenesisState { Params params = 1 [ (gogoproto.nullable) = false ]; }
|
||||
message GenesisState {
|
||||
Params params = 1 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
// Params defines the parameters of the x/auction module.
|
||||
message Params {
|
||||
@ -17,29 +19,42 @@ message Params {
|
||||
// max_bundle_size is the maximum number of transactions that can be bundled
|
||||
// in a single bundle.
|
||||
uint32 max_bundle_size = 1;
|
||||
// escrow_account_address is the address of the account that will hold the
|
||||
// funds for the auctions.
|
||||
|
||||
// escrow_account_address is the address of the account that will receive a
|
||||
// portion of the bid proceeds.
|
||||
string escrow_account_address = 2;
|
||||
|
||||
// reserve_fee specifies the bid floor for the auction.
|
||||
repeated cosmos.base.v1beta1.Coin reserve_fee = 3 [
|
||||
(gogoproto.nullable) = false,
|
||||
(amino.dont_omitempty) = true,
|
||||
(gogoproto.nullable) = false,
|
||||
(amino.dont_omitempty) = true,
|
||||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
|
||||
];
|
||||
// min_buy_in_fee specifies the fee that the bidder must pay to enter the auction.
|
||||
|
||||
// min_buy_in_fee specifies the fee that the bidder must pay to enter the
|
||||
// auction.
|
||||
repeated cosmos.base.v1beta1.Coin min_buy_in_fee = 4 [
|
||||
(gogoproto.nullable) = false,
|
||||
(amino.dont_omitempty) = true,
|
||||
(gogoproto.nullable) = false,
|
||||
(amino.dont_omitempty) = true,
|
||||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
|
||||
];
|
||||
|
||||
// min_bid_increment specifies the minimum amount that the next bid must be
|
||||
// greater than the previous bid.
|
||||
repeated cosmos.base.v1beta1.Coin min_bid_increment = 5 [
|
||||
(gogoproto.nullable) = false,
|
||||
(amino.dont_omitempty) = true,
|
||||
(gogoproto.nullable) = false,
|
||||
(amino.dont_omitempty) = true,
|
||||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
|
||||
];
|
||||
// front_running_protection specifies whether front running and sandwich attack protection
|
||||
// is enabled.
|
||||
|
||||
// front_running_protection specifies whether front running and sandwich
|
||||
// attack protection is enabled.
|
||||
bool front_running_protection = 6;
|
||||
|
||||
// proposer_fee defines the portion of the winning bid that goes to the block
|
||||
// proposer that proposed the block.
|
||||
string proposer_fee = 7 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec"
|
||||
];
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ func (k Keeper) ValidateAuctionBid(ctx sdk.Context, bidder sdk.AccAddress, bid,
|
||||
|
||||
// Ensure the bidder has enough funds to cover all the inclusion fees.
|
||||
minBalance := bid.Add(minBuyInFee...)
|
||||
balances := k.bankkeeper.GetAllBalances(ctx, bidder)
|
||||
balances := k.bankKeeper.GetAllBalances(ctx, bidder)
|
||||
if !balances.IsAllGTE(minBalance) {
|
||||
return fmt.Errorf("insufficient funds to bid %s (reserve fee + bid) with balance %s", minBalance, balances)
|
||||
}
|
||||
@ -103,8 +103,8 @@ func (k Keeper) ValidateAuctionBundle(ctx sdk.Context, bidder sdk.AccAddress, tr
|
||||
// Check that all subsequent transactions are signed by either
|
||||
// 1. the same party as the first transaction
|
||||
// 2. the same party for some arbitrary number of txs and then are all remaining txs are signed by the bidder.
|
||||
for _, txbytes := range transactions[1:] {
|
||||
txSigners, err := k.getTxSigners(txbytes)
|
||||
for _, refTx := range transactions[1:] {
|
||||
txSigners, err := k.getTxSigners(refTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -4,16 +4,12 @@ import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/skip-mev/pob/x/auction/keeper"
|
||||
auctiontypes "github.com/skip-mev/pob/x/auction/types"
|
||||
)
|
||||
|
||||
func (suite *IntegrationTestSuite) TestValidateAuctionMsg() {
|
||||
func (suite *KeeperTestSuite) TestValidateAuctionMsg() {
|
||||
var (
|
||||
// Tx building variables
|
||||
accounts = []Account{} // tracks the order of signers in the bundle
|
||||
@ -161,6 +157,8 @@ func (suite *IntegrationTestSuite) TestValidateAuctionMsg() {
|
||||
suite.key,
|
||||
suite.accountKeeper,
|
||||
suite.bankKeeper,
|
||||
suite.distrKeeper,
|
||||
suite.stakingKeeper,
|
||||
suite.authorityAccount.String(),
|
||||
)
|
||||
params := auctiontypes.Params{
|
||||
@ -191,7 +189,7 @@ func (suite *IntegrationTestSuite) TestValidateAuctionMsg() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestValidateBundle() {
|
||||
func (suite *KeeperTestSuite) TestValidateBundle() {
|
||||
// TODO: Update this to be multi-dimensional to test multi-sig
|
||||
// https://github.com/skip-mev/pob/issues/14
|
||||
var accounts []Account // tracks the order of signers in the bundle
|
||||
@ -301,33 +299,3 @@ func (suite *IntegrationTestSuite) TestValidateBundle() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// createRandomTx creates a random transaction with a given account, nonce, and number of messages.
|
||||
func createRandomTx(txCfg client.TxConfig, account Account, nonce, numberMsgs uint64) (authsigning.Tx, error) {
|
||||
msgs := make([]sdk.Msg, numberMsgs)
|
||||
for i := 0; i < int(numberMsgs); i++ {
|
||||
msgs[i] = &banktypes.MsgSend{
|
||||
FromAddress: account.Address.String(),
|
||||
ToAddress: account.Address.String(),
|
||||
}
|
||||
}
|
||||
|
||||
txBuilder := txCfg.NewTxBuilder()
|
||||
if err := txBuilder.SetMsgs(msgs...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sigV2 := signing.SignatureV2{
|
||||
PubKey: account.PrivKey.PubKey(),
|
||||
Data: &signing.SingleSignatureData{
|
||||
SignMode: txCfg.SignModeHandler().DefaultMode(),
|
||||
Signature: nil,
|
||||
},
|
||||
Sequence: nonce,
|
||||
}
|
||||
if err := txBuilder.SetSignatures(sigV2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return txBuilder.GetTx(), nil
|
||||
}
|
||||
|
||||
@ -15,15 +15,24 @@ type Keeper struct {
|
||||
cdc codec.BinaryCodec
|
||||
storeKey storetypes.StoreKey
|
||||
|
||||
bankkeeper types.BankKeeper
|
||||
bankKeeper types.BankKeeper
|
||||
distrKeeper types.DistributionKeeper
|
||||
stakingKeeper types.StakingKeeper
|
||||
|
||||
// The address that is capable of executing a MsgUpdateParams message. Typically this will be the
|
||||
// governance module's address.
|
||||
// The address that is capable of executing a MsgUpdateParams message.
|
||||
// Typically this will be the governance module's address.
|
||||
authority string
|
||||
}
|
||||
|
||||
// NewKeeper creates a new keeper instance.
|
||||
func NewKeeper(cdc codec.BinaryCodec, storeKey storetypes.StoreKey, accountKeeper types.AccountKeeper, bankkeeper types.BankKeeper, authority string) Keeper {
|
||||
func NewKeeper(
|
||||
cdc codec.BinaryCodec,
|
||||
storeKey storetypes.StoreKey,
|
||||
accountKeeper types.AccountKeeper,
|
||||
bankKeeper types.BankKeeper,
|
||||
distrKeeper types.DistributionKeeper,
|
||||
stakingKeeper types.StakingKeeper,
|
||||
authority string,
|
||||
) Keeper {
|
||||
// Ensure that the authority address is valid.
|
||||
if _, err := sdk.AccAddressFromBech32(authority); err != nil {
|
||||
panic(err)
|
||||
@ -35,10 +44,12 @@ func NewKeeper(cdc codec.BinaryCodec, storeKey storetypes.StoreKey, accountKeepe
|
||||
}
|
||||
|
||||
return Keeper{
|
||||
cdc: cdc,
|
||||
storeKey: storeKey,
|
||||
bankkeeper: bankkeeper,
|
||||
authority: authority,
|
||||
cdc: cdc,
|
||||
storeKey: storeKey,
|
||||
bankKeeper: bankKeeper,
|
||||
distrKeeper: distrKeeper,
|
||||
stakingKeeper: stakingKeeper,
|
||||
authority: authority,
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,6 +151,16 @@ func (k Keeper) GetMinBidIncrement(ctx sdk.Context) (sdk.Coins, error) {
|
||||
return params.MinBidIncrement, nil
|
||||
}
|
||||
|
||||
// GetProposerFee returns the proposer fee for the auction module.
|
||||
func (k Keeper) GetProposerFee(ctx sdk.Context) (sdk.Dec, error) {
|
||||
params, err := k.GetParams(ctx)
|
||||
if err != nil {
|
||||
return sdk.ZeroDec(), err
|
||||
}
|
||||
|
||||
return params.ProposerFee, nil
|
||||
}
|
||||
|
||||
// FrontRunningProtectionEnabled returns true if front-running protection is enabled.
|
||||
func (k Keeper) FrontRunningProtectionEnabled(ctx sdk.Context) (bool, error) {
|
||||
params, err := k.GetParams(ctx)
|
||||
|
||||
@ -1,22 +1,11 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/skip-mev/pob/mempool"
|
||||
"github.com/skip-mev/pob/x/auction/ante"
|
||||
@ -26,12 +15,14 @@ import (
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type IntegrationTestSuite struct {
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
auctionKeeper keeper.Keeper
|
||||
bankKeeper *MockBankKeeper
|
||||
accountKeeper *MockAccountKeeper
|
||||
distrKeeper *MockDistributionKeeper
|
||||
stakingKeeper *MockStakingKeeper
|
||||
encCfg encodingConfig
|
||||
AuctionDecorator sdk.AnteDecorator
|
||||
ctx sdk.Context
|
||||
@ -43,22 +34,33 @@ type IntegrationTestSuite struct {
|
||||
}
|
||||
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IntegrationTestSuite))
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) SetupTest() {
|
||||
func (suite *KeeperTestSuite) SetupTest() {
|
||||
suite.encCfg = createTestEncodingConfig()
|
||||
suite.key = sdk.NewKVStoreKey(types.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(suite.T(), suite.key, sdk.NewTransientStoreKey("transient_test"))
|
||||
suite.ctx = testCtx.Ctx
|
||||
|
||||
// Auction Keeper setup
|
||||
ctrl := gomock.NewController(suite.T())
|
||||
|
||||
suite.accountKeeper = NewMockAccountKeeper(ctrl)
|
||||
suite.accountKeeper.EXPECT().GetModuleAddress(types.ModuleName).Return(sdk.AccAddress{}).AnyTimes()
|
||||
|
||||
suite.bankKeeper = NewMockBankKeeper(ctrl)
|
||||
suite.distrKeeper = NewMockDistributionKeeper(ctrl)
|
||||
suite.stakingKeeper = NewMockStakingKeeper(ctrl)
|
||||
suite.authorityAccount = sdk.AccAddress([]byte("authority"))
|
||||
suite.auctionKeeper = keeper.NewKeeper(suite.encCfg.Codec, suite.key, suite.accountKeeper, suite.bankKeeper, suite.authorityAccount.String())
|
||||
suite.auctionKeeper = keeper.NewKeeper(
|
||||
suite.encCfg.Codec,
|
||||
suite.key,
|
||||
suite.accountKeeper,
|
||||
suite.bankKeeper,
|
||||
suite.distrKeeper,
|
||||
suite.stakingKeeper,
|
||||
suite.authorityAccount.String(),
|
||||
)
|
||||
|
||||
err := suite.auctionKeeper.SetParams(suite.ctx, types.DefaultParams())
|
||||
suite.Require().NoError(err)
|
||||
@ -67,157 +69,3 @@ func (suite *IntegrationTestSuite) SetupTest() {
|
||||
suite.AuctionDecorator = ante.NewAuctionDecorator(suite.auctionKeeper, suite.encCfg.TxConfig.TxDecoder(), suite.mempool)
|
||||
suite.msgServer = keeper.NewMsgServerImpl(suite.auctionKeeper)
|
||||
}
|
||||
|
||||
type encodingConfig struct {
|
||||
InterfaceRegistry codectypes.InterfaceRegistry
|
||||
Codec codec.Codec
|
||||
TxConfig client.TxConfig
|
||||
Amino *codec.LegacyAmino
|
||||
}
|
||||
|
||||
func createTestEncodingConfig() encodingConfig {
|
||||
cdc := codec.NewLegacyAmino()
|
||||
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
||||
|
||||
banktypes.RegisterInterfaces(interfaceRegistry)
|
||||
cryptocodec.RegisterInterfaces(interfaceRegistry)
|
||||
|
||||
codec := codec.NewProtoCodec(interfaceRegistry)
|
||||
|
||||
return encodingConfig{
|
||||
InterfaceRegistry: interfaceRegistry,
|
||||
Codec: codec,
|
||||
TxConfig: tx.NewTxConfig(codec, tx.DefaultSignModes),
|
||||
Amino: cdc,
|
||||
}
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
PrivKey cryptotypes.PrivKey
|
||||
PubKey cryptotypes.PubKey
|
||||
Address sdk.AccAddress
|
||||
ConsKey cryptotypes.PrivKey
|
||||
}
|
||||
|
||||
func (acc Account) Equals(acc2 Account) bool {
|
||||
return acc.Address.Equals(acc2.Address)
|
||||
}
|
||||
|
||||
// RandomAccounts returns a slice of n random accounts.
|
||||
func RandomAccounts(r *rand.Rand, n int) []Account {
|
||||
accs := make([]Account, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
pkSeed := make([]byte, 15)
|
||||
r.Read(pkSeed)
|
||||
|
||||
accs[i].PrivKey = secp256k1.GenPrivKeyFromSecret(pkSeed)
|
||||
accs[i].PubKey = accs[i].PrivKey.PubKey()
|
||||
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
|
||||
|
||||
accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(pkSeed)
|
||||
}
|
||||
|
||||
return accs
|
||||
}
|
||||
|
||||
// MockAccountKeeper is a mock of AccountKeeper interface.
|
||||
type MockAccountKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAccountKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper.
|
||||
type MockAccountKeeperMockRecorder struct {
|
||||
mock *MockAccountKeeper
|
||||
}
|
||||
|
||||
// NewMockAccountKeeper creates a new mock instance.
|
||||
func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper {
|
||||
mock := &MockAccountKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockAccountKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetModuleAddress mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAddress(name string) sdk.AccAddress {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAddress", name)
|
||||
ret0, _ := ret[0].(sdk.AccAddress)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetModuleAddress indicates an expected call of GetModuleAddress.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAddress(name interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAddress", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAddress), name)
|
||||
}
|
||||
|
||||
// MockBankKeeper is a mock of BankKeeper interface.
|
||||
type MockBankKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockBankKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper.
|
||||
type MockBankKeeperMockRecorder struct {
|
||||
mock *MockBankKeeper
|
||||
}
|
||||
|
||||
// NewMockBankKeeper creates a new mock instance.
|
||||
func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper {
|
||||
mock := &MockBankKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockBankKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetAllBalances mocks base method.
|
||||
func (m *MockBankKeeper) GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr)
|
||||
ret0 := ret[0].(sdk.Coins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAllBalances indicates an expected call of GetAllBalances.
|
||||
func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*MockBankKeeper)(nil).GetAllBalances), ctx, addr)
|
||||
}
|
||||
|
||||
// SendCoins mocks base method.
|
||||
func (m *MockBankKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SendCoins", ctx, fromAddr, toAddr, amt)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendCoins indicates an expected call of SendCoins.
|
||||
func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt)
|
||||
}
|
||||
|
||||
// SendCoinsFromAccountToModule mocks base method.
|
||||
func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule.
|
||||
func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt)
|
||||
}
|
||||
|
||||
144
x/auction/keeper/mocks_test.go
Normal file
144
x/auction/keeper/mocks_test.go
Normal file
@ -0,0 +1,144 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
type MockAccountKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAccountKeeperMockRecorder
|
||||
}
|
||||
|
||||
type MockAccountKeeperMockRecorder struct {
|
||||
mock *MockAccountKeeper
|
||||
}
|
||||
|
||||
func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper {
|
||||
mock := &MockAccountKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockAccountKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
func (m *MockAccountKeeper) GetModuleAddress(name string) sdk.AccAddress {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAddress", name)
|
||||
ret0, _ := ret[0].(sdk.AccAddress)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAddress(name interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAddress", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAddress), name)
|
||||
}
|
||||
|
||||
type MockBankKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockBankKeeperMockRecorder
|
||||
}
|
||||
|
||||
type MockBankKeeperMockRecorder struct {
|
||||
mock *MockBankKeeper
|
||||
}
|
||||
|
||||
func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper {
|
||||
mock := &MockBankKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockBankKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
func (m *MockBankKeeper) GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr)
|
||||
ret0 := ret[0].(sdk.Coins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*MockBankKeeper)(nil).GetAllBalances), ctx, addr)
|
||||
}
|
||||
|
||||
func (m *MockBankKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SendCoins", ctx, fromAddr, toAddr, amt)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt)
|
||||
}
|
||||
|
||||
type MockDistributionKeeperRecorder struct {
|
||||
mock *MockDistributionKeeper
|
||||
}
|
||||
|
||||
type MockDistributionKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockDistributionKeeperRecorder
|
||||
}
|
||||
|
||||
func NewMockDistributionKeeper(ctrl *gomock.Controller) *MockDistributionKeeper {
|
||||
mock := &MockDistributionKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockDistributionKeeperRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (m *MockDistributionKeeper) EXPECT() *MockDistributionKeeperRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
func (m *MockDistributionKeeper) GetPreviousProposerConsAddr(ctx sdk.Context) sdk.ConsAddress {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetPreviousProposerConsAddr", ctx)
|
||||
ret0 := ret[0].(sdk.ConsAddress)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mr *MockDistributionKeeperRecorder) GetPreviousProposerConsAddr(ctx any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPreviousProposerConsAddr", reflect.TypeOf((*MockDistributionKeeper)(nil).GetPreviousProposerConsAddr), ctx)
|
||||
}
|
||||
|
||||
type MockStakingKeeperRecorder struct {
|
||||
mock *MockStakingKeeper
|
||||
}
|
||||
|
||||
type MockStakingKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStakingKeeperRecorder
|
||||
}
|
||||
|
||||
func NewMockStakingKeeper(ctrl *gomock.Controller) *MockStakingKeeper {
|
||||
mock := &MockStakingKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockStakingKeeperRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
func (m *MockStakingKeeper) ValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) stakingtypes.ValidatorI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorByConsAddr", ctx, consAddr)
|
||||
ret0 := ret[0].(stakingtypes.ValidatorI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mr *MockStakingKeeperRecorder) ValidatorByConsAddr(ctx, consAddr any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorByConsAddr", reflect.TypeOf((*MockStakingKeeper)(nil).ValidatorByConsAddr), ctx, consAddr)
|
||||
}
|
||||
@ -20,18 +20,19 @@ func NewMsgServerImpl(keeper Keeper) *MsgServer {
|
||||
return &MsgServer{Keeper: keeper}
|
||||
}
|
||||
|
||||
// AuctionBid is the server implementation for Msg/AuctionBid.
|
||||
func (m MsgServer) AuctionBid(goCtx context.Context, msg *types.MsgAuctionBid) (*types.MsgAuctionBidResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// This should never return an error because the address was validated when the message was ingressed.
|
||||
// This should never return an error because the address was validated when
|
||||
// the message was ingressed.
|
||||
bidder, err := sdk.AccAddressFromBech32(msg.Bidder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure that the number of transactions is less than or equal to the maximum allowed.
|
||||
maxBundleSize, err := m.Keeper.GetMaxBundleSize(ctx)
|
||||
// Ensure that the number of transactions is less than or equal to the maximum
|
||||
// allowed.
|
||||
maxBundleSize, err := m.GetMaxBundleSize(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -40,27 +41,54 @@ func (m MsgServer) AuctionBid(goCtx context.Context, msg *types.MsgAuctionBid) (
|
||||
return nil, fmt.Errorf("the number of transactions in the bid is greater than the maximum allowed; expected <= %d, got %d", maxBundleSize, len(msg.Transactions))
|
||||
}
|
||||
|
||||
// Attempt to send the bid to the module account.
|
||||
if err := m.Keeper.bankkeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, msg.Bid); err != nil {
|
||||
proposerFee, err := m.GetProposerFee(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: figure out how to handle payments to the escrow address.
|
||||
// Ref: https://github.com/skip-mev/pob/issues/11
|
||||
escrow, err := m.Keeper.GetEscrowAccount(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if proposerFee.IsZero() {
|
||||
// send the entire bid to the escrow account when no proposer fee is set
|
||||
if err := m.bankKeeper.SendCoins(ctx, bidder, escrow, msg.Bid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
prevPropConsAddr := m.distrKeeper.GetPreviousProposerConsAddr(ctx)
|
||||
prevProposer := m.stakingKeeper.ValidatorByConsAddr(ctx, prevPropConsAddr)
|
||||
|
||||
// determine the amount of the bid that goes to the (previous) proposer
|
||||
bid := sdk.NewDecCoinsFromCoins(msg.Bid...)
|
||||
proposerReward, _ := bid.MulDecTruncate(proposerFee).TruncateDecimal()
|
||||
|
||||
if err := m.bankKeeper.SendCoins(ctx, bidder, sdk.AccAddress(prevProposer.GetOperator()), proposerReward); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Determine the amount of the remaining bid that goes to the escrow account.
|
||||
// If a decimal remainder exists, it'll stay with the bidding account.
|
||||
escrowTotal := bid.Sub(sdk.NewDecCoinsFromCoins(proposerReward...))
|
||||
escrowReward, _ := escrowTotal.TruncateDecimal()
|
||||
|
||||
if err := m.bankKeeper.SendCoins(ctx, bidder, escrow, escrowReward); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &types.MsgAuctionBidResponse{}, nil
|
||||
}
|
||||
|
||||
// UpdateParams is the server implementation for Msg/UpdateParams.
|
||||
func (m MsgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Ensure that the message signer is the authority.
|
||||
// ensure that the message signer is the authority
|
||||
if msg.Authority != m.Keeper.GetAuthority() {
|
||||
return nil, fmt.Errorf("this message can only be executed by the authority; expected %s, got %s", m.Keeper.GetAuthority(), msg.Authority)
|
||||
}
|
||||
|
||||
// Update the parameters.
|
||||
if err := m.Keeper.SetParams(ctx, msg.Params); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
127
x/auction/keeper/msg_server_test.go
Normal file
127
x/auction/keeper/msg_server_test.go
Normal file
@ -0,0 +1,127 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/skip-mev/pob/x/auction/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestMsgAuctionBid() {
|
||||
rng := rand.New(rand.NewSource(time.Now().Unix()))
|
||||
accounts := RandomAccounts(rng, 4)
|
||||
|
||||
bidder := accounts[0]
|
||||
escrow := accounts[1]
|
||||
|
||||
proposerCons := accounts[2]
|
||||
proposerOperator := accounts[3]
|
||||
proposer := stakingtypes.Validator{
|
||||
OperatorAddress: sdk.ValAddress(proposerOperator.Address).String(),
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
msg *types.MsgAuctionBid
|
||||
malleate func()
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "invalid bidder address",
|
||||
msg: &types.MsgAuctionBid{
|
||||
Bidder: "foo",
|
||||
},
|
||||
malleate: func() {},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "too many bundled transactions",
|
||||
msg: &types.MsgAuctionBid{
|
||||
Bidder: bidder.Address.String(),
|
||||
Transactions: [][]byte{{0xFF}, {0xFF}, {0xFF}},
|
||||
},
|
||||
malleate: func() {
|
||||
params := types.DefaultParams()
|
||||
params.MaxBundleSize = 2
|
||||
suite.auctionKeeper.SetParams(suite.ctx, params)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid bundle with no proposer fee",
|
||||
msg: &types.MsgAuctionBid{
|
||||
Bidder: bidder.Address.String(),
|
||||
Bid: sdk.NewCoins(sdk.NewInt64Coin("foo", 1024)),
|
||||
Transactions: [][]byte{{0xFF}, {0xFF}},
|
||||
},
|
||||
malleate: func() {
|
||||
params := types.DefaultParams()
|
||||
params.ProposerFee = sdk.ZeroDec()
|
||||
params.EscrowAccountAddress = escrow.Address.String()
|
||||
suite.auctionKeeper.SetParams(suite.ctx, params)
|
||||
|
||||
suite.bankKeeper.EXPECT().
|
||||
SendCoins(
|
||||
suite.ctx,
|
||||
bidder.Address,
|
||||
escrow.Address,
|
||||
sdk.NewCoins(sdk.NewInt64Coin("foo", 1024)),
|
||||
).
|
||||
Return(nil).
|
||||
AnyTimes()
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid bundle with proposer fee",
|
||||
msg: &types.MsgAuctionBid{
|
||||
Bidder: bidder.Address.String(),
|
||||
Bid: sdk.NewCoins(sdk.NewInt64Coin("foo", 3416)),
|
||||
Transactions: [][]byte{{0xFF}, {0xFF}},
|
||||
},
|
||||
malleate: func() {
|
||||
params := types.DefaultParams()
|
||||
params.ProposerFee = sdk.MustNewDecFromStr("0.30")
|
||||
params.EscrowAccountAddress = escrow.Address.String()
|
||||
suite.auctionKeeper.SetParams(suite.ctx, params)
|
||||
|
||||
suite.distrKeeper.EXPECT().
|
||||
GetPreviousProposerConsAddr(suite.ctx).
|
||||
Return(proposerCons.ConsKey.PubKey().Address().Bytes())
|
||||
|
||||
suite.stakingKeeper.EXPECT().
|
||||
ValidatorByConsAddr(suite.ctx, sdk.ConsAddress(proposerCons.ConsKey.PubKey().Address().Bytes())).
|
||||
Return(proposer).
|
||||
AnyTimes()
|
||||
|
||||
suite.bankKeeper.EXPECT().
|
||||
SendCoins(suite.ctx, bidder.Address, proposerOperator.Address, sdk.NewCoins(sdk.NewInt64Coin("foo", 1024))).
|
||||
Return(nil)
|
||||
|
||||
suite.bankKeeper.EXPECT().
|
||||
SendCoins(suite.ctx, bidder.Address, escrow.Address, sdk.NewCoins(sdk.NewInt64Coin("foo", 2392))).
|
||||
Return(nil)
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
tc.malleate()
|
||||
|
||||
_, err := suite.msgServer.AuctionBid(suite.ctx, tc.msg)
|
||||
if tc.expectErr {
|
||||
suite.Require().Error(err)
|
||||
} else {
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestMsgUpdateParams() {
|
||||
suite.T().SkipNow()
|
||||
}
|
||||
99
x/auction/keeper/util_test.go
Normal file
99
x/auction/keeper/util_test.go
Normal file
@ -0,0 +1,99 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
type encodingConfig struct {
|
||||
InterfaceRegistry codectypes.InterfaceRegistry
|
||||
Codec codec.Codec
|
||||
TxConfig client.TxConfig
|
||||
Amino *codec.LegacyAmino
|
||||
}
|
||||
|
||||
func createTestEncodingConfig() encodingConfig {
|
||||
cdc := codec.NewLegacyAmino()
|
||||
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
||||
|
||||
banktypes.RegisterInterfaces(interfaceRegistry)
|
||||
cryptocodec.RegisterInterfaces(interfaceRegistry)
|
||||
|
||||
codec := codec.NewProtoCodec(interfaceRegistry)
|
||||
|
||||
return encodingConfig{
|
||||
InterfaceRegistry: interfaceRegistry,
|
||||
Codec: codec,
|
||||
TxConfig: tx.NewTxConfig(codec, tx.DefaultSignModes),
|
||||
Amino: cdc,
|
||||
}
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
PrivKey cryptotypes.PrivKey
|
||||
PubKey cryptotypes.PubKey
|
||||
Address sdk.AccAddress
|
||||
ConsKey cryptotypes.PrivKey
|
||||
}
|
||||
|
||||
func (acc Account) Equals(acc2 Account) bool {
|
||||
return acc.Address.Equals(acc2.Address)
|
||||
}
|
||||
|
||||
func RandomAccounts(r *rand.Rand, n int) []Account {
|
||||
accs := make([]Account, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
pkSeed := make([]byte, 15)
|
||||
r.Read(pkSeed)
|
||||
|
||||
accs[i].PrivKey = secp256k1.GenPrivKeyFromSecret(pkSeed)
|
||||
accs[i].PubKey = accs[i].PrivKey.PubKey()
|
||||
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
|
||||
|
||||
accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(pkSeed)
|
||||
}
|
||||
|
||||
return accs
|
||||
}
|
||||
|
||||
func createRandomTx(txCfg client.TxConfig, account Account, nonce, numberMsgs uint64) (authsigning.Tx, error) {
|
||||
msgs := make([]sdk.Msg, numberMsgs)
|
||||
for i := 0; i < int(numberMsgs); i++ {
|
||||
msgs[i] = &banktypes.MsgSend{
|
||||
FromAddress: account.Address.String(),
|
||||
ToAddress: account.Address.String(),
|
||||
}
|
||||
}
|
||||
|
||||
txBuilder := txCfg.NewTxBuilder()
|
||||
if err := txBuilder.SetMsgs(msgs...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sigV2 := signing.SignatureV2{
|
||||
PubKey: account.PrivKey.PubKey(),
|
||||
Data: &signing.SingleSignatureData{
|
||||
SignMode: txCfg.SignModeHandler().DefaultMode(),
|
||||
Signature: nil,
|
||||
},
|
||||
Sequence: nonce,
|
||||
}
|
||||
if err := txBuilder.SetSignatures(sigV2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return txBuilder.GetTx(), nil
|
||||
}
|
||||
@ -26,7 +26,6 @@ var (
|
||||
// ConsensusVersion defines the current x/auction module consensus version.
|
||||
const ConsensusVersion = 1
|
||||
|
||||
// -------------------- AppModuleBasic -------------------- //
|
||||
// AppModuleBasic defines the basic application module used by the auction module.
|
||||
type AppModuleBasic struct {
|
||||
cdc codec.Codec
|
||||
@ -70,16 +69,11 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *r
|
||||
}
|
||||
|
||||
// GetTxCmd returns the root tx command for the auction module.
|
||||
func (AppModuleBasic) GetTxCmd() *cobra.Command {
|
||||
return nil
|
||||
}
|
||||
func (AppModuleBasic) GetTxCmd() *cobra.Command { return nil }
|
||||
|
||||
// GetQueryCmd returns no root query command for the auction module.
|
||||
func (AppModuleBasic) GetQueryCmd() *cobra.Command {
|
||||
return nil
|
||||
}
|
||||
func (AppModuleBasic) GetQueryCmd() *cobra.Command { return nil }
|
||||
|
||||
// -------------------- AppModule -------------------- //
|
||||
type AppModule struct {
|
||||
AppModuleBasic
|
||||
|
||||
@ -98,7 +92,11 @@ func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.Acc
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterServices registers a the gRPC Query and Msg services for the auciton module.
|
||||
// ConsensusVersion implements AppModule/ConsensusVersion.
|
||||
func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion }
|
||||
|
||||
// RegisterServices registers a the gRPC Query and Msg services for the x/auction
|
||||
// module.
|
||||
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
// TODO: Define the gRPC querier service and register it with the auction module configurator
|
||||
// TODO: Define the gRPC Msg service and register it with the auction module configurator
|
||||
@ -106,33 +104,24 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
|
||||
func (a AppModuleBasic) RegisterRESTRoutes(ctx client.Context, r *mux.Router) {}
|
||||
|
||||
// RegisterInvariants registers the invariants of the module. If an invariant deviates from its predicted value, the InvariantRegistry triggers appropriate logic (most often the chain will be halted)
|
||||
// RegisterInvariants registers the invariants of the module. If an invariant
|
||||
// deviates from its predicted value, the InvariantRegistry triggers appropriate
|
||||
// logic (most often the chain will be halted).
|
||||
func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
|
||||
|
||||
// InitGenesis performs the module's genesis initialization for the auction module. It returns no validator updates.
|
||||
// InitGenesis performs the module's genesis initialization for the auction
|
||||
// module. It returns no validator updates.
|
||||
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate {
|
||||
var genState types.GenesisState
|
||||
cdc.MustUnmarshalJSON(gs, &genState)
|
||||
|
||||
am.keeper.InitGenesis(ctx, genState)
|
||||
|
||||
return []abci.ValidatorUpdate{}
|
||||
}
|
||||
|
||||
// ExportGenesis returns the auction module's exported genesis state as raw JSON bytes.
|
||||
// ExportGenesis returns the auction module's exported genesis state as raw
|
||||
// JSON bytes.
|
||||
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
|
||||
genState := am.keeper.ExportGenesis(ctx)
|
||||
return cdc.MustMarshalJSON(genState)
|
||||
}
|
||||
|
||||
// ConsensusVersion implements AppModule/ConsensusVersion.
|
||||
func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion }
|
||||
|
||||
// BeginBlock returns the begin blocker for the auction module.
|
||||
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} //nolint
|
||||
|
||||
// EndBlock returns the end blocker for the auction module. It returns no validator updates.
|
||||
|
||||
func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { //nolint
|
||||
return []abci.ValidatorUpdate{}
|
||||
}
|
||||
|
||||
@ -2,16 +2,27 @@ package types
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// AccountKeeper defines the contract required for account APIs.
|
||||
// BankKeeper defines the expected API contract for the x/auth module.
|
||||
type AccountKeeper interface {
|
||||
GetModuleAddress(moduleName string) sdk.AccAddress
|
||||
}
|
||||
|
||||
// BankKeeper defines the contract required for bank APIs.
|
||||
// BankKeeper defines the expected API contract for the x/bank module.
|
||||
type BankKeeper interface {
|
||||
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
|
||||
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
|
||||
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
|
||||
}
|
||||
|
||||
// DistributionKeeper defines the expected API contract for the x/distribution
|
||||
// module.
|
||||
type DistributionKeeper interface {
|
||||
GetPreviousProposerConsAddr(ctx sdk.Context) sdk.ConsAddress
|
||||
}
|
||||
|
||||
// StakingKeeper defines the expected API contract for the x/staking module.
|
||||
type StakingKeeper interface {
|
||||
ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) stakingtypes.ValidatorI
|
||||
}
|
||||
|
||||
@ -76,19 +76,23 @@ type Params struct {
|
||||
// max_bundle_size is the maximum number of transactions that can be bundled
|
||||
// in a single bundle.
|
||||
MaxBundleSize uint32 `protobuf:"varint,1,opt,name=max_bundle_size,json=maxBundleSize,proto3" json:"max_bundle_size,omitempty"`
|
||||
// escrow_account_address is the address of the account that will hold the
|
||||
// funds for the auctions.
|
||||
// escrow_account_address is the address of the account that will receive a
|
||||
// portion of the bid proceeds.
|
||||
EscrowAccountAddress string `protobuf:"bytes,2,opt,name=escrow_account_address,json=escrowAccountAddress,proto3" json:"escrow_account_address,omitempty"`
|
||||
// reserve_fee specifies the bid floor for the auction.
|
||||
ReserveFee github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=reserve_fee,json=reserveFee,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"reserve_fee"`
|
||||
// min_buy_in_fee specifies the fee that the bidder must pay to enter the auction.
|
||||
// min_buy_in_fee specifies the fee that the bidder must pay to enter the
|
||||
// auction.
|
||||
MinBuyInFee github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,4,rep,name=min_buy_in_fee,json=minBuyInFee,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"min_buy_in_fee"`
|
||||
// min_bid_increment specifies the minimum amount that the next bid must be
|
||||
// greater than the previous bid.
|
||||
MinBidIncrement github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,5,rep,name=min_bid_increment,json=minBidIncrement,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"min_bid_increment"`
|
||||
// front_running_protection specifies whether front running and sandwich attack protection
|
||||
// is enabled.
|
||||
// front_running_protection specifies whether front running and sandwich
|
||||
// attack protection is enabled.
|
||||
FrontRunningProtection bool `protobuf:"varint,6,opt,name=front_running_protection,json=frontRunningProtection,proto3" json:"front_running_protection,omitempty"`
|
||||
// proposer_fee defines the portion of the winning bid that goes to the block
|
||||
// proposer that proposed the block.
|
||||
ProposerFee github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=proposer_fee,json=proposerFee,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"proposer_fee"`
|
||||
}
|
||||
|
||||
func (m *Params) Reset() { *m = Params{} }
|
||||
@ -174,37 +178,40 @@ func init() {
|
||||
func init() { proto.RegisterFile("pob/auction/v1/genesis.proto", fileDescriptor_9ed8651e43f855a1) }
|
||||
|
||||
var fileDescriptor_9ed8651e43f855a1 = []byte{
|
||||
// 480 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x93, 0xb1, 0x6e, 0xd4, 0x30,
|
||||
0x18, 0xc7, 0x2f, 0xf4, 0x38, 0x81, 0x8f, 0x52, 0x35, 0xaa, 0x4e, 0xa1, 0xa0, 0x34, 0xea, 0x00,
|
||||
0x51, 0xa5, 0xda, 0xba, 0x02, 0x12, 0x42, 0x2c, 0x77, 0x48, 0xa0, 0x4a, 0x0c, 0x55, 0xba, 0xb1,
|
||||
0x58, 0x4e, 0xf2, 0x35, 0x58, 0xc5, 0x76, 0x88, 0x9d, 0x70, 0x57, 0xf1, 0x04, 0x4c, 0x3c, 0x06,
|
||||
0xea, 0xd4, 0xc7, 0xe8, 0xd8, 0x91, 0x09, 0xd0, 0xdd, 0xd0, 0xd7, 0x40, 0xb1, 0x43, 0xe9, 0xc0,
|
||||
0xda, 0x25, 0x89, 0xfc, 0xfb, 0xec, 0xdf, 0xf7, 0x45, 0x7f, 0xa3, 0x47, 0xa5, 0x4a, 0x09, 0xab,
|
||||
0x33, 0xc3, 0x95, 0x24, 0xcd, 0x98, 0x14, 0x20, 0x41, 0x73, 0x8d, 0xcb, 0x4a, 0x19, 0xe5, 0x8f,
|
||||
0xf4, 0x31, 0x2f, 0x05, 0x34, 0xb8, 0x54, 0x29, 0xee, 0xaa, 0x70, 0x33, 0xde, 0xdc, 0x28, 0x54,
|
||||
0xa1, 0x6c, 0x09, 0x69, 0xbf, 0x5c, 0xf5, 0x66, 0x98, 0x29, 0x2d, 0x94, 0x26, 0x29, 0xd3, 0x40,
|
||||
0x9a, 0x71, 0x0a, 0x86, 0x8d, 0x49, 0xa6, 0xb8, 0xec, 0xf8, 0x3a, 0x13, 0x5c, 0x2a, 0x62, 0x9f,
|
||||
0x6e, 0x69, 0xfb, 0x1d, 0xba, 0xf7, 0xd6, 0x19, 0x0f, 0x0d, 0x33, 0xe0, 0xbf, 0x42, 0x83, 0x92,
|
||||
0x55, 0x4c, 0xe8, 0xc0, 0x8b, 0xbc, 0x78, 0xb8, 0x17, 0xe2, 0xff, 0x77, 0x80, 0x0f, 0x6c, 0xd5,
|
||||
0xb4, 0x7f, 0xfe, 0x73, 0xab, 0x97, 0x74, 0x7b, 0xb6, 0x4f, 0xfb, 0x68, 0xe0, 0x80, 0xff, 0x18,
|
||||
0xad, 0x09, 0x36, 0xa3, 0x69, 0x2d, 0xf3, 0x8f, 0x40, 0x35, 0x3f, 0x01, 0x7b, 0xe2, 0x6a, 0xb2,
|
||||
0x2a, 0xd8, 0x6c, 0x6a, 0x57, 0x0f, 0xf9, 0x09, 0xf8, 0xcf, 0xd0, 0x08, 0x74, 0x56, 0xa9, 0xcf,
|
||||
0x94, 0x65, 0x99, 0xaa, 0xa5, 0xa1, 0x2c, 0xcf, 0x2b, 0xd0, 0x3a, 0xb8, 0x15, 0x79, 0xf1, 0xdd,
|
||||
0x64, 0xc3, 0xd1, 0x89, 0x83, 0x13, 0xc7, 0xfc, 0x4f, 0x68, 0x58, 0x81, 0x86, 0xaa, 0x01, 0x7a,
|
||||
0x04, 0x10, 0xac, 0x44, 0x2b, 0xf1, 0x70, 0xef, 0x01, 0x76, 0xf3, 0xe3, 0x76, 0x7e, 0xdc, 0xcd,
|
||||
0x8f, 0x5f, 0x2b, 0x2e, 0xa7, 0xcf, 0xdb, 0x36, 0x4f, 0x7f, 0x6d, 0xc5, 0x05, 0x37, 0x1f, 0xea,
|
||||
0x14, 0x67, 0x4a, 0x90, 0xee, 0x67, 0xb9, 0xd7, 0xae, 0xce, 0x8f, 0x89, 0x99, 0x97, 0xa0, 0xed,
|
||||
0x06, 0xfd, 0xfd, 0xf2, 0x6c, 0xc7, 0x4b, 0x50, 0x27, 0x79, 0x03, 0xe0, 0xd7, 0xe8, 0xbe, 0xe0,
|
||||
0x92, 0xa6, 0xf5, 0x9c, 0x72, 0x69, 0xad, 0xfd, 0x1b, 0xb2, 0x0e, 0x05, 0x97, 0xd3, 0x7a, 0xbe,
|
||||
0x2f, 0x5b, 0xed, 0x17, 0xb4, 0x6e, 0xb5, 0x3c, 0xa7, 0x5c, 0x66, 0x15, 0x08, 0x90, 0x26, 0xb8,
|
||||
0x7d, 0x43, 0xe6, 0xb5, 0xd6, 0xcc, 0xf3, 0xfd, 0xbf, 0x22, 0xff, 0x05, 0x0a, 0x8e, 0x2a, 0x25,
|
||||
0x0d, 0xad, 0x6a, 0x29, 0xb9, 0x2c, 0x68, 0x9b, 0x1a, 0xb0, 0x21, 0x08, 0x06, 0x91, 0x17, 0xdf,
|
||||
0x49, 0x46, 0x96, 0x27, 0x0e, 0x1f, 0x5c, 0xd1, 0x97, 0xd1, 0xd7, 0xcb, 0xb3, 0x9d, 0x87, 0xd7,
|
||||
0x64, 0xb3, 0xab, 0x94, 0x77, 0xd1, 0x99, 0x9c, 0x2f, 0x42, 0xef, 0x62, 0x11, 0x7a, 0xbf, 0x17,
|
||||
0xa1, 0xf7, 0x6d, 0x19, 0xf6, 0x2e, 0x96, 0x61, 0xef, 0xc7, 0x32, 0xec, 0xbd, 0x7f, 0x72, 0xad,
|
||||
0xeb, 0x36, 0x7e, 0xbb, 0x02, 0x1a, 0xd2, 0xde, 0x93, 0x7f, 0x67, 0xd8, 0xd6, 0xd3, 0x81, 0x0d,
|
||||
0xf1, 0xd3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x96, 0x16, 0x18, 0xc6, 0x45, 0x03, 0x00, 0x00,
|
||||
// 517 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x93, 0x31, 0x6f, 0xd3, 0x40,
|
||||
0x14, 0xc7, 0x63, 0x1a, 0x02, 0x5c, 0x5a, 0xaa, 0x5a, 0x55, 0x64, 0x0a, 0x72, 0xa2, 0x0e, 0x25,
|
||||
0xaa, 0xd4, 0x3b, 0xa5, 0x80, 0x84, 0x10, 0x4b, 0x02, 0x2a, 0xaa, 0xc4, 0x50, 0xdc, 0x8d, 0xc5,
|
||||
0x3a, 0xdb, 0xaf, 0xe1, 0x54, 0xee, 0xce, 0xdc, 0xd9, 0x26, 0xa9, 0xf8, 0x04, 0x4c, 0x7c, 0x0c,
|
||||
0xc4, 0xd4, 0x8f, 0xd1, 0xb1, 0x23, 0x62, 0x28, 0x28, 0x19, 0xfa, 0x29, 0x90, 0xd0, 0xdd, 0xb9,
|
||||
0xa5, 0x03, 0x03, 0x4b, 0x17, 0xdb, 0xba, 0xff, 0xff, 0xde, 0xef, 0xbd, 0xe7, 0xf7, 0xd0, 0x83,
|
||||
0x5c, 0x26, 0x84, 0x96, 0x69, 0xc1, 0xa4, 0x20, 0xd5, 0x80, 0x8c, 0x41, 0x80, 0x66, 0x1a, 0xe7,
|
||||
0x4a, 0x16, 0xd2, 0xef, 0xe8, 0x43, 0x96, 0x73, 0xa8, 0x70, 0x2e, 0x13, 0x5c, 0xbb, 0x70, 0x35,
|
||||
0x58, 0x5b, 0x1d, 0xcb, 0xb1, 0xb4, 0x16, 0x62, 0xbe, 0x9c, 0x7b, 0x2d, 0x4c, 0xa5, 0xe6, 0x52,
|
||||
0x93, 0x84, 0x6a, 0x20, 0xd5, 0x20, 0x81, 0x82, 0x0e, 0x48, 0x2a, 0x99, 0xa8, 0xf5, 0x15, 0xca,
|
||||
0x99, 0x90, 0xc4, 0x3e, 0xdd, 0xd1, 0xfa, 0x6b, 0xb4, 0xf8, 0xca, 0x11, 0xf7, 0x0b, 0x5a, 0x80,
|
||||
0xff, 0x1c, 0xb5, 0x72, 0xaa, 0x28, 0xd7, 0x81, 0xd7, 0xf3, 0xfa, 0xed, 0xed, 0x10, 0xff, 0x3b,
|
||||
0x03, 0xbc, 0x67, 0x5d, 0xa3, 0xe6, 0xc9, 0x59, 0xb7, 0x11, 0xd5, 0x77, 0xd6, 0x7f, 0x37, 0x51,
|
||||
0xcb, 0x09, 0xfe, 0x06, 0x5a, 0xe6, 0x74, 0x12, 0x27, 0xa5, 0xc8, 0xde, 0x43, 0xac, 0xd9, 0x11,
|
||||
0xd8, 0x88, 0x4b, 0xd1, 0x12, 0xa7, 0x93, 0x91, 0x3d, 0xdd, 0x67, 0x47, 0xe0, 0x3f, 0x46, 0x1d,
|
||||
0xd0, 0xa9, 0x92, 0x1f, 0x63, 0x9a, 0xa6, 0xb2, 0x14, 0x45, 0x4c, 0xb3, 0x4c, 0x81, 0xd6, 0xc1,
|
||||
0x8d, 0x9e, 0xd7, 0xbf, 0x13, 0xad, 0x3a, 0x75, 0xe8, 0xc4, 0xa1, 0xd3, 0xfc, 0x0f, 0xa8, 0xad,
|
||||
0x40, 0x83, 0xaa, 0x20, 0x3e, 0x00, 0x08, 0x16, 0x7a, 0x0b, 0xfd, 0xf6, 0xf6, 0x3d, 0xec, 0xea,
|
||||
0xc7, 0xa6, 0x7e, 0x5c, 0xd7, 0x8f, 0x5f, 0x48, 0x26, 0x46, 0x4f, 0x4c, 0x9a, 0xdf, 0x7e, 0x76,
|
||||
0xfb, 0x63, 0x56, 0xbc, 0x2b, 0x13, 0x9c, 0x4a, 0x4e, 0xea, 0x66, 0xb9, 0xd7, 0x96, 0xce, 0x0e,
|
||||
0x49, 0x31, 0xcd, 0x41, 0xdb, 0x0b, 0xfa, 0xeb, 0xf9, 0xf1, 0xa6, 0x17, 0xa1, 0x1a, 0xb2, 0x03,
|
||||
0xe0, 0x97, 0xe8, 0x2e, 0x67, 0x22, 0x4e, 0xca, 0x69, 0xcc, 0x84, 0xa5, 0x36, 0xaf, 0x89, 0xda,
|
||||
0xe6, 0x4c, 0x8c, 0xca, 0xe9, 0xae, 0x30, 0xd8, 0x4f, 0x68, 0xc5, 0x62, 0x59, 0x16, 0x33, 0x91,
|
||||
0x2a, 0xe0, 0x20, 0x8a, 0xe0, 0xe6, 0x35, 0x91, 0x97, 0x0d, 0x99, 0x65, 0xbb, 0x17, 0x20, 0xff,
|
||||
0x29, 0x0a, 0x0e, 0x94, 0x14, 0x45, 0xac, 0x4a, 0x21, 0x98, 0x18, 0xc7, 0x66, 0x6a, 0xc0, 0x0e,
|
||||
0x41, 0xd0, 0xea, 0x79, 0xfd, 0xdb, 0x51, 0xc7, 0xea, 0x91, 0x93, 0xf7, 0x2e, 0x55, 0xff, 0x0d,
|
||||
0x5a, 0xcc, 0x95, 0xcc, 0xa5, 0x06, 0x65, 0x9b, 0x75, 0xcb, 0xfc, 0xcd, 0x11, 0x36, 0x79, 0xfd,
|
||||
0x38, 0xeb, 0x6e, 0xfc, 0x47, 0x5e, 0x2f, 0x21, 0x8d, 0xda, 0x17, 0x31, 0x76, 0x00, 0x9e, 0xf5,
|
||||
0x3e, 0x9f, 0x1f, 0x6f, 0xde, 0xbf, 0xe2, 0x9b, 0x5c, 0x2e, 0x4e, 0x3d, 0x8d, 0xc3, 0x93, 0x59,
|
||||
0xe8, 0x9d, 0xce, 0x42, 0xef, 0xd7, 0x2c, 0xf4, 0xbe, 0xcc, 0xc3, 0xc6, 0xe9, 0x3c, 0x6c, 0x7c,
|
||||
0x9f, 0x87, 0x8d, 0xb7, 0x0f, 0xaf, 0x00, 0xcd, 0x44, 0x6f, 0x71, 0xa8, 0x88, 0x59, 0xbd, 0xbf,
|
||||
0x31, 0x2c, 0x35, 0x69, 0xd9, 0xbd, 0x78, 0xf4, 0x27, 0x00, 0x00, 0xff, 0xff, 0x32, 0x3f, 0xb6,
|
||||
0x9a, 0x98, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
|
||||
@ -260,6 +267,16 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
{
|
||||
size := m.ProposerFee.Size()
|
||||
i -= size
|
||||
if _, err := m.ProposerFee.MarshalTo(dAtA[i:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x3a
|
||||
if m.FrontRunningProtection {
|
||||
i--
|
||||
if m.FrontRunningProtection {
|
||||
@ -383,6 +400,8 @@ func (m *Params) Size() (n int) {
|
||||
if m.FrontRunningProtection {
|
||||
n += 2
|
||||
}
|
||||
l = m.ProposerFee.Size()
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
return n
|
||||
}
|
||||
|
||||
@ -677,6 +696,40 @@ func (m *Params) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
}
|
||||
m.FrontRunningProtection = bool(v != 0)
|
||||
case 7:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ProposerFee", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.ProposerFee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenesis(dAtA[iNdEx:])
|
||||
|
||||
@ -116,6 +116,7 @@ func TestMsgUpdateParams(t *testing.T) {
|
||||
msg: types.MsgUpdateParams{
|
||||
Authority: sdk.AccAddress([]byte("test")).String(),
|
||||
Params: types.Params{
|
||||
ProposerFee: sdk.NewDec(1),
|
||||
EscrowAccountAddress: sdk.AccAddress([]byte("test")).String(),
|
||||
},
|
||||
},
|
||||
|
||||
@ -3,6 +3,7 @@ package types
|
||||
import (
|
||||
fmt "fmt"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
@ -13,10 +14,17 @@ var (
|
||||
DefaultMinBuyInFee = sdk.Coins{}
|
||||
DefaultMinBidIncrement = sdk.Coins{}
|
||||
DefaultFrontRunningProtection = true
|
||||
DefaultProposerFee = sdk.ZeroDec()
|
||||
)
|
||||
|
||||
// NewParams returns a new Params instance with the provided values.
|
||||
func NewParams(maxBundleSize uint32, escrowAccountAddress string, reserveFee, minBuyInFee, minBidIncrement sdk.Coins, frontRunningProtection bool) Params {
|
||||
func NewParams(
|
||||
maxBundleSize uint32,
|
||||
escrowAccountAddress string,
|
||||
reserveFee, minBuyInFee, minBidIncrement sdk.Coins,
|
||||
frontRunningProtection bool,
|
||||
proposerFee sdk.Dec,
|
||||
) Params {
|
||||
return Params{
|
||||
MaxBundleSize: maxBundleSize,
|
||||
EscrowAccountAddress: escrowAccountAddress,
|
||||
@ -24,6 +32,7 @@ func NewParams(maxBundleSize uint32, escrowAccountAddress string, reserveFee, mi
|
||||
MinBuyInFee: minBuyInFee,
|
||||
MinBidIncrement: minBidIncrement,
|
||||
FrontRunningProtection: frontRunningProtection,
|
||||
ProposerFee: proposerFee,
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,6 +45,7 @@ func DefaultParams() Params {
|
||||
DefaultMinBuyInFee,
|
||||
DefaultMinBidIncrement,
|
||||
DefaultFrontRunningProtection,
|
||||
DefaultProposerFee,
|
||||
)
|
||||
}
|
||||
|
||||
@ -57,10 +67,29 @@ func (p Params) Validate() error {
|
||||
return fmt.Errorf("invalid minimum bid increment (%s)", err)
|
||||
}
|
||||
|
||||
if err := validateProposerFee(p.ProposerFee); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateEscrowAccountAddress ensures the escrow account address is a valid address (if set).
|
||||
func validateProposerFee(v sdk.Dec) error {
|
||||
if v.IsNil() {
|
||||
return fmt.Errorf("proposer fee cannot be nil: %s", v)
|
||||
}
|
||||
if v.IsNegative() {
|
||||
return fmt.Errorf("proposer fee cannot be negative: %s", v)
|
||||
}
|
||||
if v.GT(math.LegacyOneDec()) {
|
||||
return fmt.Errorf("proposer fee too large: %s", v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateEscrowAccountAddress ensures the escrow account address is a valid
|
||||
// address.
|
||||
func validateEscrowAccountAddress(account string) error {
|
||||
// If the escrow account address is set, ensure it is a valid address.
|
||||
if _, err := sdk.AccAddressFromBech32(account); err != nil {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user