mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-25 07:45:18 +00:00
BEP3: support multiple assets (#616)
* wip: refactor to allow multiple bep3 assets * update tests * sims: validate asset before claiming * move asset supply to params * update tests * fix sims * fix tests * wip: add migration from v0.9 -> v0.10 bep3 * fix build and migration tests * nit: rename file * move asset supply out of params * update committee tests * fix sims * address review comments * address review comments * address review comments
This commit is contained in:
parent
928ce5f064
commit
790753f156
@ -8,10 +8,10 @@ const (
|
|||||||
|
|
||||||
// Default simulation operation weights for messages and gov proposals
|
// Default simulation operation weights for messages and gov proposals
|
||||||
const (
|
const (
|
||||||
DefaultWeightMsgPlaceBid int = 75
|
DefaultWeightMsgPlaceBid int = 20
|
||||||
DefaultWeightMsgCreateAtomicSwap int = 50
|
DefaultWeightMsgCreateAtomicSwap int = 20
|
||||||
DefaultWeightMsgUpdatePrices int = 50
|
DefaultWeightMsgUpdatePrices int = 20
|
||||||
DefaultWeightMsgCdp int = 100
|
DefaultWeightMsgCdp int = 20
|
||||||
DefaultWeightMsgClaimReward int = 50
|
DefaultWeightMsgClaimReward int = 20
|
||||||
OpWeightSubmitCommitteeChangeProposal int = 50
|
OpWeightSubmitCommitteeChangeProposal int = 20
|
||||||
)
|
)
|
||||||
|
@ -3,6 +3,7 @@ package app
|
|||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
@ -110,6 +111,33 @@ func (tApp TestApp) InitializeFromGenesisStates(genesisStates ...GenesisState) T
|
|||||||
return tApp
|
return tApp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InitializeFromGenesisStatesWithTime calls InitChain on the app using the default genesis state, overwitten with any passed in genesis states and genesis Time
|
||||||
|
func (tApp TestApp) InitializeFromGenesisStatesWithTime(genTime time.Time, genesisStates ...GenesisState) TestApp {
|
||||||
|
// Create a default genesis state and overwrite with provided values
|
||||||
|
genesisState := NewDefaultGenesisState()
|
||||||
|
for _, state := range genesisStates {
|
||||||
|
for k, v := range state {
|
||||||
|
genesisState[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the chain
|
||||||
|
stateBytes, err := codec.MarshalJSONIndent(tApp.cdc, genesisState)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
tApp.InitChain(
|
||||||
|
abci.RequestInitChain{
|
||||||
|
Time: genTime,
|
||||||
|
Validators: []abci.ValidatorUpdate{},
|
||||||
|
AppStateBytes: stateBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
tApp.Commit()
|
||||||
|
tApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: tApp.LastBlockHeight() + 1}})
|
||||||
|
return tApp
|
||||||
|
}
|
||||||
|
|
||||||
func (tApp TestApp) CheckBalance(t *testing.T, ctx sdk.Context, owner sdk.AccAddress, expectedCoins sdk.Coins) {
|
func (tApp TestApp) CheckBalance(t *testing.T, ctx sdk.Context, owner sdk.AccAddress, expectedCoins sdk.Coins) {
|
||||||
acc := tApp.GetAccountKeeper().GetAccount(ctx, owner)
|
acc := tApp.GetAccountKeeper().GetAccount(ctx, owner)
|
||||||
require.NotNilf(t, acc, "account with address '%s' doesn't exist", owner)
|
require.NotNilf(t, acc, "account with address '%s' doesn't exist", owner)
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/x/supply"
|
"github.com/cosmos/cosmos-sdk/x/supply"
|
||||||
|
|
||||||
"github.com/kava-labs/kava/x/auction"
|
"github.com/kava-labs/kava/x/auction"
|
||||||
"github.com/kava-labs/kava/x/bep3"
|
v0_8bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_9"
|
||||||
"github.com/kava-labs/kava/x/cdp"
|
"github.com/kava-labs/kava/x/cdp"
|
||||||
"github.com/kava-labs/kava/x/committee"
|
"github.com/kava-labs/kava/x/committee"
|
||||||
"github.com/kava-labs/kava/x/incentive"
|
"github.com/kava-labs/kava/x/incentive"
|
||||||
@ -108,23 +108,23 @@ func addAuctionState(cdc *codec.Codec, appState genutil.AppMap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addBep3State(cdc *codec.Codec, appState genutil.AppMap) {
|
func addBep3State(cdc *codec.Codec, appState genutil.AppMap) {
|
||||||
appState[bep3.ModuleName] = cdc.MustMarshalJSON(bep3.NewGenesisState(
|
appState[v0_8bep3.ModuleName] = cdc.MustMarshalJSON(v0_8bep3.NewGenesisState(
|
||||||
bep3.NewParams(
|
v0_8bep3.NewParams(
|
||||||
mustAccAddressFromBech32(deputyAddressBech32),
|
mustAccAddressFromBech32(deputyAddressBech32),
|
||||||
bep3.DefaultBnbDeputyFixedFee,
|
v0_8bep3.DefaultBnbDeputyFixedFee,
|
||||||
bep3.DefaultMinAmount,
|
v0_8bep3.DefaultMinAmount,
|
||||||
bep3.DefaultMaxAmount,
|
v0_8bep3.DefaultMaxAmount,
|
||||||
bep3.DefaultMinBlockLock,
|
v0_8bep3.DefaultMinBlockLock,
|
||||||
bep3.DefaultMaxBlockLock,
|
v0_8bep3.DefaultMaxBlockLock,
|
||||||
bep3.AssetParams{{
|
v0_8bep3.AssetParams{{
|
||||||
Denom: bnbDenom,
|
Denom: bnbDenom,
|
||||||
CoinID: 714,
|
CoinID: 714,
|
||||||
Limit: sdk.NewInt(4_000_000_000_000),
|
Limit: sdk.NewInt(4_000_000_000_000),
|
||||||
Active: true,
|
Active: true,
|
||||||
}},
|
}},
|
||||||
),
|
),
|
||||||
bep3.AtomicSwaps{},
|
v0_8bep3.AtomicSwaps{},
|
||||||
bep3.AssetSupplies{},
|
v0_8bep3.AssetSupplies{},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,8 +203,8 @@ func addCommitteeState(cdc *codec.Codec, appState genutil.AppMap) {
|
|||||||
Key: string(auction.KeyIncrementCollateral),
|
Key: string(auction.KeyIncrementCollateral),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Subspace: bep3.ModuleName,
|
Subspace: v0_8bep3.ModuleName,
|
||||||
Key: string(bep3.KeySupportedAssets),
|
Key: string(v0_8bep3.KeySupportedAssets),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Subspace: cdp.ModuleName,
|
Subspace: cdp.ModuleName,
|
||||||
|
68
migrate/v0_11/migrate.go
Normal file
68
migrate/v0_11/migrate.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package v0_11
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
|
v0_11bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_11"
|
||||||
|
v0_9bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_9"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateBep3 migrates from a v0.9 (or v0.10) bep3 genesis state to a v0.11 bep3 genesis state
|
||||||
|
func MigrateBep3(oldGenState v0_9bep3.GenesisState) v0_11bep3.GenesisState {
|
||||||
|
var assetParams v0_11bep3.AssetParams
|
||||||
|
v0_9Params := oldGenState.Params
|
||||||
|
|
||||||
|
for _, asset := range v0_9Params.SupportedAssets {
|
||||||
|
v10AssetParam := v0_11bep3.AssetParam{
|
||||||
|
Active: asset.Active,
|
||||||
|
Denom: asset.Denom,
|
||||||
|
CoinID: asset.CoinID,
|
||||||
|
DeputyAddress: v0_9Params.BnbDeputyAddress,
|
||||||
|
FixedFee: v0_9Params.BnbDeputyFixedFee,
|
||||||
|
MinSwapAmount: v0_9Params.MinAmount,
|
||||||
|
MaxSwapAmount: v0_9Params.MaxAmount,
|
||||||
|
MinBlockLock: v0_9Params.MinBlockLock,
|
||||||
|
MaxBlockLock: v0_9Params.MaxBlockLock,
|
||||||
|
SupplyLimit: v0_11bep3.AssetSupply{
|
||||||
|
SupplyLimit: sdk.NewCoin(asset.Denom, sdk.ZeroInt()),
|
||||||
|
CurrentSupply: sdk.NewCoin(asset.Denom, sdk.ZeroInt()),
|
||||||
|
IncomingSupply: sdk.NewCoin(asset.Denom, sdk.ZeroInt()),
|
||||||
|
OutgoingSupply: sdk.NewCoin(asset.Denom, sdk.ZeroInt()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assetParams = append(assetParams, v10AssetParam)
|
||||||
|
}
|
||||||
|
for _, supply := range oldGenState.AssetSupplies {
|
||||||
|
for _, asset := range assetParams {
|
||||||
|
if asset.Denom == supply.Denom {
|
||||||
|
asset.SupplyLimit.SupplyLimit = supply.SupplyLimit
|
||||||
|
asset.SupplyLimit.CurrentSupply = supply.CurrentSupply
|
||||||
|
asset.SupplyLimit.IncomingSupply = supply.IncomingSupply
|
||||||
|
asset.SupplyLimit.OutgoingSupply = supply.OutgoingSupply
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var swaps v0_11bep3.AtomicSwaps
|
||||||
|
for _, oldSwap := range oldGenState.AtomicSwaps {
|
||||||
|
newSwap := v0_11bep3.AtomicSwap{
|
||||||
|
Amount: oldSwap.Amount,
|
||||||
|
RandomNumberHash: oldSwap.RandomNumberHash,
|
||||||
|
ExpireHeight: oldSwap.ExpireHeight,
|
||||||
|
Timestamp: oldSwap.Timestamp,
|
||||||
|
Sender: oldSwap.Sender,
|
||||||
|
Recipient: oldSwap.Recipient,
|
||||||
|
SenderOtherChain: oldSwap.SenderOtherChain,
|
||||||
|
RecipientOtherChain: oldSwap.RecipientOtherChain,
|
||||||
|
ClosedBlock: oldSwap.ClosedBlock,
|
||||||
|
Status: v0_11bep3.SwapStatus(oldSwap.Status),
|
||||||
|
CrossChain: oldSwap.CrossChain,
|
||||||
|
Direction: v0_11bep3.SwapDirection(oldSwap.Direction),
|
||||||
|
}
|
||||||
|
swaps = append(swaps, newSwap)
|
||||||
|
}
|
||||||
|
return v0_11bep3.GenesisState{
|
||||||
|
Params: v0_11bep3.Params{
|
||||||
|
AssetParams: assetParams},
|
||||||
|
AtomicSwaps: swaps,
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,7 @@ import (
|
|||||||
v032tendermint "github.com/kava-labs/kava/migrate/v0_8/tendermint/v0_32"
|
v032tendermint "github.com/kava-labs/kava/migrate/v0_8/tendermint/v0_32"
|
||||||
v033tendermint "github.com/kava-labs/kava/migrate/v0_8/tendermint/v0_33"
|
v033tendermint "github.com/kava-labs/kava/migrate/v0_8/tendermint/v0_33"
|
||||||
"github.com/kava-labs/kava/x/auction"
|
"github.com/kava-labs/kava/x/auction"
|
||||||
"github.com/kava-labs/kava/x/bep3"
|
v0_8bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_9"
|
||||||
"github.com/kava-labs/kava/x/cdp"
|
"github.com/kava-labs/kava/x/cdp"
|
||||||
"github.com/kava-labs/kava/x/committee"
|
"github.com/kava-labs/kava/x/committee"
|
||||||
"github.com/kava-labs/kava/x/incentive"
|
"github.com/kava-labs/kava/x/incentive"
|
||||||
@ -90,7 +90,7 @@ func MigrateAppState(v0_3AppState v038genutil.AppMap) v038genutil.AppMap {
|
|||||||
|
|
||||||
// migrate new modules (by adding new gen states)
|
// migrate new modules (by adding new gen states)
|
||||||
v0_8AppState[auction.ModuleName] = v0_8Codec.MustMarshalJSON(auction.DefaultGenesisState())
|
v0_8AppState[auction.ModuleName] = v0_8Codec.MustMarshalJSON(auction.DefaultGenesisState())
|
||||||
v0_8AppState[bep3.ModuleName] = v0_8Codec.MustMarshalJSON(bep3.DefaultGenesisState())
|
v0_8AppState[v0_8bep3.ModuleName] = v0_8Codec.MustMarshalJSON(v0_8bep3.DefaultGenesisState())
|
||||||
v0_8AppState[cdp.ModuleName] = v0_8Codec.MustMarshalJSON(cdp.DefaultGenesisState())
|
v0_8AppState[cdp.ModuleName] = v0_8Codec.MustMarshalJSON(cdp.DefaultGenesisState())
|
||||||
v0_8AppState[committee.ModuleName] = v0_8Codec.MustMarshalJSON(committee.DefaultGenesisState())
|
v0_8AppState[committee.ModuleName] = v0_8Codec.MustMarshalJSON(committee.DefaultGenesisState())
|
||||||
v0_8AppState[incentive.ModuleName] = v0_8Codec.MustMarshalJSON(incentive.DefaultGenesisState())
|
v0_8AppState[incentive.ModuleName] = v0_8Codec.MustMarshalJSON(incentive.DefaultGenesisState())
|
||||||
|
@ -9,7 +9,4 @@ import (
|
|||||||
func BeginBlocker(ctx sdk.Context, k Keeper) {
|
func BeginBlocker(ctx sdk.Context, k Keeper) {
|
||||||
k.UpdateExpiredAtomicSwaps(ctx)
|
k.UpdateExpiredAtomicSwaps(ctx)
|
||||||
k.DeleteClosedAtomicSwapsFromLongtermStorage(ctx)
|
k.DeleteClosedAtomicSwapsFromLongtermStorage(ctx)
|
||||||
if ctx.BlockTime().After(SupplyLimitUpgradeTime) {
|
|
||||||
k.UpdateAssetSupplies(ctx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package bep3_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
@ -31,14 +30,14 @@ func (suite *ABCITestSuite) SetupTest() {
|
|||||||
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
||||||
|
|
||||||
// Set up auth GenesisState
|
// Set up auth GenesisState
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(11)
|
_, addrs := app.GeneratePrivKeyAddressPairs(12)
|
||||||
coins := []sdk.Coins{}
|
coins := []sdk.Coins{}
|
||||||
for j := 0; j < 11; j++ {
|
for j := 0; j < 12; j++ {
|
||||||
coins = append(coins, cs(c("bnb", 10000000000), c("ukava", 10000000000)))
|
coins = append(coins, cs(c("bnb", 10000000000), c("ukava", 10000000000)))
|
||||||
}
|
}
|
||||||
authGS := app.NewAuthGenState(addrs, coins)
|
authGS := app.NewAuthGenState(addrs, coins)
|
||||||
// Initialize test app
|
// Initialize test app
|
||||||
tApp.InitializeFromGenesisStates(authGS, NewBep3GenStateMulti(addrs[0]))
|
tApp.InitializeFromGenesisStates(authGS, NewBep3GenStateMulti(addrs[11]))
|
||||||
|
|
||||||
suite.ctx = ctx
|
suite.ctx = ctx
|
||||||
suite.app = tApp
|
suite.app = tApp
|
||||||
@ -61,12 +60,12 @@ func (suite *ABCITestSuite) ResetKeeper() {
|
|||||||
|
|
||||||
// Create atomic swap and check err to confirm creation
|
// Create atomic swap and check err to confirm creation
|
||||||
err := suite.keeper.CreateAtomicSwap(suite.ctx, randomNumberHash, timestamp, expireHeight,
|
err := suite.keeper.CreateAtomicSwap(suite.ctx, randomNumberHash, timestamp, expireHeight,
|
||||||
suite.addrs[0], suite.addrs[i], TestSenderOtherChain, TestRecipientOtherChain,
|
suite.addrs[11], suite.addrs[i], TestSenderOtherChain, TestRecipientOtherChain,
|
||||||
amount, true)
|
amount, true)
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
|
|
||||||
// Store swap's calculated ID and secret random number
|
// Store swap's calculated ID and secret random number
|
||||||
swapID := bep3.CalculateSwapID(randomNumberHash, suite.addrs[0], TestSenderOtherChain)
|
swapID := bep3.CalculateSwapID(randomNumberHash, suite.addrs[11], TestSenderOtherChain)
|
||||||
swapIDs = append(swapIDs, swapID)
|
swapIDs = append(swapIDs, swapID)
|
||||||
randomNumbers = append(randomNumbers, randomNumber[:])
|
randomNumbers = append(randomNumbers, randomNumber[:])
|
||||||
}
|
}
|
||||||
@ -240,61 +239,6 @@ func (suite *ABCITestSuite) TestBeginBlocker_DeleteClosedAtomicSwapsFromLongterm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ABCITestSuite) TestBeginBlocker_UpdateAssetSupplies() {
|
|
||||||
// set new asset limit in the params
|
|
||||||
newBnbLimit := c("bnb", 100)
|
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
|
||||||
for i := range params.SupportedAssets {
|
|
||||||
if params.SupportedAssets[i].Denom != newBnbLimit.Denom {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
params.SupportedAssets[i].Limit = newBnbLimit.Amount
|
|
||||||
}
|
|
||||||
suite.keeper.SetParams(suite.ctx, params)
|
|
||||||
|
|
||||||
// store the old limit for future reference
|
|
||||||
supply, found := suite.keeper.GetAssetSupply(suite.ctx, []byte(newBnbLimit.Denom))
|
|
||||||
suite.True(found)
|
|
||||||
oldBnbLimit := supply.SupplyLimit
|
|
||||||
|
|
||||||
// run before the upgrade time, check limit was not changed
|
|
||||||
bep3.BeginBlocker(suite.ctx.WithBlockTime(bep3.SupplyLimitUpgradeTime.Add(-time.Hour)), suite.keeper)
|
|
||||||
|
|
||||||
supply, found = suite.keeper.GetAssetSupply(suite.ctx, []byte(newBnbLimit.Denom))
|
|
||||||
suite.True(found)
|
|
||||||
suite.True(supply.SupplyLimit.IsEqual(oldBnbLimit))
|
|
||||||
|
|
||||||
// run at precise upgrade time, check limit was not changed
|
|
||||||
bep3.BeginBlocker(suite.ctx.WithBlockTime(bep3.SupplyLimitUpgradeTime), suite.keeper)
|
|
||||||
|
|
||||||
supply, found = suite.keeper.GetAssetSupply(suite.ctx, []byte(newBnbLimit.Denom))
|
|
||||||
suite.True(found)
|
|
||||||
suite.True(supply.SupplyLimit.IsEqual(oldBnbLimit))
|
|
||||||
|
|
||||||
// run after upgrade time, check limit was changed
|
|
||||||
bep3.BeginBlocker(suite.ctx.WithBlockTime(bep3.SupplyLimitUpgradeTime.Add(time.Nanosecond)), suite.keeper)
|
|
||||||
|
|
||||||
supply, found = suite.keeper.GetAssetSupply(suite.ctx, []byte(newBnbLimit.Denom))
|
|
||||||
suite.True(found)
|
|
||||||
suite.True(supply.SupplyLimit.IsEqual(newBnbLimit))
|
|
||||||
|
|
||||||
// run again with new params, check limit was updated to new param limit
|
|
||||||
finalBnbLimit := c("bnb", 5000000000000)
|
|
||||||
params = suite.keeper.GetParams(suite.ctx)
|
|
||||||
for i := range params.SupportedAssets {
|
|
||||||
if params.SupportedAssets[i].Denom != finalBnbLimit.Denom {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
params.SupportedAssets[i].Limit = finalBnbLimit.Amount
|
|
||||||
}
|
|
||||||
suite.keeper.SetParams(suite.ctx, params)
|
|
||||||
bep3.BeginBlocker(suite.ctx.WithBlockTime(bep3.SupplyLimitUpgradeTime.Add(time.Hour)), suite.keeper)
|
|
||||||
|
|
||||||
supply, found = suite.keeper.GetAssetSupply(suite.ctx, []byte(newBnbLimit.Denom))
|
|
||||||
suite.True(found)
|
|
||||||
suite.True(supply.SupplyLimit.IsEqual(finalBnbLimit))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestABCITestSuite(t *testing.T) {
|
func TestABCITestSuite(t *testing.T) {
|
||||||
suite.Run(t, new(ABCITestSuite))
|
suite.Run(t, new(ABCITestSuite))
|
||||||
}
|
}
|
||||||
|
198
x/bep3/alias.go
198
x/bep3/alias.go
@ -1,140 +1,146 @@
|
|||||||
package bep3
|
package bep3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kava-labs/kava/x/bep3/client/rest"
|
|
||||||
"github.com/kava-labs/kava/x/bep3/keeper"
|
"github.com/kava-labs/kava/x/bep3/keeper"
|
||||||
"github.com/kava-labs/kava/x/bep3/types"
|
"github.com/kava-labs/kava/x/bep3/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
// autogenerated code using github.com/rigelrozanski/multitool
|
||||||
|
// aliases generated for the following subdirectories:
|
||||||
|
// ALIASGEN: github.com/kava-labs/kava/x/bep3/keeper
|
||||||
|
// ALIASGEN: github.com/kava-labs/kava/x/bep3/types
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AddrByteCount = types.AddrByteCount
|
|
||||||
AttributeKeyAmount = types.AttributeKeyAmount
|
|
||||||
AttributeKeyAtomicSwapID = types.AttributeKeyAtomicSwapID
|
|
||||||
AttributeKeyAtomicSwapIDs = types.AttributeKeyAtomicSwapIDs
|
|
||||||
AttributeKeyClaimSender = types.AttributeKeyClaimSender
|
|
||||||
AttributeKeyDirection = types.AttributeKeyDirection
|
|
||||||
AttributeKeyExpireHeight = types.AttributeKeyExpireHeight
|
|
||||||
AttributeKeyRandomNumber = types.AttributeKeyRandomNumber
|
|
||||||
AttributeKeyRandomNumberHash = types.AttributeKeyRandomNumberHash
|
|
||||||
AttributeKeyRecipient = types.AttributeKeyRecipient
|
|
||||||
AttributeKeyRefundSender = types.AttributeKeyRefundSender
|
|
||||||
AttributeKeySender = types.AttributeKeySender
|
|
||||||
AttributeKeySenderOtherChain = types.AttributeKeySenderOtherChain
|
|
||||||
AttributeKeyTimestamp = types.AttributeKeyTimestamp
|
|
||||||
AttributeValueCategory = types.AttributeValueCategory
|
|
||||||
CalcSwapID = types.CalcSwapID
|
|
||||||
ClaimAtomicSwap = types.ClaimAtomicSwap
|
|
||||||
Completed = types.Completed
|
|
||||||
CreateAtomicSwap = types.CreateAtomicSwap
|
|
||||||
DefaultLongtermStorageDuration = types.DefaultLongtermStorageDuration
|
|
||||||
DefaultParamspace = types.DefaultParamspace
|
|
||||||
EventTypeClaimAtomicSwap = types.EventTypeClaimAtomicSwap
|
|
||||||
EventTypeCreateAtomicSwap = types.EventTypeCreateAtomicSwap
|
EventTypeCreateAtomicSwap = types.EventTypeCreateAtomicSwap
|
||||||
|
EventTypeClaimAtomicSwap = types.EventTypeClaimAtomicSwap
|
||||||
EventTypeRefundAtomicSwap = types.EventTypeRefundAtomicSwap
|
EventTypeRefundAtomicSwap = types.EventTypeRefundAtomicSwap
|
||||||
EventTypeSwapsExpired = types.EventTypeSwapsExpired
|
EventTypeSwapsExpired = types.EventTypeSwapsExpired
|
||||||
Expired = types.Expired
|
AttributeValueCategory = types.AttributeValueCategory
|
||||||
INVALID = types.INVALID
|
AttributeKeySender = types.AttributeKeySender
|
||||||
Incoming = types.Incoming
|
AttributeKeyRecipient = types.AttributeKeyRecipient
|
||||||
Int64Size = types.Int64Size
|
AttributeKeyAtomicSwapID = types.AttributeKeyAtomicSwapID
|
||||||
MaxExpectedIncomeLength = types.MaxExpectedIncomeLength
|
AttributeKeyRandomNumberHash = types.AttributeKeyRandomNumberHash
|
||||||
MaxOtherChainAddrLength = types.MaxOtherChainAddrLength
|
AttributeKeyTimestamp = types.AttributeKeyTimestamp
|
||||||
|
AttributeKeySenderOtherChain = types.AttributeKeySenderOtherChain
|
||||||
|
AttributeKeyExpireHeight = types.AttributeKeyExpireHeight
|
||||||
|
AttributeKeyAmount = types.AttributeKeyAmount
|
||||||
|
AttributeKeyDirection = types.AttributeKeyDirection
|
||||||
|
AttributeKeyClaimSender = types.AttributeKeyClaimSender
|
||||||
|
AttributeKeyRandomNumber = types.AttributeKeyRandomNumber
|
||||||
|
AttributeKeyRefundSender = types.AttributeKeyRefundSender
|
||||||
|
AttributeKeyAtomicSwapIDs = types.AttributeKeyAtomicSwapIDs
|
||||||
|
AttributeExpirationBlock = types.AttributeExpirationBlock
|
||||||
ModuleName = types.ModuleName
|
ModuleName = types.ModuleName
|
||||||
NULL = types.NULL
|
StoreKey = types.StoreKey
|
||||||
Open = types.Open
|
RouterKey = types.RouterKey
|
||||||
Outgoing = types.Outgoing
|
|
||||||
QuerierRoute = types.QuerierRoute
|
QuerierRoute = types.QuerierRoute
|
||||||
|
DefaultParamspace = types.DefaultParamspace
|
||||||
|
DefaultLongtermStorageDuration = types.DefaultLongtermStorageDuration
|
||||||
|
CreateAtomicSwap = types.CreateAtomicSwap
|
||||||
|
ClaimAtomicSwap = types.ClaimAtomicSwap
|
||||||
|
RefundAtomicSwap = types.RefundAtomicSwap
|
||||||
|
CalcSwapID = types.CalcSwapID
|
||||||
|
Int64Size = types.Int64Size
|
||||||
|
RandomNumberHashLength = types.RandomNumberHashLength
|
||||||
|
RandomNumberLength = types.RandomNumberLength
|
||||||
|
AddrByteCount = types.AddrByteCount
|
||||||
|
MaxOtherChainAddrLength = types.MaxOtherChainAddrLength
|
||||||
|
SwapIDLength = types.SwapIDLength
|
||||||
|
MaxExpectedIncomeLength = types.MaxExpectedIncomeLength
|
||||||
QueryGetAssetSupply = types.QueryGetAssetSupply
|
QueryGetAssetSupply = types.QueryGetAssetSupply
|
||||||
|
QueryGetAssetSupplies = types.QueryGetAssetSupplies
|
||||||
QueryGetAtomicSwap = types.QueryGetAtomicSwap
|
QueryGetAtomicSwap = types.QueryGetAtomicSwap
|
||||||
QueryGetAtomicSwaps = types.QueryGetAtomicSwaps
|
QueryGetAtomicSwaps = types.QueryGetAtomicSwaps
|
||||||
QueryGetParams = types.QueryGetParams
|
QueryGetParams = types.QueryGetParams
|
||||||
RandomNumberHashLength = types.RandomNumberHashLength
|
NULL = types.NULL
|
||||||
RandomNumberLength = types.RandomNumberLength
|
Open = types.Open
|
||||||
RefundAtomicSwap = types.RefundAtomicSwap
|
Completed = types.Completed
|
||||||
RouterKey = types.RouterKey
|
Expired = types.Expired
|
||||||
StoreKey = types.StoreKey
|
INVALID = types.INVALID
|
||||||
SwapIDLength = types.SwapIDLength
|
Incoming = types.Incoming
|
||||||
|
Outgoing = types.Outgoing
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// functions aliases
|
||||||
NewKeeper = keeper.NewKeeper
|
NewKeeper = keeper.NewKeeper
|
||||||
NewQuerier = keeper.NewQuerier
|
NewQuerier = keeper.NewQuerier
|
||||||
RegisterRoutes = rest.RegisterRoutes
|
NewAssetSupply = types.NewAssetSupply
|
||||||
|
RegisterCodec = types.RegisterCodec
|
||||||
|
NewGenesisState = types.NewGenesisState
|
||||||
|
DefaultGenesisState = types.DefaultGenesisState
|
||||||
|
GenerateSecureRandomNumber = types.GenerateSecureRandomNumber
|
||||||
CalculateRandomHash = types.CalculateRandomHash
|
CalculateRandomHash = types.CalculateRandomHash
|
||||||
CalculateSwapID = types.CalculateSwapID
|
CalculateSwapID = types.CalculateSwapID
|
||||||
DefaultGenesisState = types.DefaultGenesisState
|
|
||||||
DefaultParams = types.DefaultParams
|
|
||||||
ErrAssetNotActive = types.ErrAssetNotActive
|
|
||||||
ErrAssetNotSupported = types.ErrAssetNotSupported
|
|
||||||
ErrAssetSupplyNotFound = types.ErrAssetSupplyNotFound
|
|
||||||
ErrAtomicSwapAlreadyExists = types.ErrAtomicSwapAlreadyExists
|
|
||||||
ErrAtomicSwapNotFound = types.ErrAtomicSwapNotFound
|
|
||||||
ErrExceedsAvailableSupply = types.ErrExceedsAvailableSupply
|
|
||||||
ErrExceedsSupplyLimit = types.ErrExceedsSupplyLimit
|
|
||||||
ErrInvalidClaimSecret = types.ErrInvalidClaimSecret
|
|
||||||
ErrInvalidCurrentSupply = types.ErrInvalidCurrentSupply
|
|
||||||
ErrInvalidHeightSpan = types.ErrInvalidHeightSpan
|
|
||||||
ErrInvalidAmount = types.ErrInvalidAmount
|
|
||||||
ErrInvalidIncomingSupply = types.ErrInvalidIncomingSupply
|
|
||||||
ErrInvalidOutgoingSupply = types.ErrInvalidOutgoingSupply
|
|
||||||
ErrInvalidTimestamp = types.ErrInvalidTimestamp
|
|
||||||
ErrSwapNotClaimable = types.ErrSwapNotClaimable
|
|
||||||
ErrSwapNotRefundable = types.ErrSwapNotRefundable
|
|
||||||
GenerateSecureRandomNumber = types.GenerateSecureRandomNumber
|
|
||||||
GetAtomicSwapByHeightKey = types.GetAtomicSwapByHeightKey
|
GetAtomicSwapByHeightKey = types.GetAtomicSwapByHeightKey
|
||||||
NewAssetSupply = types.NewAssetSupply
|
|
||||||
NewAtomicSwap = types.NewAtomicSwap
|
|
||||||
NewGenesisState = types.NewGenesisState
|
|
||||||
NewMsgClaimAtomicSwap = types.NewMsgClaimAtomicSwap
|
|
||||||
NewMsgCreateAtomicSwap = types.NewMsgCreateAtomicSwap
|
NewMsgCreateAtomicSwap = types.NewMsgCreateAtomicSwap
|
||||||
|
NewMsgClaimAtomicSwap = types.NewMsgClaimAtomicSwap
|
||||||
NewMsgRefundAtomicSwap = types.NewMsgRefundAtomicSwap
|
NewMsgRefundAtomicSwap = types.NewMsgRefundAtomicSwap
|
||||||
NewParams = types.NewParams
|
NewParams = types.NewParams
|
||||||
|
DefaultParams = types.DefaultParams
|
||||||
|
NewAssetParam = types.NewAssetParam
|
||||||
|
ParamKeyTable = types.ParamKeyTable
|
||||||
NewQueryAssetSupply = types.NewQueryAssetSupply
|
NewQueryAssetSupply = types.NewQueryAssetSupply
|
||||||
|
NewQueryAssetSupplies = types.NewQueryAssetSupplies
|
||||||
NewQueryAtomicSwapByID = types.NewQueryAtomicSwapByID
|
NewQueryAtomicSwapByID = types.NewQueryAtomicSwapByID
|
||||||
NewQueryAtomicSwaps = types.NewQueryAtomicSwaps
|
NewQueryAtomicSwaps = types.NewQueryAtomicSwaps
|
||||||
NewSwapDirectionFromString = types.NewSwapDirectionFromString
|
NewAtomicSwap = types.NewAtomicSwap
|
||||||
NewSwapStatusFromString = types.NewSwapStatusFromString
|
NewSwapStatusFromString = types.NewSwapStatusFromString
|
||||||
ParamKeyTable = types.ParamKeyTable
|
NewSwapDirectionFromString = types.NewSwapDirectionFromString
|
||||||
RegisterCodec = types.RegisterCodec
|
NewAugmentedAtomicSwap = types.NewAugmentedAtomicSwap
|
||||||
|
|
||||||
// variable aliases
|
// variable aliases
|
||||||
AssetSupplyKeyPrefix = types.AssetSupplyKeyPrefix
|
ModuleCdc = types.ModuleCdc
|
||||||
AtomicSwapByBlockPrefix = types.AtomicSwapByBlockPrefix
|
ErrInvalidTimestamp = types.ErrInvalidTimestamp
|
||||||
AtomicSwapCoinsAccAddr = types.AtomicSwapCoinsAccAddr
|
ErrInvalidHeightSpan = types.ErrInvalidHeightSpan
|
||||||
|
ErrInsufficientAmount = types.ErrInsufficientAmount
|
||||||
|
ErrAssetNotSupported = types.ErrAssetNotSupported
|
||||||
|
ErrAssetNotActive = types.ErrAssetNotActive
|
||||||
|
ErrAssetSupplyNotFound = types.ErrAssetSupplyNotFound
|
||||||
|
ErrExceedsSupplyLimit = types.ErrExceedsSupplyLimit
|
||||||
|
ErrExceedsAvailableSupply = types.ErrExceedsAvailableSupply
|
||||||
|
ErrInvalidCurrentSupply = types.ErrInvalidCurrentSupply
|
||||||
|
ErrInvalidIncomingSupply = types.ErrInvalidIncomingSupply
|
||||||
|
ErrInvalidOutgoingSupply = types.ErrInvalidOutgoingSupply
|
||||||
|
ErrInvalidClaimSecret = types.ErrInvalidClaimSecret
|
||||||
|
ErrAtomicSwapAlreadyExists = types.ErrAtomicSwapAlreadyExists
|
||||||
|
ErrAtomicSwapNotFound = types.ErrAtomicSwapNotFound
|
||||||
|
ErrSwapNotRefundable = types.ErrSwapNotRefundable
|
||||||
|
ErrSwapNotClaimable = types.ErrSwapNotClaimable
|
||||||
|
ErrInvalidAmount = types.ErrInvalidAmount
|
||||||
|
ErrInvalidSwapAccount = types.ErrInvalidSwapAccount
|
||||||
AtomicSwapKeyPrefix = types.AtomicSwapKeyPrefix
|
AtomicSwapKeyPrefix = types.AtomicSwapKeyPrefix
|
||||||
|
AtomicSwapByBlockPrefix = types.AtomicSwapByBlockPrefix
|
||||||
AtomicSwapLongtermStoragePrefix = types.AtomicSwapLongtermStoragePrefix
|
AtomicSwapLongtermStoragePrefix = types.AtomicSwapLongtermStoragePrefix
|
||||||
|
AtomicSwapCoinsAccAddr = types.AtomicSwapCoinsAccAddr
|
||||||
|
KeyAssetParams = types.KeyAssetParams
|
||||||
DefaultBnbDeputyFixedFee = types.DefaultBnbDeputyFixedFee
|
DefaultBnbDeputyFixedFee = types.DefaultBnbDeputyFixedFee
|
||||||
DefaultMinAmount = types.DefaultMinAmount
|
DefaultMinAmount = types.DefaultMinAmount
|
||||||
DefaultMaxAmount = types.DefaultMaxAmount
|
DefaultMaxAmount = types.DefaultMaxAmount
|
||||||
DefaultMaxBlockLock = types.DefaultMaxBlockLock
|
|
||||||
DefaultMinBlockLock = types.DefaultMinBlockLock
|
DefaultMinBlockLock = types.DefaultMinBlockLock
|
||||||
DefaultSupportedAssets = types.DefaultSupportedAssets
|
DefaultMaxBlockLock = types.DefaultMaxBlockLock
|
||||||
KeyBnbDeputyAddress = types.KeyBnbDeputyAddress
|
|
||||||
KeyBnbDeputyFixedFee = types.KeyBnbDeputyFixedFee
|
|
||||||
KeyMinAmount = types.KeyMinAmount
|
|
||||||
KeyMaxAmount = types.KeyMaxAmount
|
|
||||||
KeyMaxBlockLock = types.KeyMaxBlockLock
|
|
||||||
KeyMinBlockLock = types.KeyMinBlockLock
|
|
||||||
KeySupportedAssets = types.KeySupportedAssets
|
|
||||||
ModuleCdc = types.ModuleCdc
|
|
||||||
SupplyLimitUpgradeTime = types.SupplyLimitUpgradeTime
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Keeper = keeper.Keeper
|
Keeper = keeper.Keeper
|
||||||
AssetParam = types.AssetParam
|
AssetSupply = types.AssetSupply
|
||||||
AssetParams = types.AssetParams
|
AssetSupplies = types.AssetSupplies
|
||||||
AssetSupplies = types.AssetSupplies
|
GenesisState = types.GenesisState
|
||||||
AssetSupply = types.AssetSupply
|
MsgCreateAtomicSwap = types.MsgCreateAtomicSwap
|
||||||
AtomicSwap = types.AtomicSwap
|
MsgClaimAtomicSwap = types.MsgClaimAtomicSwap
|
||||||
AtomicSwaps = types.AtomicSwaps
|
MsgRefundAtomicSwap = types.MsgRefundAtomicSwap
|
||||||
GenesisState = types.GenesisState
|
Params = types.Params
|
||||||
MsgClaimAtomicSwap = types.MsgClaimAtomicSwap
|
AssetParam = types.AssetParam
|
||||||
MsgCreateAtomicSwap = types.MsgCreateAtomicSwap
|
AssetParams = types.AssetParams
|
||||||
MsgRefundAtomicSwap = types.MsgRefundAtomicSwap
|
QueryAssetSupply = types.QueryAssetSupply
|
||||||
Params = types.Params
|
QueryAssetSupplies = types.QueryAssetSupplies
|
||||||
QueryAssetSupply = types.QueryAssetSupply
|
QueryAtomicSwapByID = types.QueryAtomicSwapByID
|
||||||
QueryAtomicSwapByID = types.QueryAtomicSwapByID
|
QueryAtomicSwaps = types.QueryAtomicSwaps
|
||||||
QueryAtomicSwaps = types.QueryAtomicSwaps
|
AtomicSwap = types.AtomicSwap
|
||||||
SwapDirection = types.SwapDirection
|
AtomicSwaps = types.AtomicSwaps
|
||||||
SwapStatus = types.SwapStatus
|
SwapStatus = types.SwapStatus
|
||||||
|
SwapDirection = types.SwapDirection
|
||||||
|
AugmentedAtomicSwap = types.AugmentedAtomicSwap
|
||||||
|
AugmentedAtomicSwaps = types.AugmentedAtomicSwaps
|
||||||
)
|
)
|
||||||
|
@ -133,7 +133,7 @@ func QueryGetAssetSupplyCmd(queryRoute string, cdc *codec.Codec) *cobra.Command
|
|||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
|
|
||||||
// Prepare query params
|
// Prepare query params
|
||||||
bz, err := cdc.MarshalJSON(types.NewQueryAssetSupply([]byte(args[0])))
|
bz, err := cdc.MarshalJSON(types.NewQueryAssetSupply(args[0]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ func queryAssetSupplyHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
|
|
||||||
// Prepare params for querier
|
// Prepare params for querier
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
denom := []byte(vars[restDenom])
|
denom := vars[restDenom]
|
||||||
params := types.NewQueryAssetSupply(denom)
|
params := types.NewQueryAssetSupply(denom)
|
||||||
|
|
||||||
bz, err := cliCtx.Codec.MarshalJSON(params)
|
bz, err := cliCtx.Codec.MarshalJSON(params)
|
||||||
|
@ -21,39 +21,8 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, supplyKeeper types.SupplyKeeper
|
|||||||
}
|
}
|
||||||
|
|
||||||
keeper.SetParams(ctx, gs.Params)
|
keeper.SetParams(ctx, gs.Params)
|
||||||
|
for _, supply := range gs.Supplies {
|
||||||
// Initialize supported assets
|
keeper.SetAssetSupply(ctx, supply, supply.GetDenom())
|
||||||
for _, asset := range gs.Params.SupportedAssets {
|
|
||||||
zeroCoin := sdk.NewCoin(asset.Denom, sdk.NewInt(0))
|
|
||||||
supply := NewAssetSupply(asset.Denom, zeroCoin, zeroCoin, zeroCoin, sdk.NewCoin(asset.Denom, asset.Limit))
|
|
||||||
keeper.SetAssetSupply(ctx, supply, []byte(asset.Denom))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment an asset's incoming, current, and outgoing supply
|
|
||||||
// It it required that assets are supported but they do not have to be active
|
|
||||||
for _, supply := range gs.AssetSupplies {
|
|
||||||
// Asset must be supported but does not have to be active
|
|
||||||
coin, found := keeper.GetAssetByDenom(ctx, supply.Denom)
|
|
||||||
if !found {
|
|
||||||
panic(fmt.Sprintf("invalid asset supply: %s is not a supported asset", coin.Denom))
|
|
||||||
}
|
|
||||||
if !coin.Limit.Equal(supply.SupplyLimit.Amount) {
|
|
||||||
panic(fmt.Sprintf("supported asset limit %s does not equal asset supply %s", coin.Limit, supply.SupplyLimit.Amount))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment current, incoming, and outgoing asset supplies
|
|
||||||
err := keeper.IncrementCurrentAssetSupply(ctx, supply.CurrentSupply)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = keeper.IncrementIncomingAssetSupply(ctx, supply.IncomingSupply)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = keeper.IncrementOutgoingAssetSupply(ctx, supply.OutgoingSupply)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var incomingSupplies sdk.Coins
|
var incomingSupplies sdk.Coins
|
||||||
@ -108,16 +77,33 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, supplyKeeper types.SupplyKeeper
|
|||||||
// Asset's given incoming/outgoing supply much match the amount of coins in incoming/outgoing atomic swaps
|
// Asset's given incoming/outgoing supply much match the amount of coins in incoming/outgoing atomic swaps
|
||||||
supplies := keeper.GetAllAssetSupplies(ctx)
|
supplies := keeper.GetAllAssetSupplies(ctx)
|
||||||
for _, supply := range supplies {
|
for _, supply := range supplies {
|
||||||
incomingSupply := incomingSupplies.AmountOf(supply.Denom)
|
incomingSupply := incomingSupplies.AmountOf(supply.GetDenom())
|
||||||
if !supply.IncomingSupply.Amount.Equal(incomingSupply) {
|
if !supply.IncomingSupply.Amount.Equal(incomingSupply) {
|
||||||
panic(fmt.Sprintf("asset's incoming supply %s does not match amount %s in incoming atomic swaps",
|
panic(fmt.Sprintf("asset's incoming supply %s does not match amount %s in incoming atomic swaps",
|
||||||
supply.IncomingSupply, incomingSupply))
|
supply.IncomingSupply, incomingSupply))
|
||||||
}
|
}
|
||||||
outgoingSupply := outgoingSupplies.AmountOf(supply.Denom)
|
outgoingSupply := outgoingSupplies.AmountOf(supply.GetDenom())
|
||||||
if !supply.OutgoingSupply.Amount.Equal(outgoingSupply) {
|
if !supply.OutgoingSupply.Amount.Equal(outgoingSupply) {
|
||||||
panic(fmt.Sprintf("asset's outgoing supply %s does not match amount %s in outgoing atomic swaps",
|
panic(fmt.Sprintf("asset's outgoing supply %s does not match amount %s in outgoing atomic swaps",
|
||||||
supply.OutgoingSupply, outgoingSupply))
|
supply.OutgoingSupply, outgoingSupply))
|
||||||
}
|
}
|
||||||
|
limit, err := keeper.GetSupplyLimit(ctx, supply.GetDenom())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if supply.CurrentSupply.Amount.GT(limit) {
|
||||||
|
panic(fmt.Sprintf("asset's current supply %s is over the supply limit %s", supply.CurrentSupply, limit))
|
||||||
|
}
|
||||||
|
if supply.IncomingSupply.Amount.GT(limit) {
|
||||||
|
panic(fmt.Sprintf("asset's incoming supply %s is over the supply limit %s", supply.IncomingSupply, limit))
|
||||||
|
}
|
||||||
|
if supply.IncomingSupply.Amount.Add(supply.CurrentSupply.Amount).GT(limit) {
|
||||||
|
panic(fmt.Sprintf("asset's incoming supply + current supply %s is over the supply limit %s", supply.IncomingSupply.Add(supply.CurrentSupply), limit))
|
||||||
|
}
|
||||||
|
if supply.OutgoingSupply.Amount.GT(limit) {
|
||||||
|
panic(fmt.Sprintf("asset's outgoing supply %s is over the supply limit %s", supply.OutgoingSupply, limit))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +111,6 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, supplyKeeper types.SupplyKeeper
|
|||||||
func ExportGenesis(ctx sdk.Context, k Keeper) (data GenesisState) {
|
func ExportGenesis(ctx sdk.Context, k Keeper) (data GenesisState) {
|
||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
swaps := k.GetAllAtomicSwaps(ctx)
|
swaps := k.GetAllAtomicSwaps(ctx)
|
||||||
assets := k.GetAllAssetSupplies(ctx)
|
supplies := k.GetAllAssetSupplies(ctx)
|
||||||
return NewGenesisState(params, swaps, assets)
|
return NewGenesisState(params, swaps, supplies)
|
||||||
}
|
}
|
||||||
|
@ -53,16 +53,16 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
name: "import atomic swaps and asset supplies",
|
name: "import atomic swaps and asset supplies",
|
||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(3)
|
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
||||||
var swaps bep3.AtomicSwaps
|
var swaps bep3.AtomicSwaps
|
||||||
var supplies bep3.AssetSupplies
|
var supplies bep3.AssetSupplies
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
swap, supply := loadSwapAndSupply(addrs[i], i)
|
swap, supply := loadSwapAndSupply(addrs[i], i)
|
||||||
swaps = append(swaps, swap)
|
swaps = append(swaps, swap)
|
||||||
supplies = append(supplies, supply)
|
supplies = append(supplies, supply)
|
||||||
}
|
}
|
||||||
gs.AtomicSwaps = swaps
|
gs.AtomicSwaps = swaps
|
||||||
gs.AssetSupplies = supplies
|
gs.Supplies = supplies
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
},
|
},
|
||||||
expectPass: true,
|
expectPass: true,
|
||||||
@ -71,7 +71,7 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
name: "0 deputy fees",
|
name: "0 deputy fees",
|
||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
gs.Params.BnbDeputyFixedFee = sdk.ZeroInt()
|
gs.Params.AssetParams[0].FixedFee = sdk.ZeroInt()
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
},
|
},
|
||||||
expectPass: true,
|
expectPass: true,
|
||||||
@ -91,14 +91,12 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
name: "current supply above limit",
|
name: "current supply above limit",
|
||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
assetParam, _ := suite.keeper.GetAssetByDenom(suite.ctx, "bnb")
|
assetParam, _ := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
gs.AssetSupplies = bep3.AssetSupplies{
|
gs.Supplies = bep3.AssetSupplies{
|
||||||
bep3.AssetSupply{
|
bep3.AssetSupply{
|
||||||
Denom: "bnb",
|
|
||||||
IncomingSupply: c("bnb", 0),
|
IncomingSupply: c("bnb", 0),
|
||||||
OutgoingSupply: c("bnb", 0),
|
OutgoingSupply: c("bnb", 0),
|
||||||
CurrentSupply: c("bnb", assetParam.Limit.Add(i(1)).Int64()),
|
CurrentSupply: c("bnb", assetParam.SupplyLimit.Add(i(1)).Int64()),
|
||||||
SupplyLimit: c("bnb", assetParam.Limit.Int64()),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
@ -110,8 +108,8 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
// Set up overlimit amount
|
// Set up overlimit amount
|
||||||
assetParam, _ := suite.keeper.GetAssetByDenom(suite.ctx, "bnb")
|
assetParam, _ := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
overLimitAmount := assetParam.Limit.Add(i(1))
|
overLimitAmount := assetParam.SupplyLimit.Add(i(1))
|
||||||
|
|
||||||
// Set up an atomic swap with amount equal to the currently asset supply
|
// Set up an atomic swap with amount equal to the currently asset supply
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
||||||
@ -124,13 +122,11 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
gs.AtomicSwaps = bep3.AtomicSwaps{swap}
|
gs.AtomicSwaps = bep3.AtomicSwaps{swap}
|
||||||
|
|
||||||
// Set up asset supply with overlimit current supply
|
// Set up asset supply with overlimit current supply
|
||||||
gs.AssetSupplies = bep3.AssetSupplies{
|
gs.Supplies = bep3.AssetSupplies{
|
||||||
bep3.AssetSupply{
|
bep3.AssetSupply{
|
||||||
Denom: "bnb",
|
IncomingSupply: c("bnb", assetParam.SupplyLimit.Add(i(1)).Int64()),
|
||||||
IncomingSupply: c("bnb", assetParam.Limit.Add(i(1)).Int64()),
|
|
||||||
OutgoingSupply: c("bnb", 0),
|
OutgoingSupply: c("bnb", 0),
|
||||||
CurrentSupply: c("bnb", 0),
|
CurrentSupply: c("bnb", 0),
|
||||||
SupplyLimit: c("bnb", assetParam.Limit.Int64()),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
@ -142,8 +138,8 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
// Set up overlimit amount
|
// Set up overlimit amount
|
||||||
assetParam, _ := suite.keeper.GetAssetByDenom(suite.ctx, "bnb")
|
assetParam, _ := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
halfLimit := assetParam.Limit.Int64() / 2
|
halfLimit := assetParam.SupplyLimit.Int64() / 2
|
||||||
overHalfLimit := halfLimit + 1
|
overHalfLimit := halfLimit + 1
|
||||||
|
|
||||||
// Set up an atomic swap with amount equal to the currently asset supply
|
// Set up an atomic swap with amount equal to the currently asset supply
|
||||||
@ -157,13 +153,41 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
gs.AtomicSwaps = bep3.AtomicSwaps{swap}
|
gs.AtomicSwaps = bep3.AtomicSwaps{swap}
|
||||||
|
|
||||||
// Set up asset supply with overlimit current supply
|
// Set up asset supply with overlimit current supply
|
||||||
gs.AssetSupplies = bep3.AssetSupplies{
|
gs.Supplies = bep3.AssetSupplies{
|
||||||
bep3.AssetSupply{
|
bep3.AssetSupply{
|
||||||
Denom: "bnb",
|
|
||||||
IncomingSupply: c("bnb", halfLimit),
|
IncomingSupply: c("bnb", halfLimit),
|
||||||
OutgoingSupply: c("bnb", 0),
|
OutgoingSupply: c("bnb", 0),
|
||||||
CurrentSupply: c("bnb", overHalfLimit),
|
CurrentSupply: c("bnb", overHalfLimit),
|
||||||
SupplyLimit: c("bnb", assetParam.Limit.Int64()),
|
},
|
||||||
|
}
|
||||||
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
|
},
|
||||||
|
expectPass: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "outgoing supply above limit",
|
||||||
|
genState: func() app.GenesisState {
|
||||||
|
gs := baseGenState(suite.addrs[0])
|
||||||
|
// Set up overlimit amount
|
||||||
|
assetParam, _ := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
|
overLimitAmount := assetParam.SupplyLimit.Add(i(1))
|
||||||
|
|
||||||
|
// Set up an atomic swap with amount equal to the currently asset supply
|
||||||
|
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
||||||
|
timestamp := ts(0)
|
||||||
|
randomNumber, _ := bep3.GenerateSecureRandomNumber()
|
||||||
|
randomNumberHash := bep3.CalculateRandomHash(randomNumber[:], timestamp)
|
||||||
|
swap := bep3.NewAtomicSwap(cs(c("bnb", overLimitAmount.Int64())), randomNumberHash,
|
||||||
|
bep3.DefaultMinBlockLock, timestamp, addrs[1], suite.addrs[0], TestSenderOtherChain,
|
||||||
|
TestRecipientOtherChain, 0, bep3.Open, true, bep3.Outgoing)
|
||||||
|
gs.AtomicSwaps = bep3.AtomicSwaps{swap}
|
||||||
|
|
||||||
|
// Set up asset supply with overlimit current supply
|
||||||
|
gs.Supplies = bep3.AssetSupplies{
|
||||||
|
bep3.AssetSupply{
|
||||||
|
IncomingSupply: c("bnb", 0),
|
||||||
|
OutgoingSupply: c("bnb", 0),
|
||||||
|
CurrentSupply: c("bnb", assetParam.SupplyLimit.Add(i(1)).Int64()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
@ -174,13 +198,11 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
name: "asset supply denom is not a supported asset",
|
name: "asset supply denom is not a supported asset",
|
||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
gs.AssetSupplies = bep3.AssetSupplies{
|
gs.Supplies = bep3.AssetSupplies{
|
||||||
bep3.AssetSupply{
|
bep3.AssetSupply{
|
||||||
Denom: "fake",
|
|
||||||
IncomingSupply: c("fake", 0),
|
IncomingSupply: c("fake", 0),
|
||||||
OutgoingSupply: c("fake", 0),
|
OutgoingSupply: c("fake", 0),
|
||||||
CurrentSupply: c("fake", 0),
|
CurrentSupply: c("fake", 0),
|
||||||
SupplyLimit: c("fake", StandardSupplyLimit.Int64()),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
@ -225,8 +247,8 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
name: "minimum block lock cannot be > maximum block lock",
|
name: "minimum block lock cannot be > maximum block lock",
|
||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
gs.Params.MinBlockLock = 201
|
gs.Params.AssetParams[0].MinBlockLock = 201
|
||||||
gs.Params.MaxBlockLock = 200
|
gs.Params.AssetParams[0].MaxBlockLock = 200
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
},
|
},
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
@ -235,7 +257,7 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
name: "empty supported asset denom",
|
name: "empty supported asset denom",
|
||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
gs.Params.SupportedAssets[0].Denom = ""
|
gs.Params.AssetParams[0].Denom = ""
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
},
|
},
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
@ -244,7 +266,7 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
name: "negative supported asset limit",
|
name: "negative supported asset limit",
|
||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
gs.Params.SupportedAssets[0].Limit = i(-100)
|
gs.Params.AssetParams[0].SupplyLimit = i(-100)
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
},
|
},
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
@ -253,7 +275,7 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
name: "duplicate supported asset denom",
|
name: "duplicate supported asset denom",
|
||||||
genState: func() app.GenesisState {
|
genState: func() app.GenesisState {
|
||||||
gs := baseGenState(suite.addrs[0])
|
gs := baseGenState(suite.addrs[0])
|
||||||
gs.Params.SupportedAssets[1].Denom = "bnb"
|
gs.Params.AssetParams[1].Denom = "bnb"
|
||||||
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
return app.GenesisState{"bep3": bep3.ModuleCdc.MustMarshalJSON(gs)}
|
||||||
},
|
},
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
@ -261,15 +283,18 @@ func (suite *GenesisTestSuite) TestGenesisState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
if tc.expectPass {
|
suite.Run(tc.name, func() {
|
||||||
suite.NotPanics(func() {
|
if tc.expectPass {
|
||||||
suite.app.InitializeFromGenesisStates(tc.genState())
|
suite.NotPanics(func() {
|
||||||
}, tc.name)
|
suite.app.InitializeFromGenesisStates(tc.genState())
|
||||||
} else {
|
}, tc.name)
|
||||||
suite.Panics(func() {
|
} else {
|
||||||
suite.app.InitializeFromGenesisStates(tc.genState())
|
suite.Panics(func() {
|
||||||
}, tc.name)
|
suite.app.InitializeFromGenesisStates(tc.genState())
|
||||||
}
|
}, tc.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
StandardSupplyLimit = i(100000000000)
|
StandardSupplyLimit = i(100000000000)
|
||||||
DenomMap = map[int]string{0: "btc", 1: "eth", 2: "bnb", 3: "xrp", 4: "dai"}
|
DenomMap = map[int]string{0: "bnb", 1: "inc"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func i(in int64) sdk.Int { return sdk.NewInt(in) }
|
func i(in int64) sdk.Int { return sdk.NewInt(in) }
|
||||||
@ -35,41 +35,48 @@ func NewBep3GenStateMulti(deputy sdk.AccAddress) app.GenesisState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func baseGenState(deputy sdk.AccAddress) bep3.GenesisState {
|
func baseGenState(deputy sdk.AccAddress) bep3.GenesisState {
|
||||||
|
|
||||||
bep3Genesis := bep3.GenesisState{
|
bep3Genesis := bep3.GenesisState{
|
||||||
Params: bep3.Params{
|
Params: bep3.Params{
|
||||||
BnbDeputyAddress: deputy,
|
AssetParams: bep3.AssetParams{
|
||||||
BnbDeputyFixedFee: bep3.DefaultBnbDeputyFixedFee, // 1,000
|
|
||||||
MinAmount: bep3.DefaultMinAmount, // 0
|
|
||||||
MaxAmount: bep3.DefaultMaxAmount, // 10,000
|
|
||||||
MinBlockLock: bep3.DefaultMinBlockLock, // 220
|
|
||||||
MaxBlockLock: bep3.DefaultMaxBlockLock, // 270
|
|
||||||
SupportedAssets: bep3.AssetParams{
|
|
||||||
bep3.AssetParam{
|
bep3.AssetParam{
|
||||||
Denom: "btc",
|
Denom: "bnb",
|
||||||
CoinID: 714,
|
CoinID: 714,
|
||||||
Limit: StandardSupplyLimit,
|
SupplyLimit: sdk.NewInt(350000000000000),
|
||||||
Active: true,
|
Active: true,
|
||||||
|
DeputyAddress: deputy,
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: bep3.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: bep3.DefaultMaxBlockLock,
|
||||||
},
|
},
|
||||||
bep3.AssetParam{
|
bep3.AssetParam{
|
||||||
Denom: "eth",
|
Denom: "inc",
|
||||||
CoinID: 999999,
|
CoinID: 9999,
|
||||||
Limit: StandardSupplyLimit,
|
SupplyLimit: sdk.NewInt(100000000000),
|
||||||
Active: true,
|
Active: true,
|
||||||
},
|
DeputyAddress: deputy,
|
||||||
bep3.AssetParam{
|
FixedFee: sdk.NewInt(1000),
|
||||||
Denom: "bnb",
|
MinSwapAmount: sdk.OneInt(),
|
||||||
CoinID: 99999,
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
Limit: StandardSupplyLimit,
|
MinBlockLock: bep3.DefaultMinBlockLock,
|
||||||
Active: true,
|
MaxBlockLock: bep3.DefaultMaxBlockLock,
|
||||||
},
|
|
||||||
bep3.AssetParam{
|
|
||||||
Denom: "inc",
|
|
||||||
CoinID: 9999,
|
|
||||||
Limit: i(100),
|
|
||||||
Active: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Supplies: bep3.AssetSupplies{
|
||||||
|
bep3.NewAssetSupply(
|
||||||
|
sdk.NewCoin("bnb", sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin("bnb", sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin("bnb", sdk.ZeroInt()),
|
||||||
|
),
|
||||||
|
bep3.NewAssetSupply(
|
||||||
|
sdk.NewCoin("inc", sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin("inc", sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin("inc", sdk.ZeroInt()),
|
||||||
|
),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return bep3Genesis
|
return bep3Genesis
|
||||||
}
|
}
|
||||||
@ -84,8 +91,8 @@ func loadSwapAndSupply(addr sdk.AccAddress, index int) (bep3.AtomicSwap, bep3.As
|
|||||||
expireOffset, timestamp, addr, addr, TestSenderOtherChain,
|
expireOffset, timestamp, addr, addr, TestSenderOtherChain,
|
||||||
TestRecipientOtherChain, 1, bep3.Open, true, bep3.Incoming)
|
TestRecipientOtherChain, 1, bep3.Open, true, bep3.Incoming)
|
||||||
|
|
||||||
supply := bep3.NewAssetSupply(coin.Denom, coin, c(coin.Denom, 0),
|
supply := bep3.NewAssetSupply(coin, c(coin.Denom, 0),
|
||||||
c(coin.Denom, 0), c(coin.Denom, StandardSupplyLimit.Int64()))
|
c(coin.Denom, 0))
|
||||||
|
|
||||||
return swap, supply
|
return swap, supply
|
||||||
}
|
}
|
||||||
|
@ -9,24 +9,30 @@ import (
|
|||||||
|
|
||||||
// IncrementCurrentAssetSupply increments an asset's supply by the coin
|
// IncrementCurrentAssetSupply increments an asset's supply by the coin
|
||||||
func (k Keeper) IncrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
func (k Keeper) IncrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
||||||
supply, found := k.GetAssetSupply(ctx, []byte(coin.Denom))
|
supply, found := k.GetAssetSupply(ctx, coin.Denom)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
limit, err := k.GetSupplyLimit(ctx, coin.Denom)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
supplyLimit := sdk.NewCoin(coin.Denom, limit)
|
||||||
|
|
||||||
// Resulting current supply must be under asset's limit
|
// Resulting current supply must be under asset's limit
|
||||||
if supply.SupplyLimit.IsLT(supply.CurrentSupply.Add(coin)) {
|
if supplyLimit.IsLT(supply.CurrentSupply.Add(coin)) {
|
||||||
return sdkerrors.Wrapf(types.ErrExceedsSupplyLimit, "increase %s, asset supply %s, limit %s", coin, supply.CurrentSupply, supply.SupplyLimit)
|
return sdkerrors.Wrapf(types.ErrExceedsSupplyLimit, "increase %s, asset supply %s, limit %s", coin, supply.CurrentSupply, supplyLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
supply.CurrentSupply = supply.CurrentSupply.Add(coin)
|
supply.CurrentSupply = supply.CurrentSupply.Add(coin)
|
||||||
k.SetAssetSupply(ctx, supply, []byte(coin.Denom))
|
k.SetAssetSupply(ctx, supply, coin.Denom)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecrementCurrentAssetSupply decrement an asset's supply by the coin
|
// DecrementCurrentAssetSupply decrement an asset's supply by the coin
|
||||||
func (k Keeper) DecrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
func (k Keeper) DecrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
||||||
supply, found := k.GetAssetSupply(ctx, []byte(coin.Denom))
|
supply, found := k.GetAssetSupply(ctx, coin.Denom)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
||||||
}
|
}
|
||||||
@ -38,31 +44,37 @@ func (k Keeper) DecrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
supply.CurrentSupply = supply.CurrentSupply.Sub(coin)
|
supply.CurrentSupply = supply.CurrentSupply.Sub(coin)
|
||||||
k.SetAssetSupply(ctx, supply, []byte(coin.Denom))
|
k.SetAssetSupply(ctx, supply, coin.Denom)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrementIncomingAssetSupply increments an asset's incoming supply
|
// IncrementIncomingAssetSupply increments an asset's incoming supply
|
||||||
func (k Keeper) IncrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
func (k Keeper) IncrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
||||||
supply, found := k.GetAssetSupply(ctx, []byte(coin.Denom))
|
supply, found := k.GetAssetSupply(ctx, coin.Denom)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result of (current + incoming + amount) must be under asset's limit
|
// Result of (current + incoming + amount) must be under asset's limit
|
||||||
totalSupply := supply.CurrentSupply.Add(supply.IncomingSupply)
|
totalSupply := supply.CurrentSupply.Add(supply.IncomingSupply)
|
||||||
if supply.SupplyLimit.IsLT(totalSupply.Add(coin)) {
|
|
||||||
return sdkerrors.Wrapf(types.ErrExceedsSupplyLimit, "increase %s, asset supply %s, limit %s", coin, totalSupply, supply.SupplyLimit)
|
limit, err := k.GetSupplyLimit(ctx, coin.Denom)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
supplyLimit := sdk.NewCoin(coin.Denom, limit)
|
||||||
|
if supplyLimit.IsLT(totalSupply.Add(coin)) {
|
||||||
|
return sdkerrors.Wrapf(types.ErrExceedsSupplyLimit, "increase %s, asset supply %s, limit %s", coin, totalSupply, supplyLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
supply.IncomingSupply = supply.IncomingSupply.Add(coin)
|
supply.IncomingSupply = supply.IncomingSupply.Add(coin)
|
||||||
k.SetAssetSupply(ctx, supply, []byte(coin.Denom))
|
k.SetAssetSupply(ctx, supply, coin.Denom)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecrementIncomingAssetSupply decrements an asset's incoming supply
|
// DecrementIncomingAssetSupply decrements an asset's incoming supply
|
||||||
func (k Keeper) DecrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
func (k Keeper) DecrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
||||||
supply, found := k.GetAssetSupply(ctx, []byte(coin.Denom))
|
supply, found := k.GetAssetSupply(ctx, coin.Denom)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
||||||
}
|
}
|
||||||
@ -74,13 +86,13 @@ func (k Keeper) DecrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
supply.IncomingSupply = supply.IncomingSupply.Sub(coin)
|
supply.IncomingSupply = supply.IncomingSupply.Sub(coin)
|
||||||
k.SetAssetSupply(ctx, supply, []byte(coin.Denom))
|
k.SetAssetSupply(ctx, supply, coin.Denom)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrementOutgoingAssetSupply increments an asset's outoing supply
|
// IncrementOutgoingAssetSupply increments an asset's outgoing supply
|
||||||
func (k Keeper) IncrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
func (k Keeper) IncrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
||||||
supply, found := k.GetAssetSupply(ctx, []byte(coin.Denom))
|
supply, found := k.GetAssetSupply(ctx, coin.Denom)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
||||||
}
|
}
|
||||||
@ -92,13 +104,13 @@ func (k Keeper) IncrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
supply.OutgoingSupply = supply.OutgoingSupply.Add(coin)
|
supply.OutgoingSupply = supply.OutgoingSupply.Add(coin)
|
||||||
k.SetAssetSupply(ctx, supply, []byte(coin.Denom))
|
k.SetAssetSupply(ctx, supply, coin.Denom)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecrementOutgoingAssetSupply decrements an asset's outoing supply
|
// DecrementOutgoingAssetSupply decrements an asset's outgoing supply
|
||||||
func (k Keeper) DecrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
func (k Keeper) DecrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) error {
|
||||||
supply, found := k.GetAssetSupply(ctx, []byte(coin.Denom))
|
supply, found := k.GetAssetSupply(ctx, coin.Denom)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
||||||
}
|
}
|
||||||
@ -110,21 +122,6 @@ func (k Keeper) DecrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
supply.OutgoingSupply = supply.OutgoingSupply.Sub(coin)
|
supply.OutgoingSupply = supply.OutgoingSupply.Sub(coin)
|
||||||
k.SetAssetSupply(ctx, supply, []byte(coin.Denom))
|
k.SetAssetSupply(ctx, supply, coin.Denom)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateAssetSupplies applies updates to the asset limit from parameters to the asset supplies
|
|
||||||
func (k Keeper) UpdateAssetSupplies(ctx sdk.Context) {
|
|
||||||
params := k.GetParams(ctx)
|
|
||||||
for _, supportedAsset := range params.SupportedAssets {
|
|
||||||
asset, found := k.GetAssetSupply(ctx, []byte(supportedAsset.Denom))
|
|
||||||
if !found {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !asset.SupplyLimit.Amount.Equal(supportedAsset.Limit) {
|
|
||||||
asset.SupplyLimit = sdk.NewCoin(supportedAsset.Denom, supportedAsset.Limit)
|
|
||||||
k.SetAssetSupply(ctx, asset, []byte(supportedAsset.Denom))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -36,16 +36,16 @@ func (suite *AssetTestSuite) SetupTest() {
|
|||||||
tApp.InitializeFromGenesisStates(NewBep3GenStateMulti(deputy))
|
tApp.InitializeFromGenesisStates(NewBep3GenStateMulti(deputy))
|
||||||
|
|
||||||
keeper := tApp.GetBep3Keeper()
|
keeper := tApp.GetBep3Keeper()
|
||||||
|
params := keeper.GetParams(ctx)
|
||||||
|
params.AssetParams[0].SupplyLimit = sdk.NewInt(50)
|
||||||
|
keeper.SetParams(ctx, params)
|
||||||
// Set asset supply with standard value for testing
|
// Set asset supply with standard value for testing
|
||||||
supply := types.AssetSupply{
|
supply := types.AssetSupply{
|
||||||
Denom: "bnb",
|
|
||||||
IncomingSupply: c("bnb", 5),
|
IncomingSupply: c("bnb", 5),
|
||||||
OutgoingSupply: c("bnb", 5),
|
OutgoingSupply: c("bnb", 5),
|
||||||
CurrentSupply: c("bnb", 40),
|
CurrentSupply: c("bnb", 40),
|
||||||
SupplyLimit: c("bnb", 50),
|
|
||||||
}
|
}
|
||||||
keeper.SetAssetSupply(ctx, supply, []byte(supply.Denom))
|
keeper.SetAssetSupply(ctx, supply, supply.GetDenom())
|
||||||
|
|
||||||
suite.app = tApp
|
suite.app = tApp
|
||||||
suite.ctx = ctx
|
suite.ctx = ctx
|
||||||
@ -95,11 +95,10 @@ func (suite *AssetTestSuite) TestIncrementCurrentAssetSupply() {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.SetupTest()
|
suite.SetupTest()
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
supplyKeyPrefix := []byte(tc.args.coin.Denom)
|
|
||||||
|
|
||||||
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
err := suite.keeper.IncrementCurrentAssetSupply(suite.ctx, tc.args.coin)
|
err := suite.keeper.IncrementCurrentAssetSupply(suite.ctx, tc.args.coin)
|
||||||
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
|
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
@ -155,11 +154,10 @@ func (suite *AssetTestSuite) TestDecrementCurrentAssetSupply() {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.SetupTest()
|
suite.SetupTest()
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
supplyKeyPrefix := []byte(tc.args.coin.Denom)
|
|
||||||
|
|
||||||
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
err := suite.keeper.DecrementCurrentAssetSupply(suite.ctx, tc.args.coin)
|
err := suite.keeper.DecrementCurrentAssetSupply(suite.ctx, tc.args.coin)
|
||||||
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
|
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
@ -215,11 +213,9 @@ func (suite *AssetTestSuite) TestIncrementIncomingAssetSupply() {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.SetupTest()
|
suite.SetupTest()
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
supplyKeyPrefix := []byte(tc.args.coin.Denom)
|
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
|
|
||||||
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
|
||||||
err := suite.keeper.IncrementIncomingAssetSupply(suite.ctx, tc.args.coin)
|
err := suite.keeper.IncrementIncomingAssetSupply(suite.ctx, tc.args.coin)
|
||||||
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
|
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
@ -275,11 +271,10 @@ func (suite *AssetTestSuite) TestDecrementIncomingAssetSupply() {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.SetupTest()
|
suite.SetupTest()
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
supplyKeyPrefix := []byte(tc.args.coin.Denom)
|
|
||||||
|
|
||||||
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
err := suite.keeper.DecrementIncomingAssetSupply(suite.ctx, tc.args.coin)
|
err := suite.keeper.DecrementIncomingAssetSupply(suite.ctx, tc.args.coin)
|
||||||
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
|
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
@ -335,11 +330,10 @@ func (suite *AssetTestSuite) TestIncrementOutgoingAssetSupply() {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.SetupTest()
|
suite.SetupTest()
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
supplyKeyPrefix := []byte(tc.args.coin.Denom)
|
|
||||||
|
|
||||||
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
err := suite.keeper.IncrementOutgoingAssetSupply(suite.ctx, tc.args.coin)
|
err := suite.keeper.IncrementOutgoingAssetSupply(suite.ctx, tc.args.coin)
|
||||||
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
|
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
@ -395,11 +389,9 @@ func (suite *AssetTestSuite) TestDecrementOutgoingAssetSupply() {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.SetupTest()
|
suite.SetupTest()
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
supplyKeyPrefix := []byte(tc.args.coin.Denom)
|
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
|
|
||||||
preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
|
||||||
err := suite.keeper.DecrementOutgoingAssetSupply(suite.ctx, tc.args.coin)
|
err := suite.keeper.DecrementOutgoingAssetSupply(suite.ctx, tc.args.coin)
|
||||||
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, supplyKeyPrefix)
|
postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom)
|
||||||
|
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
@ -413,25 +405,6 @@ func (suite *AssetTestSuite) TestDecrementOutgoingAssetSupply() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AssetTestSuite) TestUpdateAssetSupplies() {
|
|
||||||
// set new asset limit in the params
|
|
||||||
newBnbLimit := c("bnb", 100)
|
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
|
||||||
for i := range params.SupportedAssets {
|
|
||||||
if params.SupportedAssets[i].Denom != newBnbLimit.Denom {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
params.SupportedAssets[i].Limit = newBnbLimit.Amount
|
|
||||||
}
|
|
||||||
suite.keeper.SetParams(suite.ctx, params)
|
|
||||||
|
|
||||||
suite.keeper.UpdateAssetSupplies(suite.ctx)
|
|
||||||
|
|
||||||
supply, found := suite.keeper.GetAssetSupply(suite.ctx, []byte(newBnbLimit.Denom))
|
|
||||||
suite.True(found)
|
|
||||||
suite.True(supply.SupplyLimit.IsEqual(newBnbLimit))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAssetTestSuite(t *testing.T) {
|
func TestAssetTestSuite(t *testing.T) {
|
||||||
suite.Run(t, new(AssetTestSuite))
|
suite.Run(t, new(AssetTestSuite))
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
StandardSupplyLimit = i(350000000000000)
|
DenomMap = map[int]string{0: "btc", 1: "eth", 2: "bnb", 3: "xrp", 4: "dai"}
|
||||||
DenomMap = map[int]string{0: "btc", 1: "eth", 2: "bnb", 3: "xrp", 4: "dai"}
|
TestUser1 = sdk.AccAddress(crypto.AddressHash([]byte("KavaTestUser1")))
|
||||||
TestUser1 = sdk.AccAddress(crypto.AddressHash([]byte("KavaTestUser1")))
|
TestUser2 = sdk.AccAddress(crypto.AddressHash([]byte("KavaTestUser2")))
|
||||||
TestUser2 = sdk.AccAddress(crypto.AddressHash([]byte("KavaTestUser2")))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func i(in int64) sdk.Int { return sdk.NewInt(in) }
|
func i(in int64) sdk.Int { return sdk.NewInt(in) }
|
||||||
@ -34,27 +33,45 @@ func ts(minOffset int) int64 { return tmtime.Now().Add(time.Durat
|
|||||||
func NewBep3GenStateMulti(deputyAddress sdk.AccAddress) app.GenesisState {
|
func NewBep3GenStateMulti(deputyAddress sdk.AccAddress) app.GenesisState {
|
||||||
bep3Genesis := types.GenesisState{
|
bep3Genesis := types.GenesisState{
|
||||||
Params: bep3.Params{
|
Params: bep3.Params{
|
||||||
BnbDeputyAddress: deputyAddress,
|
AssetParams: types.AssetParams{
|
||||||
BnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee, // 1000
|
|
||||||
MinAmount: types.DefaultMinAmount, // 0
|
|
||||||
MaxAmount: types.DefaultMaxAmount, // 10,000
|
|
||||||
MinBlockLock: types.DefaultMinBlockLock, // 220
|
|
||||||
MaxBlockLock: types.DefaultMaxBlockLock, // 270
|
|
||||||
SupportedAssets: types.AssetParams{
|
|
||||||
types.AssetParam{
|
types.AssetParam{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
CoinID: 714,
|
CoinID: 714,
|
||||||
Limit: StandardSupplyLimit,
|
SupplyLimit: sdk.NewInt(350000000000000),
|
||||||
Active: true,
|
Active: true,
|
||||||
|
DeputyAddress: deputyAddress,
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: types.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: types.DefaultMaxBlockLock,
|
||||||
},
|
},
|
||||||
types.AssetParam{
|
types.AssetParam{
|
||||||
Denom: "inc",
|
Denom: "inc",
|
||||||
CoinID: 9999,
|
CoinID: 9999,
|
||||||
Limit: i(100),
|
SupplyLimit: sdk.NewInt(100),
|
||||||
Active: false,
|
Active: false,
|
||||||
|
DeputyAddress: deputyAddress,
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: types.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: types.DefaultMaxBlockLock,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Supplies: bep3.AssetSupplies{
|
||||||
|
bep3.NewAssetSupply(
|
||||||
|
sdk.NewCoin("bnb", sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin("bnb", sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin("bnb", sdk.ZeroInt()),
|
||||||
|
),
|
||||||
|
bep3.NewAssetSupply(
|
||||||
|
sdk.NewCoin("inc", sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin("inc", sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin("inc", sdk.ZeroInt()),
|
||||||
|
),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return app.GenesisState{bep3.ModuleName: bep3.ModuleCdc.MustMarshalJSON(bep3Genesis)}
|
return app.GenesisState{bep3.ModuleName: bep3.ModuleCdc.MustMarshalJSON(bep3Genesis)}
|
||||||
}
|
}
|
||||||
@ -95,5 +112,5 @@ func assetSupplies(count int) types.AssetSupplies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func assetSupply(denom string) types.AssetSupply {
|
func assetSupply(denom string) types.AssetSupply {
|
||||||
return types.NewAssetSupply(denom, c(denom, 0), c(denom, 0), c(denom, 0), c(denom, 10000))
|
return types.NewAssetSupply(c(denom, 0), c(denom, 0), c(denom, 0))
|
||||||
}
|
}
|
||||||
|
@ -182,35 +182,31 @@ func (k Keeper) IterateAtomicSwapsLongtermStorage(ctx sdk.Context, inclusiveCuto
|
|||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
|
|
||||||
// GetAssetSupply gets an asset's current supply from the store.
|
// GetAssetSupply gets an asset's current supply from the store.
|
||||||
func (k Keeper) GetAssetSupply(ctx sdk.Context, denom []byte) (types.AssetSupply, bool) {
|
func (k Keeper) GetAssetSupply(ctx sdk.Context, denom string) (types.AssetSupply, bool) {
|
||||||
var supply types.AssetSupply
|
var assetSupply types.AssetSupply
|
||||||
|
store := prefix.NewStore(ctx.KVStore(k.key), types.AssetSupplyPrefix)
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.AssetSupplyKeyPrefix)
|
bz := store.Get([]byte(denom))
|
||||||
bz := store.Get(denom)
|
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
return types.AssetSupply{}, false
|
return types.AssetSupply{}, false
|
||||||
}
|
}
|
||||||
|
k.cdc.MustUnmarshalBinaryBare(bz, &assetSupply)
|
||||||
k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &supply)
|
return assetSupply, true
|
||||||
return supply, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAssetSupply updates an asset's current active supply
|
// SetAssetSupply updates an asset's supply
|
||||||
func (k Keeper) SetAssetSupply(ctx sdk.Context, supply types.AssetSupply, denom []byte) {
|
func (k Keeper) SetAssetSupply(ctx sdk.Context, supply types.AssetSupply, denom string) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.AssetSupplyKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.AssetSupplyPrefix)
|
||||||
bz := k.cdc.MustMarshalBinaryLengthPrefixed(supply)
|
store.Set([]byte(denom), k.cdc.MustMarshalBinaryBare(supply))
|
||||||
store.Set(denom, bz)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterateAssetSupplies provides an iterator over current asset supplies.
|
// IterateAssetSupplies provides an iterator over all stored AssetSupplies.
|
||||||
// For each asset supply, cb will be called. If cb returns true, the iterator will close and stop.
|
|
||||||
func (k Keeper) IterateAssetSupplies(ctx sdk.Context, cb func(supply types.AssetSupply) (stop bool)) {
|
func (k Keeper) IterateAssetSupplies(ctx sdk.Context, cb func(supply types.AssetSupply) (stop bool)) {
|
||||||
iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.AssetSupplyKeyPrefix)
|
iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.AssetSupplyPrefix)
|
||||||
|
|
||||||
defer iterator.Close()
|
defer iterator.Close()
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
var supply types.AssetSupply
|
var supply types.AssetSupply
|
||||||
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &supply)
|
k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &supply)
|
||||||
|
|
||||||
if cb(supply) {
|
if cb(supply) {
|
||||||
break
|
break
|
||||||
@ -218,7 +214,7 @@ func (k Keeper) IterateAssetSupplies(ctx sdk.Context, cb func(supply types.Asset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllAssetSupplies returns current asset supplies from the store as an array of sdk.Coin
|
// GetAllAssetSupplies returns all asset supplies from the store
|
||||||
func (k Keeper) GetAllAssetSupplies(ctx sdk.Context) (supplies types.AssetSupplies) {
|
func (k Keeper) GetAllAssetSupplies(ctx sdk.Context) (supplies types.AssetSupplies) {
|
||||||
k.IterateAssetSupplies(ctx, func(supply types.AssetSupply) bool {
|
k.IterateAssetSupplies(ctx, func(supply types.AssetSupply) bool {
|
||||||
supplies = append(supplies, supply)
|
supplies = append(supplies, supply)
|
||||||
|
@ -308,64 +308,32 @@ func (suite *KeeperTestSuite) TestIterateAtomicSwapsLongtermStorage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestGetSetAssetSupply() {
|
func (suite *KeeperTestSuite) TestGetSetAssetSupply() {
|
||||||
suite.ResetChain()
|
|
||||||
|
|
||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
// Put asset supply in store
|
// Put asset supply in store
|
||||||
assetSupply := types.NewAssetSupply(denom, c(denom, 0), c(denom, 0), c(denom, 50000), c(denom, 100000))
|
assetSupply := types.NewAssetSupply(c(denom, 0), c(denom, 0), c(denom, 50000))
|
||||||
suite.keeper.SetAssetSupply(suite.ctx, assetSupply, []byte(denom))
|
suite.keeper.SetAssetSupply(suite.ctx, assetSupply, denom)
|
||||||
|
|
||||||
// Check asset in store
|
// Check asset in store
|
||||||
storedAssetSupply, found := suite.keeper.GetAssetSupply(suite.ctx, []byte(denom))
|
storedAssetSupply, found := suite.keeper.GetAssetSupply(suite.ctx, denom)
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
suite.Equal(assetSupply, storedAssetSupply)
|
suite.Equal(assetSupply, storedAssetSupply)
|
||||||
|
|
||||||
// Check fake asset supply not in store
|
// Check fake asset supply not in store
|
||||||
fakeDenom := "xyz"
|
fakeDenom := "xyz"
|
||||||
_, found = suite.keeper.GetAssetSupply(suite.ctx, []byte(fakeDenom))
|
_, found = suite.keeper.GetAssetSupply(suite.ctx, fakeDenom)
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestIterateAssetSupplies() {
|
|
||||||
suite.ResetChain()
|
|
||||||
|
|
||||||
// Set asset supplies
|
|
||||||
supplies := assetSupplies(5)
|
|
||||||
for _, supply := range supplies {
|
|
||||||
suite.keeper.SetAssetSupply(suite.ctx, supply, []byte(supply.Denom))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read each asset supply from the store
|
|
||||||
var readSupplies types.AssetSupplies
|
|
||||||
suite.keeper.IterateAssetSupplies(suite.ctx, func(a types.AssetSupply) bool {
|
|
||||||
readSupplies = append(readSupplies, a)
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
// Check expected values
|
|
||||||
for i := 0; i < len(supplies); i++ {
|
|
||||||
suite.Contains(readSupplies, supplies[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestGetAllAssetSupplies() {
|
func (suite *KeeperTestSuite) TestGetAllAssetSupplies() {
|
||||||
suite.ResetChain()
|
|
||||||
|
|
||||||
// Set asset supplies
|
// Put asset supply in store
|
||||||
count := 3
|
assetSupply := types.NewAssetSupply(c("bnb", 0), c("bnb", 0), c("bnb", 50000))
|
||||||
supplies := assetSupplies(count)
|
suite.keeper.SetAssetSupply(suite.ctx, assetSupply, "bnb")
|
||||||
for _, supply := range supplies {
|
assetSupply = types.NewAssetSupply(c("inc", 0), c("inc", 0), c("inc", 50000))
|
||||||
suite.keeper.SetAssetSupply(suite.ctx, supply, []byte(supply.Denom))
|
suite.keeper.SetAssetSupply(suite.ctx, assetSupply, "inc")
|
||||||
}
|
|
||||||
|
|
||||||
// Get all asset supplies
|
supplies := suite.keeper.GetAllAssetSupplies(suite.ctx)
|
||||||
readSupplies := suite.keeper.GetAllAssetSupplies(suite.ctx)
|
suite.Equal(2, len(supplies))
|
||||||
suite.Equal(count, len(readSupplies))
|
|
||||||
|
|
||||||
// Check expected values
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
suite.Contains(readSupplies, supplies[i])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeeperTestSuite(t *testing.T) {
|
func TestKeeperTestSuite(t *testing.T) {
|
||||||
|
@ -18,63 +18,100 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
|
|||||||
k.paramSubspace.SetParamSet(ctx, ¶ms)
|
k.paramSubspace.SetParamSet(ctx, ¶ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBnbDeputyAddress returns the Bnbchain's deputy address
|
// ------------------------------------------
|
||||||
func (k Keeper) GetBnbDeputyAddress(ctx sdk.Context) sdk.AccAddress {
|
// Asset
|
||||||
|
// ------------------------------------------
|
||||||
|
|
||||||
|
// GetAsset returns the asset param associated with the input denom
|
||||||
|
func (k Keeper) GetAsset(ctx sdk.Context, denom string) (types.AssetParam, error) {
|
||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
return params.BnbDeputyAddress
|
for _, asset := range params.AssetParams {
|
||||||
|
if denom == asset.Denom {
|
||||||
|
return asset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types.AssetParam{}, sdkerrors.Wrap(types.ErrAssetNotSupported, denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBnbDeputyFixedFee returns the deputy's fixed fee
|
// SetAsset sets an asset in the params
|
||||||
func (k Keeper) GetBnbDeputyFixedFee(ctx sdk.Context) sdk.Int {
|
func (k Keeper) SetAsset(ctx sdk.Context, asset types.AssetParam) {
|
||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
return params.BnbDeputyFixedFee
|
for i := range params.AssetParams {
|
||||||
}
|
if params.AssetParams[i].Denom == asset.Denom {
|
||||||
|
params.AssetParams[i] = asset
|
||||||
// GetMinAmount returns the minimum amount
|
}
|
||||||
func (k Keeper) GetMinAmount(ctx sdk.Context) sdk.Int {
|
}
|
||||||
params := k.GetParams(ctx)
|
k.SetParams(ctx, params)
|
||||||
return params.MinAmount
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMaxAmount returns the maximum amount
|
|
||||||
func (k Keeper) GetMaxAmount(ctx sdk.Context) sdk.Int {
|
|
||||||
params := k.GetParams(ctx)
|
|
||||||
return params.MaxAmount
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMinBlockLock returns the minimum block lock
|
|
||||||
func (k Keeper) GetMinBlockLock(ctx sdk.Context) uint64 {
|
|
||||||
params := k.GetParams(ctx)
|
|
||||||
return params.MinBlockLock
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMaxBlockLock returns the maximum block lock
|
|
||||||
func (k Keeper) GetMaxBlockLock(ctx sdk.Context) uint64 {
|
|
||||||
params := k.GetParams(ctx)
|
|
||||||
return params.MaxBlockLock
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAssets returns a list containing all supported assets
|
// GetAssets returns a list containing all supported assets
|
||||||
func (k Keeper) GetAssets(ctx sdk.Context) (types.AssetParams, bool) {
|
func (k Keeper) GetAssets(ctx sdk.Context) (types.AssetParams, bool) {
|
||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
return params.SupportedAssets, len(params.SupportedAssets) > 0
|
return params.AssetParams, len(params.AssetParams) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAssetByDenom returns an asset by its denom
|
// ------------------------------------------
|
||||||
func (k Keeper) GetAssetByDenom(ctx sdk.Context, denom string) (types.AssetParam, bool) {
|
// Asset-specific getters
|
||||||
params := k.GetParams(ctx)
|
// ------------------------------------------
|
||||||
for _, asset := range params.SupportedAssets {
|
|
||||||
if asset.Denom == denom {
|
// GetDeputyAddress returns the deputy address for the input denom
|
||||||
return asset, true
|
func (k Keeper) GetDeputyAddress(ctx sdk.Context, denom string) (sdk.AccAddress, error) {
|
||||||
}
|
asset, err := k.GetAsset(ctx, denom)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.AccAddress{}, err
|
||||||
}
|
}
|
||||||
return types.AssetParam{}, false
|
return asset.DeputyAddress, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFixedFee returns the fixed fee for incoming swaps
|
||||||
|
func (k Keeper) GetFixedFee(ctx sdk.Context, denom string) (sdk.Int, error) {
|
||||||
|
asset, err := k.GetAsset(ctx, denom)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.Int{}, err
|
||||||
|
}
|
||||||
|
return asset.FixedFee, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMinSwapAmount returns the minimum swap amount
|
||||||
|
func (k Keeper) GetMinSwapAmount(ctx sdk.Context, denom string) (sdk.Int, error) {
|
||||||
|
asset, err := k.GetAsset(ctx, denom)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.Int{}, err
|
||||||
|
}
|
||||||
|
return asset.MinSwapAmount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMaxSwapAmount returns the maximum swap amount
|
||||||
|
func (k Keeper) GetMaxSwapAmount(ctx sdk.Context, denom string) (sdk.Int, error) {
|
||||||
|
asset, err := k.GetAsset(ctx, denom)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.Int{}, err
|
||||||
|
}
|
||||||
|
return asset.MaxSwapAmount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMinBlockLock returns the minimum block lock
|
||||||
|
func (k Keeper) GetMinBlockLock(ctx sdk.Context, denom string) (uint64, error) {
|
||||||
|
asset, err := k.GetAsset(ctx, denom)
|
||||||
|
if err != nil {
|
||||||
|
return uint64(0), err
|
||||||
|
}
|
||||||
|
return asset.MinBlockLock, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMaxBlockLock returns the maximum block lock
|
||||||
|
func (k Keeper) GetMaxBlockLock(ctx sdk.Context, denom string) (uint64, error) {
|
||||||
|
asset, err := k.GetAsset(ctx, denom)
|
||||||
|
if err != nil {
|
||||||
|
return uint64(0), err
|
||||||
|
}
|
||||||
|
return asset.MaxBlockLock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAssetByCoinID returns an asset by its denom
|
// GetAssetByCoinID returns an asset by its denom
|
||||||
func (k Keeper) GetAssetByCoinID(ctx sdk.Context, coinID int) (types.AssetParam, bool) {
|
func (k Keeper) GetAssetByCoinID(ctx sdk.Context, coinID int) (types.AssetParam, bool) {
|
||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
for _, asset := range params.SupportedAssets {
|
for _, asset := range params.AssetParams {
|
||||||
if asset.CoinID == coinID {
|
if asset.CoinID == coinID {
|
||||||
return asset, true
|
return asset, true
|
||||||
}
|
}
|
||||||
@ -84,12 +121,21 @@ func (k Keeper) GetAssetByCoinID(ctx sdk.Context, coinID int) (types.AssetParam,
|
|||||||
|
|
||||||
// ValidateLiveAsset checks if an asset is both supported and active
|
// ValidateLiveAsset checks if an asset is both supported and active
|
||||||
func (k Keeper) ValidateLiveAsset(ctx sdk.Context, coin sdk.Coin) error {
|
func (k Keeper) ValidateLiveAsset(ctx sdk.Context, coin sdk.Coin) error {
|
||||||
asset, found := k.GetAssetByDenom(ctx, coin.Denom)
|
asset, err := k.GetAsset(ctx, coin.Denom)
|
||||||
if !found {
|
if err != nil {
|
||||||
return sdkerrors.Wrap(types.ErrAssetNotSupported, coin.Denom)
|
return err
|
||||||
}
|
}
|
||||||
if !asset.Active {
|
if !asset.Active {
|
||||||
return sdkerrors.Wrap(types.ErrAssetNotActive, asset.Denom)
|
return sdkerrors.Wrap(types.ErrAssetNotActive, asset.Denom)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSupplyLimit returns the supply limit for the input denom
|
||||||
|
func (k Keeper) GetSupplyLimit(ctx sdk.Context, denom string) (sdk.Int, error) {
|
||||||
|
asset, err := k.GetAsset(ctx, denom)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.Int{}, err
|
||||||
|
}
|
||||||
|
return asset.SupplyLimit, nil
|
||||||
|
}
|
||||||
|
@ -35,78 +35,81 @@ func (suite *ParamsTestSuite) SetupTest() {
|
|||||||
suite.addrs = addrs
|
suite.addrs = addrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetSetBnbDeputyAddress() {
|
func (suite *ParamsTestSuite) TestGetSetAsset() {
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
asset, err := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
params.BnbDeputyAddress = suite.addrs[1]
|
suite.Require().NoError(err)
|
||||||
suite.NotPanics(func() { suite.keeper.SetParams(suite.ctx, params) })
|
suite.NotPanics(func() { suite.keeper.SetAsset(suite.ctx, asset) })
|
||||||
|
_, err = suite.keeper.GetAsset(suite.ctx, "dne")
|
||||||
|
suite.Require().Error(err)
|
||||||
|
|
||||||
params = suite.keeper.GetParams(suite.ctx)
|
_, err = suite.keeper.GetAsset(suite.ctx, "inc")
|
||||||
suite.Equal(suite.addrs[1], params.BnbDeputyAddress)
|
suite.Require().NoError(err)
|
||||||
addr := suite.keeper.GetBnbDeputyAddress(suite.ctx)
|
|
||||||
suite.Equal(suite.addrs[1], addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetBnbDeputyFixedFee() {
|
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
|
||||||
bnbDeputyFixedFee := params.BnbDeputyFixedFee
|
|
||||||
|
|
||||||
res := suite.keeper.GetBnbDeputyFixedFee(suite.ctx)
|
|
||||||
suite.Equal(bnbDeputyFixedFee, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetMinAmount() {
|
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
|
||||||
minAmount := params.MinAmount
|
|
||||||
|
|
||||||
res := suite.keeper.GetMinAmount(suite.ctx)
|
|
||||||
suite.Equal(minAmount, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetMaxAmount() {
|
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
|
||||||
maxAmount := params.MaxAmount
|
|
||||||
|
|
||||||
res := suite.keeper.GetMaxAmount(suite.ctx)
|
|
||||||
suite.Equal(maxAmount, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetMinBlockLock() {
|
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
|
||||||
minBlockLock := params.MinBlockLock
|
|
||||||
|
|
||||||
res := suite.keeper.GetMinBlockLock(suite.ctx)
|
|
||||||
suite.Equal(minBlockLock, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetMaxBlockLock() {
|
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
|
||||||
maxBlockLock := params.MaxBlockLock
|
|
||||||
|
|
||||||
res := suite.keeper.GetMaxBlockLock(suite.ctx)
|
|
||||||
suite.Equal(maxBlockLock, res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetAssets() {
|
func (suite *ParamsTestSuite) TestGetAssets() {
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
assets, found := suite.keeper.GetAssets(suite.ctx)
|
||||||
assets := params.SupportedAssets
|
suite.Require().True(found)
|
||||||
|
suite.Require().Equal(2, len(assets))
|
||||||
res, found := suite.keeper.GetAssets(suite.ctx)
|
|
||||||
suite.True(found)
|
|
||||||
suite.Equal(assets, res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetAssetByDenom() {
|
func (suite *ParamsTestSuite) TestGetSetDeputyAddress() {
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
asset, err := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
asset := params.SupportedAssets[0]
|
suite.Require().NoError(err)
|
||||||
|
asset.DeputyAddress = suite.addrs[1]
|
||||||
|
suite.NotPanics(func() { suite.keeper.SetAsset(suite.ctx, asset) })
|
||||||
|
|
||||||
res, found := suite.keeper.GetAssetByDenom(suite.ctx, asset.Denom)
|
asset, err = suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
suite.True(found)
|
suite.Require().NoError(err)
|
||||||
suite.Equal(asset, res)
|
suite.Equal(suite.addrs[1], asset.DeputyAddress)
|
||||||
|
addr, err := suite.keeper.GetDeputyAddress(suite.ctx, "bnb")
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Equal(suite.addrs[1], addr)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ParamsTestSuite) TestGetDeputyFixedFee() {
|
||||||
|
asset, err := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
bnbDeputyFixedFee := asset.FixedFee
|
||||||
|
|
||||||
|
res, err := suite.keeper.GetFixedFee(suite.ctx, asset.Denom)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Equal(bnbDeputyFixedFee, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ParamsTestSuite) TestGetMinMaxSwapAmount() {
|
||||||
|
asset, err := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
minAmount := asset.MinSwapAmount
|
||||||
|
|
||||||
|
res, err := suite.keeper.GetMinSwapAmount(suite.ctx, asset.Denom)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Equal(minAmount, res)
|
||||||
|
|
||||||
|
maxAmount := asset.MaxSwapAmount
|
||||||
|
res, err = suite.keeper.GetMaxSwapAmount(suite.ctx, asset.Denom)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Equal(maxAmount, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ParamsTestSuite) TestGetMinMaxBlockLock() {
|
||||||
|
asset, err := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
minLock := asset.MinBlockLock
|
||||||
|
|
||||||
|
res, err := suite.keeper.GetMinBlockLock(suite.ctx, asset.Denom)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Equal(minLock, res)
|
||||||
|
|
||||||
|
maxLock := asset.MaxBlockLock
|
||||||
|
res, err = suite.keeper.GetMaxBlockLock(suite.ctx, asset.Denom)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Equal(maxLock, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestGetAssetByCoinID() {
|
func (suite *ParamsTestSuite) TestGetAssetByCoinID() {
|
||||||
params := suite.keeper.GetParams(suite.ctx)
|
asset, err := suite.keeper.GetAsset(suite.ctx, "bnb")
|
||||||
asset := params.SupportedAssets[0]
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
res, found := suite.keeper.GetAssetByCoinID(suite.ctx, asset.CoinID)
|
res, found := suite.keeper.GetAssetByCoinID(suite.ctx, asset.CoinID)
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
|
@ -39,7 +39,7 @@ func queryAssetSupply(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]
|
|||||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
assetSupply, found := keeper.GetAssetSupply(ctx, []byte(requestParams.Denom))
|
assetSupply, found := keeper.GetAssetSupply(ctx, requestParams.Denom)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, sdkerrors.Wrap(types.ErrAssetSupplyNotFound, string(requestParams.Denom))
|
return nil, sdkerrors.Wrap(types.ErrAssetSupplyNotFound, string(requestParams.Denom))
|
||||||
}
|
}
|
||||||
|
@ -39,16 +39,16 @@ func (suite *QuerierTestSuite) SetupTest() {
|
|||||||
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
||||||
|
|
||||||
// Set up auth GenesisState
|
// Set up auth GenesisState
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(10)
|
_, addrs := app.GeneratePrivKeyAddressPairs(11)
|
||||||
coins := []sdk.Coins{}
|
coins := []sdk.Coins{}
|
||||||
for j := 0; j < 10; j++ {
|
for j := 0; j < 11; j++ {
|
||||||
coins = append(coins, cs(c("bnb", 10000000000), c("ukava", 10000000000)))
|
coins = append(coins, cs(c("bnb", 10000000000), c("ukava", 10000000000)))
|
||||||
}
|
}
|
||||||
authGS := app.NewAuthGenState(addrs, coins)
|
authGS := app.NewAuthGenState(addrs, coins)
|
||||||
|
|
||||||
tApp.InitializeFromGenesisStates(
|
tApp.InitializeFromGenesisStates(
|
||||||
authGS,
|
authGS,
|
||||||
NewBep3GenStateMulti(addrs[0]),
|
NewBep3GenStateMulti(addrs[10]),
|
||||||
)
|
)
|
||||||
|
|
||||||
suite.ctx = ctx
|
suite.ctx = ctx
|
||||||
@ -70,11 +70,11 @@ func (suite *QuerierTestSuite) SetupTest() {
|
|||||||
|
|
||||||
// Create atomic swap and check err
|
// Create atomic swap and check err
|
||||||
err := suite.keeper.CreateAtomicSwap(suite.ctx, randomNumberHash, timestamp, expireHeight,
|
err := suite.keeper.CreateAtomicSwap(suite.ctx, randomNumberHash, timestamp, expireHeight,
|
||||||
addrs[0], suite.addrs[i], TestSenderOtherChain, TestRecipientOtherChain, amount, true)
|
addrs[10], suite.addrs[i], TestSenderOtherChain, TestRecipientOtherChain, amount, true)
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
|
|
||||||
// Calculate swap ID and save
|
// Calculate swap ID and save
|
||||||
swapID := types.CalculateSwapID(randomNumberHash, addrs[0], TestSenderOtherChain)
|
swapID := types.CalculateSwapID(randomNumberHash, addrs[10], TestSenderOtherChain)
|
||||||
swapIDs = append(swapIDs, swapID)
|
swapIDs = append(swapIDs, swapID)
|
||||||
isSwapID[hex.EncodeToString(swapID)] = true
|
isSwapID[hex.EncodeToString(swapID)] = true
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ func (suite *QuerierTestSuite) TestQueryAssetSupply() {
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
query := abci.RequestQuery{
|
query := abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetAssetSupply}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetAssetSupply}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryAssetSupply(tmbytes.HexBytes(denom))),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryAssetSupply(denom)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute query and check the []byte result
|
// Execute query and check the []byte result
|
||||||
@ -101,8 +101,8 @@ func (suite *QuerierTestSuite) TestQueryAssetSupply() {
|
|||||||
var supply types.AssetSupply
|
var supply types.AssetSupply
|
||||||
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &supply))
|
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &supply))
|
||||||
|
|
||||||
expectedSupply := types.NewAssetSupply(denom, c(denom, 1000),
|
expectedSupply := types.NewAssetSupply(c(denom, 1000),
|
||||||
c(denom, 0), c(denom, 0), c(denom, StandardSupplyLimit.Int64()))
|
c(denom, 0), c(denom, 0))
|
||||||
suite.Equal(supply, expectedSupply)
|
suite.Equal(supply, expectedSupply)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,9 +179,10 @@ func (suite *QuerierTestSuite) TestQueryParams() {
|
|||||||
var p types.Params
|
var p types.Params
|
||||||
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &p))
|
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &p))
|
||||||
|
|
||||||
bep3GenesisState := NewBep3GenStateMulti(suite.addrs[0])
|
bep3GenesisState := NewBep3GenStateMulti(suite.addrs[10])
|
||||||
gs := types.GenesisState{}
|
gs := types.GenesisState{}
|
||||||
types.ModuleCdc.UnmarshalJSON(bep3GenesisState["bep3"], &gs)
|
types.ModuleCdc.UnmarshalJSON(bep3GenesisState["bep3"], &gs)
|
||||||
|
// update asset supply to account for swaps that were created in setup
|
||||||
suite.Equal(gs.Params, p)
|
suite.Equal(gs.Params, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,29 +31,38 @@ func (k Keeper) CreateAtomicSwap(ctx sdk.Context, randomNumberHash []byte, times
|
|||||||
if len(amount) != 1 {
|
if len(amount) != 1 {
|
||||||
return fmt.Errorf("amount must contain exactly one coin")
|
return fmt.Errorf("amount must contain exactly one coin")
|
||||||
}
|
}
|
||||||
|
asset, err := k.GetAsset(ctx, amount[0].Denom)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
err := k.ValidateLiveAsset(ctx, amount[0])
|
err = k.ValidateLiveAsset(ctx, amount[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap amount must be within the specified swap amount limits
|
// Swap amount must be within the specified swap amount limits
|
||||||
if amount[0].Amount.LT(k.GetMinAmount(ctx)) || amount[0].Amount.GT(k.GetMaxAmount(ctx)) {
|
if amount[0].Amount.LT(asset.MinSwapAmount) || amount[0].Amount.GT(asset.MaxSwapAmount) {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidAmount, "amount %d outside range [%d, %d]", amount[0].Amount, k.GetMinAmount(ctx), k.GetMaxAmount(ctx))
|
return sdkerrors.Wrapf(types.ErrInvalidAmount, "amount %d outside range [%s, %s]", amount[0].Amount, asset.MinSwapAmount, asset.MaxSwapAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unix timestamp must be in range [-15 mins, 30 mins] of the current time
|
// Unix timestamp must be in range [-15 mins, 30 mins] of the current time
|
||||||
pastTimestampLimit := ctx.BlockTime().Add(time.Duration(-15) * time.Minute).Unix()
|
pastTimestampLimit := ctx.BlockTime().Add(time.Duration(-15) * time.Minute).Unix()
|
||||||
futureTimestampLimit := ctx.BlockTime().Add(time.Duration(30) * time.Minute).Unix()
|
futureTimestampLimit := ctx.BlockTime().Add(time.Duration(30) * time.Minute).Unix()
|
||||||
if timestamp < pastTimestampLimit || timestamp >= futureTimestampLimit {
|
if timestamp < pastTimestampLimit || timestamp >= futureTimestampLimit {
|
||||||
return sdkerrors.Wrap(types.ErrInvalidTimestamp, time.Unix(timestamp, 0).UTC().String())
|
return sdkerrors.Wrap(types.ErrInvalidTimestamp, fmt.Sprintf("block time: %s, timestamp: %s", ctx.BlockTime().String(), time.Unix(timestamp, 0).UTC().String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
var direction types.SwapDirection
|
var direction types.SwapDirection
|
||||||
deputy := k.GetBnbDeputyAddress(ctx)
|
if sender.Equals(asset.DeputyAddress) {
|
||||||
if sender.Equals(deputy) {
|
if recipient.Equals(asset.DeputyAddress) {
|
||||||
|
return sdkerrors.Wrapf(types.ErrInvalidSwapAccount, "deputy cannot be both sender and receiver: %s", asset.DeputyAddress)
|
||||||
|
}
|
||||||
direction = types.Incoming
|
direction = types.Incoming
|
||||||
} else {
|
} else {
|
||||||
|
if !recipient.Equals(asset.DeputyAddress) {
|
||||||
|
return sdkerrors.Wrapf(types.ErrInvalidSwapAccount, "deputy must be recipient for outgoing account: %s", recipient)
|
||||||
|
}
|
||||||
direction = types.Outgoing
|
direction = types.Outgoing
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,18 +78,13 @@ func (k Keeper) CreateAtomicSwap(ctx sdk.Context, randomNumberHash []byte, times
|
|||||||
// Incoming swaps have already had their fees collected by the deputy during the relay process.
|
// Incoming swaps have already had their fees collected by the deputy during the relay process.
|
||||||
err = k.IncrementIncomingAssetSupply(ctx, amount[0])
|
err = k.IncrementIncomingAssetSupply(ctx, amount[0])
|
||||||
case types.Outgoing:
|
case types.Outgoing:
|
||||||
if ctx.BlockTime().After(types.SupplyLimitUpgradeTime) {
|
|
||||||
if !recipient.Equals(deputy) {
|
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidOutgoingAccount, "%s", recipient)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Outoing swaps must have a height span within the accepted range
|
// Outoing swaps must have a height span within the accepted range
|
||||||
if heightSpan < k.GetMinBlockLock(ctx) || heightSpan > k.GetMaxBlockLock(ctx) {
|
if heightSpan < asset.MinBlockLock || heightSpan > asset.MaxBlockLock {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidHeightSpan, "height span %d outside range [%d, %d]", heightSpan, k.GetMinBlockLock(ctx), k.GetMaxBlockLock(ctx))
|
return sdkerrors.Wrapf(types.ErrInvalidHeightSpan, "height span %d outside range [%d, %d]", heightSpan, asset.MinBlockLock, asset.MaxBlockLock)
|
||||||
}
|
}
|
||||||
// Amount in outgoing swaps must be able to pay the deputy's fixed fee.
|
// Amount in outgoing swaps must be able to pay the deputy's fixed fee.
|
||||||
if amount[0].Amount.LTE(k.GetBnbDeputyFixedFee(ctx).Add(k.GetMinAmount(ctx))) {
|
if amount[0].Amount.LTE(asset.FixedFee.Add(asset.MinSwapAmount)) {
|
||||||
return sdkerrors.Wrap(types.ErrInsufficientAmount, amount[0].String())
|
return sdkerrors.Wrap(types.ErrInsufficientAmount, amount[0].String())
|
||||||
}
|
}
|
||||||
err = k.IncrementOutgoingAssetSupply(ctx, amount[0])
|
err = k.IncrementOutgoingAssetSupply(ctx, amount[0])
|
||||||
|
@ -156,60 +156,6 @@ func (suite *AtomicSwapTestSuite) TestCreateAtomicSwap() {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"outgoing swap recipient before update",
|
|
||||||
types.SupplyLimitUpgradeTime.Add(-time.Hour),
|
|
||||||
args{
|
|
||||||
randomNumberHash: suite.randomNumberHashes[12],
|
|
||||||
timestamp: types.SupplyLimitUpgradeTime.Add(-time.Hour).Unix(),
|
|
||||||
heightSpan: types.DefaultMinBlockLock,
|
|
||||||
sender: suite.addrs[1],
|
|
||||||
recipient: suite.addrs[2],
|
|
||||||
senderOtherChain: TestUser1.String(),
|
|
||||||
recipientOtherChain: TestUser2.String(),
|
|
||||||
coins: cs(c(BNB_DENOM, 50000)),
|
|
||||||
crossChain: true,
|
|
||||||
direction: types.Outgoing,
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"outgoing swap recipient at update time",
|
|
||||||
types.SupplyLimitUpgradeTime,
|
|
||||||
args{
|
|
||||||
randomNumberHash: suite.randomNumberHashes[13],
|
|
||||||
timestamp: types.SupplyLimitUpgradeTime.Unix(),
|
|
||||||
heightSpan: types.DefaultMinBlockLock,
|
|
||||||
sender: suite.addrs[1],
|
|
||||||
recipient: suite.addrs[2],
|
|
||||||
senderOtherChain: TestUser1.String(),
|
|
||||||
recipientOtherChain: TestUser2.String(),
|
|
||||||
coins: cs(c(BNB_DENOM, 50000)),
|
|
||||||
crossChain: true,
|
|
||||||
direction: types.Outgoing,
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"outgoing swap recipient after update",
|
|
||||||
types.SupplyLimitUpgradeTime.Add(time.Nanosecond),
|
|
||||||
args{
|
|
||||||
randomNumberHash: suite.randomNumberHashes[14],
|
|
||||||
timestamp: types.SupplyLimitUpgradeTime.Add(time.Nanosecond).Unix(),
|
|
||||||
heightSpan: types.DefaultMinBlockLock,
|
|
||||||
sender: suite.addrs[1],
|
|
||||||
recipient: suite.addrs[2],
|
|
||||||
senderOtherChain: TestUser1.String(),
|
|
||||||
recipientOtherChain: TestUser2.String(),
|
|
||||||
coins: cs(c(BNB_DENOM, 50000)),
|
|
||||||
crossChain: true,
|
|
||||||
direction: types.Outgoing,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
|
|
||||||
"outgoing swap amount not greater than fixed fee",
|
"outgoing swap amount not greater than fixed fee",
|
||||||
@ -222,7 +168,7 @@ func (suite *AtomicSwapTestSuite) TestCreateAtomicSwap() {
|
|||||||
recipient: suite.addrs[2],
|
recipient: suite.addrs[2],
|
||||||
senderOtherChain: TestSenderOtherChain,
|
senderOtherChain: TestSenderOtherChain,
|
||||||
recipientOtherChain: TestRecipientOtherChain,
|
recipientOtherChain: TestRecipientOtherChain,
|
||||||
coins: cs(c(BNB_DENOM, suite.keeper.GetBnbDeputyFixedFee(suite.ctx).Int64())),
|
coins: cs(c(BNB_DENOM, 1000)),
|
||||||
crossChain: true,
|
crossChain: true,
|
||||||
direction: types.Outgoing,
|
direction: types.Outgoing,
|
||||||
},
|
},
|
||||||
@ -432,7 +378,7 @@ func (suite *AtomicSwapTestSuite) TestCreateAtomicSwap() {
|
|||||||
ak := suite.app.GetAccountKeeper()
|
ak := suite.app.GetAccountKeeper()
|
||||||
senderAccPre := ak.GetAccount(suite.ctx, tc.args.sender)
|
senderAccPre := ak.GetAccount(suite.ctx, tc.args.sender)
|
||||||
senderBalancePre := senderAccPre.GetCoins().AmountOf(swapAssetDenom)
|
senderBalancePre := senderAccPre.GetCoins().AmountOf(swapAssetDenom)
|
||||||
assetSupplyPre, _ := suite.keeper.GetAssetSupply(suite.ctx, []byte(swapAssetDenom))
|
assetSupplyPre, _ := suite.keeper.GetAssetSupply(suite.ctx, swapAssetDenom)
|
||||||
|
|
||||||
// Create atomic swap
|
// Create atomic swap
|
||||||
err := suite.keeper.CreateAtomicSwap(suite.ctx, tc.args.randomNumberHash, tc.args.timestamp,
|
err := suite.keeper.CreateAtomicSwap(suite.ctx, tc.args.randomNumberHash, tc.args.timestamp,
|
||||||
@ -442,7 +388,7 @@ func (suite *AtomicSwapTestSuite) TestCreateAtomicSwap() {
|
|||||||
// Load sender's account after swap creation
|
// Load sender's account after swap creation
|
||||||
senderAccPost := ak.GetAccount(suite.ctx, tc.args.sender)
|
senderAccPost := ak.GetAccount(suite.ctx, tc.args.sender)
|
||||||
senderBalancePost := senderAccPost.GetCoins().AmountOf(swapAssetDenom)
|
senderBalancePost := senderAccPost.GetCoins().AmountOf(swapAssetDenom)
|
||||||
assetSupplyPost, _ := suite.keeper.GetAssetSupply(suite.ctx, []byte(swapAssetDenom))
|
assetSupplyPost, _ := suite.keeper.GetAssetSupply(suite.ctx, swapAssetDenom)
|
||||||
|
|
||||||
// Load expected swap ID
|
// Load expected swap ID
|
||||||
expectedSwapID := types.CalculateSwapID(tc.args.randomNumberHash, tc.args.sender, tc.args.senderOtherChain)
|
expectedSwapID := types.CalculateSwapID(tc.args.randomNumberHash, tc.args.sender, tc.args.senderOtherChain)
|
||||||
@ -625,7 +571,7 @@ func (suite *AtomicSwapTestSuite) TestClaimAtomicSwap() {
|
|||||||
expectedRecipientAccPre := ak.GetAccount(tc.claimCtx, expectedRecipient)
|
expectedRecipientAccPre := ak.GetAccount(tc.claimCtx, expectedRecipient)
|
||||||
expectedRecipientBalancePre := expectedRecipientAccPre.GetCoins().AmountOf(expectedClaimAmount[0].Denom)
|
expectedRecipientBalancePre := expectedRecipientAccPre.GetCoins().AmountOf(expectedClaimAmount[0].Denom)
|
||||||
// Load asset supplies prior to claim attempt
|
// Load asset supplies prior to claim attempt
|
||||||
assetSupplyPre, _ := suite.keeper.GetAssetSupply(tc.claimCtx, []byte(expectedClaimAmount[0].Denom))
|
assetSupplyPre, _ := suite.keeper.GetAssetSupply(tc.claimCtx, expectedClaimAmount[0].Denom)
|
||||||
|
|
||||||
// Attempt to claim atomic swap
|
// Attempt to claim atomic swap
|
||||||
err = suite.keeper.ClaimAtomicSwap(tc.claimCtx, expectedRecipient, claimSwapID, claimRandomNumber)
|
err = suite.keeper.ClaimAtomicSwap(tc.claimCtx, expectedRecipient, claimSwapID, claimRandomNumber)
|
||||||
@ -634,7 +580,7 @@ func (suite *AtomicSwapTestSuite) TestClaimAtomicSwap() {
|
|||||||
expectedRecipientAccPost := ak.GetAccount(tc.claimCtx, expectedRecipient)
|
expectedRecipientAccPost := ak.GetAccount(tc.claimCtx, expectedRecipient)
|
||||||
expectedRecipientBalancePost := expectedRecipientAccPost.GetCoins().AmountOf(expectedClaimAmount[0].Denom)
|
expectedRecipientBalancePost := expectedRecipientAccPost.GetCoins().AmountOf(expectedClaimAmount[0].Denom)
|
||||||
// Load asset supplies after the claim attempt
|
// Load asset supplies after the claim attempt
|
||||||
assetSupplyPost, _ := suite.keeper.GetAssetSupply(tc.claimCtx, []byte(expectedClaimAmount[0].Denom))
|
assetSupplyPost, _ := suite.keeper.GetAssetSupply(tc.claimCtx, expectedClaimAmount[0].Denom)
|
||||||
|
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
@ -773,7 +719,7 @@ func (suite *AtomicSwapTestSuite) TestRefundAtomicSwap() {
|
|||||||
originalSenderAccPre := ak.GetAccount(tc.refundCtx, sender)
|
originalSenderAccPre := ak.GetAccount(tc.refundCtx, sender)
|
||||||
originalSenderBalancePre := originalSenderAccPre.GetCoins().AmountOf(expectedRefundAmount[0].Denom)
|
originalSenderBalancePre := originalSenderAccPre.GetCoins().AmountOf(expectedRefundAmount[0].Denom)
|
||||||
// Load asset supply prior to swap refund
|
// Load asset supply prior to swap refund
|
||||||
assetSupplyPre, _ := suite.keeper.GetAssetSupply(tc.refundCtx, []byte(expectedRefundAmount[0].Denom))
|
assetSupplyPre, _ := suite.keeper.GetAssetSupply(tc.refundCtx, expectedRefundAmount[0].Denom)
|
||||||
|
|
||||||
// Attempt to refund atomic swap
|
// Attempt to refund atomic swap
|
||||||
err = suite.keeper.RefundAtomicSwap(tc.refundCtx, sender, refundSwapID)
|
err = suite.keeper.RefundAtomicSwap(tc.refundCtx, sender, refundSwapID)
|
||||||
@ -782,7 +728,7 @@ func (suite *AtomicSwapTestSuite) TestRefundAtomicSwap() {
|
|||||||
originalSenderAccPost := ak.GetAccount(tc.refundCtx, sender)
|
originalSenderAccPost := ak.GetAccount(tc.refundCtx, sender)
|
||||||
originalSenderBalancePost := originalSenderAccPost.GetCoins().AmountOf(expectedRefundAmount[0].Denom)
|
originalSenderBalancePost := originalSenderAccPost.GetCoins().AmountOf(expectedRefundAmount[0].Denom)
|
||||||
// Load asset supply after to swap refund
|
// Load asset supply after to swap refund
|
||||||
assetSupplyPost, _ := suite.keeper.GetAssetSupply(tc.refundCtx, []byte(expectedRefundAmount[0].Denom))
|
assetSupplyPost, _ := suite.keeper.GetAssetSupply(tc.refundCtx, expectedRefundAmount[0].Denom)
|
||||||
|
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
81
x/bep3/legacy/v0_11/types.go
Normal file
81
x/bep3/legacy/v0_11/types.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package v0_11
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GenesisState - all bep3 state that must be provided at genesis
|
||||||
|
type GenesisState struct {
|
||||||
|
Params Params `json:"params" yaml:"params"`
|
||||||
|
AtomicSwaps AtomicSwaps `json:"atomic_swaps" yaml:"atomic_swaps"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Params governance parameters for the bep3 module
|
||||||
|
type Params struct {
|
||||||
|
AssetParams AssetParams `json:"asset_params" yaml:"asset_params"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetParam parameters that must be specified for each bep3 asset
|
||||||
|
type AssetParam struct {
|
||||||
|
Denom string `json:"denom" yaml:"denom"` // name of the asset
|
||||||
|
CoinID int `json:"coin_id" yaml:"coin_id"` // SLIP-0044 registered coin type - see https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||||
|
SupplyLimit AssetSupply `json:"supply_limit" yaml:"supply_limit"` // asset supply limit
|
||||||
|
Active bool `json:"active" yaml:"active"` // denotes if asset is available or paused
|
||||||
|
DeputyAddress sdk.AccAddress `json:"deputy_address" yaml:"deputy_address"` // the address of the relayer process
|
||||||
|
FixedFee sdk.Int `json:"incoming_swap_fixed_fee" yaml:"incoming_swap_fixed_fee"` // the fixed fee charged by the relayer process for incoming swaps
|
||||||
|
MinSwapAmount sdk.Int `json:"min_swap_amount" yaml:"min_swap_amount"` // Minimum swap amount
|
||||||
|
MaxSwapAmount sdk.Int `json:"max_swap_amount" yaml:"max_swap_amount"` // Maximum swap amount
|
||||||
|
MinBlockLock uint64 `json:"min_block_lock" yaml:"min_block_lock"` // Minimum swap block lock
|
||||||
|
MaxBlockLock uint64 `json:"max_block_lock" yaml:"max_block_lock"` // Maximum swap block lock
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetParams array of AssetParam
|
||||||
|
type AssetParams []AssetParam
|
||||||
|
|
||||||
|
// AssetSupply contains information about an asset's supply
|
||||||
|
type AssetSupply struct {
|
||||||
|
IncomingSupply sdk.Coin `json:"incoming_supply" yaml:"incoming_supply"`
|
||||||
|
OutgoingSupply sdk.Coin `json:"outgoing_supply" yaml:"outgoing_supply"`
|
||||||
|
CurrentSupply sdk.Coin `json:"current_supply" yaml:"current_supply"`
|
||||||
|
SupplyLimit sdk.Coin `json:"supply_limit" yaml:"supply_limit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AtomicSwap contains the information for an atomic swap
|
||||||
|
type AtomicSwap struct {
|
||||||
|
Amount sdk.Coins `json:"amount" yaml:"amount"`
|
||||||
|
RandomNumberHash tmbytes.HexBytes `json:"random_number_hash" yaml:"random_number_hash"`
|
||||||
|
ExpireHeight uint64 `json:"expire_height" yaml:"expire_height"`
|
||||||
|
Timestamp int64 `json:"timestamp" yaml:"timestamp"`
|
||||||
|
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
||||||
|
Recipient sdk.AccAddress `json:"recipient" yaml:"recipient"`
|
||||||
|
SenderOtherChain string `json:"sender_other_chain" yaml:"sender_other_chain"`
|
||||||
|
RecipientOtherChain string `json:"recipient_other_chain" yaml:"recipient_other_chain"`
|
||||||
|
ClosedBlock int64 `json:"closed_block" yaml:"closed_block"`
|
||||||
|
Status SwapStatus `json:"status" yaml:"status"`
|
||||||
|
CrossChain bool `json:"cross_chain" yaml:"cross_chain"`
|
||||||
|
Direction SwapDirection `json:"direction" yaml:"direction"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AtomicSwaps is a slice of AtomicSwap
|
||||||
|
type AtomicSwaps []AtomicSwap
|
||||||
|
|
||||||
|
// SwapStatus is the status of an AtomicSwap
|
||||||
|
type SwapStatus byte
|
||||||
|
|
||||||
|
// swap statuses
|
||||||
|
const (
|
||||||
|
NULL SwapStatus = 0x00
|
||||||
|
Open SwapStatus = 0x01
|
||||||
|
Completed SwapStatus = 0x02
|
||||||
|
Expired SwapStatus = 0x03
|
||||||
|
)
|
||||||
|
|
||||||
|
// SwapDirection is the direction of an AtomicSwap
|
||||||
|
type SwapDirection byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
INVALID SwapDirection = 0x00
|
||||||
|
Incoming SwapDirection = 0x01
|
||||||
|
Outgoing SwapDirection = 0x02
|
||||||
|
)
|
151
x/bep3/legacy/v0_9/types.go
Normal file
151
x/bep3/legacy/v0_9/types.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package v0_9
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ModuleName = "bep3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultBnbDeputyFixedFee sdk.Int = sdk.NewInt(1000) // 0.00001 BNB
|
||||||
|
DefaultMinAmount sdk.Int = sdk.ZeroInt()
|
||||||
|
DefaultMaxAmount sdk.Int = sdk.NewInt(1000000000000) // 10,000 BNB
|
||||||
|
DefaultMinBlockLock uint64 = 220
|
||||||
|
DefaultMaxBlockLock uint64 = 270
|
||||||
|
DefaultSupportedAssets = AssetParams{
|
||||||
|
AssetParam{
|
||||||
|
Denom: "bnb",
|
||||||
|
CoinID: 714,
|
||||||
|
Limit: sdk.NewInt(350000000000000), // 3,500,000 BNB
|
||||||
|
Active: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
KeySupportedAssets = []byte("SupportedAssets")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Params v0.9 governance parameters for bep3 module
|
||||||
|
type Params struct {
|
||||||
|
BnbDeputyAddress sdk.AccAddress `json:"bnb_deputy_address" yaml:"bnb_deputy_address"` // Bnbchain deputy address
|
||||||
|
BnbDeputyFixedFee sdk.Int `json:"bnb_deputy_fixed_fee" yaml:"bnb_deputy_fixed_fee"` // Deputy fixed fee in BNB
|
||||||
|
MinAmount sdk.Int `json:"min_amount" yaml:"min_amount"` // Minimum swap amount
|
||||||
|
MaxAmount sdk.Int `json:"max_amount" yaml:"max_amount"` // Maximum swap amount
|
||||||
|
MinBlockLock uint64 `json:"min_block_lock" yaml:"min_block_lock"` // Minimum swap block lock
|
||||||
|
MaxBlockLock uint64 `json:"max_block_lock" yaml:"max_block_lock"` // Maximum swap block lock
|
||||||
|
SupportedAssets AssetParams `json:"supported_assets" yaml:"supported_assets"` // Supported assets
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewParams returns a new params object
|
||||||
|
func NewParams(bnbDeputyAddress sdk.AccAddress, bnbDeputyFixedFee, minAmount,
|
||||||
|
maxAmount sdk.Int, minBlockLock, maxBlockLock uint64, supportedAssets AssetParams,
|
||||||
|
) Params {
|
||||||
|
return Params{
|
||||||
|
BnbDeputyAddress: bnbDeputyAddress,
|
||||||
|
BnbDeputyFixedFee: bnbDeputyFixedFee,
|
||||||
|
MinAmount: minAmount,
|
||||||
|
MaxAmount: maxAmount,
|
||||||
|
MinBlockLock: minBlockLock,
|
||||||
|
MaxBlockLock: maxBlockLock,
|
||||||
|
SupportedAssets: supportedAssets,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetParam v0.9 governance parameters for each asset supported on kava chain
|
||||||
|
type AssetParam struct {
|
||||||
|
Denom string `json:"denom" yaml:"denom"` // name of the asset
|
||||||
|
CoinID int `json:"coin_id" yaml:"coin_id"` // internationally recognized coin ID
|
||||||
|
Limit sdk.Int `json:"limit" yaml:"limit"` // asset supply limit
|
||||||
|
Active bool `json:"active" yaml:"active"` // denotes if asset is available or paused
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetParams is a slice of AssetParams
|
||||||
|
type AssetParams []AssetParam
|
||||||
|
|
||||||
|
// GenesisState - all bep3 state that must be provided at genesis
|
||||||
|
type GenesisState struct {
|
||||||
|
Params Params `json:"params" yaml:"params"`
|
||||||
|
AtomicSwaps AtomicSwaps `json:"atomic_swaps" yaml:"atomic_swaps"`
|
||||||
|
AssetSupplies AssetSupplies `json:"assets_supplies" yaml:"assets_supplies"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGenesisState creates a new GenesisState object
|
||||||
|
func NewGenesisState(params Params, swaps AtomicSwaps, supplies AssetSupplies) GenesisState {
|
||||||
|
return GenesisState{
|
||||||
|
Params: params,
|
||||||
|
AtomicSwaps: swaps,
|
||||||
|
AssetSupplies: supplies,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultGenesisState - default GenesisState used by Cosmos Hub
|
||||||
|
func DefaultGenesisState() GenesisState {
|
||||||
|
return NewGenesisState(
|
||||||
|
DefaultParams(),
|
||||||
|
AtomicSwaps{},
|
||||||
|
AssetSupplies{},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultParams returns default params for bep3 module
|
||||||
|
func DefaultParams() Params {
|
||||||
|
defaultBnbDeputyAddress, err := sdk.AccAddressFromBech32("kava1r4v2zdhdalfj2ydazallqvrus9fkphmglhn6u6")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewParams(defaultBnbDeputyAddress, DefaultBnbDeputyFixedFee, DefaultMinAmount,
|
||||||
|
DefaultMaxAmount, DefaultMinBlockLock, DefaultMaxBlockLock, DefaultSupportedAssets)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AtomicSwap contains the information for an atomic swap
|
||||||
|
type AtomicSwap struct {
|
||||||
|
Amount sdk.Coins `json:"amount" yaml:"amount"`
|
||||||
|
RandomNumberHash tmbytes.HexBytes `json:"random_number_hash" yaml:"random_number_hash"`
|
||||||
|
ExpireHeight uint64 `json:"expire_height" yaml:"expire_height"`
|
||||||
|
Timestamp int64 `json:"timestamp" yaml:"timestamp"`
|
||||||
|
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
||||||
|
Recipient sdk.AccAddress `json:"recipient" yaml:"recipient"`
|
||||||
|
SenderOtherChain string `json:"sender_other_chain" yaml:"sender_other_chain"`
|
||||||
|
RecipientOtherChain string `json:"recipient_other_chain" yaml:"recipient_other_chain"`
|
||||||
|
ClosedBlock int64 `json:"closed_block" yaml:"closed_block"`
|
||||||
|
Status SwapStatus `json:"status" yaml:"status"`
|
||||||
|
CrossChain bool `json:"cross_chain" yaml:"cross_chain"`
|
||||||
|
Direction SwapDirection `json:"direction" yaml:"direction"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AtomicSwaps is a slice of AtomicSwap
|
||||||
|
type AtomicSwaps []AtomicSwap
|
||||||
|
|
||||||
|
// AssetSupply contains information about an asset's supply
|
||||||
|
type AssetSupply struct {
|
||||||
|
Denom string `json:"denom" yaml:"denom"`
|
||||||
|
IncomingSupply sdk.Coin `json:"incoming_supply" yaml:"incoming_supply"`
|
||||||
|
OutgoingSupply sdk.Coin `json:"outgoing_supply" yaml:"outgoing_supply"`
|
||||||
|
CurrentSupply sdk.Coin `json:"current_supply" yaml:"current_supply"`
|
||||||
|
SupplyLimit sdk.Coin `json:"supply_limit" yaml:"supply_limit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetSupplies is a slice of AssetSupply
|
||||||
|
type AssetSupplies []AssetSupply
|
||||||
|
|
||||||
|
// SwapStatus is the status of an AtomicSwap
|
||||||
|
type SwapStatus byte
|
||||||
|
|
||||||
|
// swap statuses
|
||||||
|
const (
|
||||||
|
NULL SwapStatus = 0x00
|
||||||
|
Open SwapStatus = 0x01
|
||||||
|
Completed SwapStatus = 0x02
|
||||||
|
Expired SwapStatus = 0x03
|
||||||
|
)
|
||||||
|
|
||||||
|
// SwapDirection is the direction of an AtomicSwap
|
||||||
|
type SwapDirection byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
INVALID SwapDirection = 0x00
|
||||||
|
Incoming SwapDirection = 0x01
|
||||||
|
Outgoing SwapDirection = 0x02
|
||||||
|
)
|
@ -21,17 +21,16 @@ func DecodeStore(cdc *codec.Codec, kvA, kvB kv.Pair) string {
|
|||||||
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &swapB)
|
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &swapB)
|
||||||
return fmt.Sprintf("%v\n%v", swapA, swapB)
|
return fmt.Sprintf("%v\n%v", swapA, swapB)
|
||||||
|
|
||||||
case bytes.Equal(kvA.Key[:1], types.AssetSupplyKeyPrefix):
|
|
||||||
var supplyA, supplyB types.AssetSupply
|
|
||||||
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &supplyA)
|
|
||||||
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &supplyB)
|
|
||||||
return fmt.Sprintf("%s\n%s", supplyA, supplyB)
|
|
||||||
|
|
||||||
case bytes.Equal(kvA.Key[:1], types.AtomicSwapByBlockPrefix),
|
case bytes.Equal(kvA.Key[:1], types.AtomicSwapByBlockPrefix),
|
||||||
bytes.Equal(kvA.Key[:1], types.AtomicSwapLongtermStoragePrefix):
|
bytes.Equal(kvA.Key[:1], types.AtomicSwapLongtermStoragePrefix):
|
||||||
var bytesA tmbytes.HexBytes = kvA.Value
|
var bytesA tmbytes.HexBytes = kvA.Value
|
||||||
var bytesB tmbytes.HexBytes = kvA.Value
|
var bytesB tmbytes.HexBytes = kvA.Value
|
||||||
return fmt.Sprintf("%s\n%s", bytesA.String(), bytesB.String())
|
return fmt.Sprintf("%s\n%s", bytesA.String(), bytesB.String())
|
||||||
|
case bytes.Equal(kvA.Key[:1], types.AssetSupplyPrefix):
|
||||||
|
var supplyA, supplyB types.AssetSupply
|
||||||
|
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &supplyA)
|
||||||
|
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &supplyB)
|
||||||
|
return fmt.Sprintf("%s\n%s", supplyA, supplyB)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("invalid %s key prefix %X", types.ModuleName, kvA.Key[:1]))
|
panic(fmt.Sprintf("invalid %s key prefix %X", types.ModuleName, kvA.Key[:1]))
|
||||||
|
@ -27,12 +27,12 @@ func TestDecodeDistributionStore(t *testing.T) {
|
|||||||
|
|
||||||
oneCoin := sdk.NewCoin("coin", sdk.OneInt())
|
oneCoin := sdk.NewCoin("coin", sdk.OneInt())
|
||||||
swap := types.NewAtomicSwap(sdk.Coins{oneCoin}, nil, 10, 100, nil, nil, "otherChainSender", "otherChainRec", 200, types.Completed, true, types.Outgoing)
|
swap := types.NewAtomicSwap(sdk.Coins{oneCoin}, nil, 10, 100, nil, nil, "otherChainSender", "otherChainRec", 200, types.Completed, true, types.Outgoing)
|
||||||
supply := types.AssetSupply{Denom: "coin", IncomingSupply: oneCoin, OutgoingSupply: oneCoin, CurrentSupply: oneCoin, SupplyLimit: oneCoin}
|
supply := types.AssetSupply{IncomingSupply: oneCoin, OutgoingSupply: oneCoin, CurrentSupply: oneCoin}
|
||||||
bz := tmbytes.HexBytes([]byte{1, 2})
|
bz := tmbytes.HexBytes([]byte{1, 2})
|
||||||
|
|
||||||
kvPairs := kv.Pairs{
|
kvPairs := kv.Pairs{
|
||||||
kv.Pair{Key: types.AtomicSwapKeyPrefix, Value: cdc.MustMarshalBinaryLengthPrefixed(swap)},
|
kv.Pair{Key: types.AtomicSwapKeyPrefix, Value: cdc.MustMarshalBinaryLengthPrefixed(swap)},
|
||||||
kv.Pair{Key: types.AssetSupplyKeyPrefix, Value: cdc.MustMarshalBinaryLengthPrefixed(supply)},
|
kv.Pair{Key: types.AssetSupplyPrefix, Value: cdc.MustMarshalBinaryLengthPrefixed(supply)},
|
||||||
kv.Pair{Key: types.AtomicSwapByBlockPrefix, Value: bz},
|
kv.Pair{Key: types.AtomicSwapByBlockPrefix, Value: bz},
|
||||||
kv.Pair{Key: types.AtomicSwapByBlockPrefix, Value: bz},
|
kv.Pair{Key: types.AtomicSwapByBlockPrefix, Value: bz},
|
||||||
kv.Pair{Key: []byte{0x99}, Value: []byte{0x99}},
|
kv.Pair{Key: []byte{0x99}, Value: []byte{0x99}},
|
||||||
|
@ -16,21 +16,13 @@ import (
|
|||||||
"github.com/kava-labs/kava/x/bep3/types"
|
"github.com/kava-labs/kava/x/bep3/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Simulation parameter constants
|
|
||||||
const (
|
|
||||||
BnbDeputyAddress = "bnb_deputy_address"
|
|
||||||
BnbDeputyFixedFee = "bnb_deputy_fixed_fee"
|
|
||||||
MinAmount = "min_amount"
|
|
||||||
MaxAmount = "max_amount"
|
|
||||||
MinBlockLock = "min_block_lock"
|
|
||||||
MaxBlockLock = "max_block_lock"
|
|
||||||
SupportedAssets = "supported_assets"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
MaxSupplyLimit = sdk.NewInt(1000000000000)
|
MaxSupplyLimit = 1000000000000
|
||||||
accs []simulation.Account
|
MinSupplyLimit = 100000000
|
||||||
ConsistentDenoms = [3]string{"bnb", "xrp", "btc"}
|
MinSwapAmountLimit = 999
|
||||||
|
accs []simulation.Account
|
||||||
|
ConsistentDenoms = [3]string{"bnb", "xrp", "btc"}
|
||||||
|
MinBlockLock = uint64(5)
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenRandBnbDeputy randomized BnbDeputyAddress
|
// GenRandBnbDeputy randomized BnbDeputyAddress
|
||||||
@ -39,39 +31,48 @@ func GenRandBnbDeputy(r *rand.Rand) simulation.Account {
|
|||||||
return acc
|
return acc
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenRandBnbDeputyFixedFee randomized BnbDeputyFixedFee in range [2, 10000]
|
// GenRandFixedFee randomized FixedFee in range [1, 10000]
|
||||||
func GenRandBnbDeputyFixedFee(r *rand.Rand) sdk.Int {
|
func GenRandFixedFee(r *rand.Rand) sdk.Int {
|
||||||
min := int(1)
|
min := int(1)
|
||||||
max := types.DefaultBnbDeputyFixedFee.Int64()
|
max := types.DefaultBnbDeputyFixedFee.Int64()
|
||||||
return sdk.NewInt(int64(r.Intn(int(max)-min) + min))
|
return sdk.NewInt(int64(r.Intn(int(max)-min) + min))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenMinAmount randomized MinAmount in range [0, 1000000000000]
|
// GenMinSwapAmount randomized MinAmount in range [1, 1000]
|
||||||
func GenMinAmount(r *rand.Rand) sdk.Int {
|
func GenMinSwapAmount(r *rand.Rand) sdk.Int {
|
||||||
min := types.DefaultMinAmount.Int64()
|
return sdk.OneInt().Add(simulation.RandomAmount(r, sdk.NewInt(int64(MinSwapAmountLimit))))
|
||||||
max := types.DefaultMaxAmount.Int64()
|
}
|
||||||
|
|
||||||
|
// GenMaxSwapAmount randomized MaxAmount
|
||||||
|
func GenMaxSwapAmount(r *rand.Rand, minAmount sdk.Int, supplyMax sdk.Int) sdk.Int {
|
||||||
|
min := minAmount.Int64()
|
||||||
|
max := supplyMax.Quo(sdk.NewInt(100)).Int64()
|
||||||
|
|
||||||
return sdk.NewInt((int64(r.Intn(int(max-min))) + min))
|
return sdk.NewInt((int64(r.Intn(int(max-min))) + min))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenMaxAmount randomized MaxAmount
|
// GenSupplyLimit generates a random SupplyLimit
|
||||||
func GenMaxAmount(r *rand.Rand, minAmount sdk.Int) sdk.Int {
|
func GenSupplyLimit(r *rand.Rand, max int) sdk.Int {
|
||||||
min := minAmount.Int64()
|
max = simulation.RandIntBetween(r, MinSupplyLimit, max)
|
||||||
max := types.DefaultMaxAmount.Int64()
|
return sdk.NewInt(int64(max))
|
||||||
return sdk.NewInt((int64(r.Intn(int(max-min))) + min))
|
}
|
||||||
|
|
||||||
|
// GenSupplyLimit generates a random SupplyLimit
|
||||||
|
func GenAssetSupply(r *rand.Rand, denom string) types.AssetSupply {
|
||||||
|
return types.NewAssetSupply(
|
||||||
|
sdk.NewCoin(denom, sdk.ZeroInt()), sdk.NewCoin(denom, sdk.ZeroInt()),
|
||||||
|
sdk.NewCoin(denom, sdk.ZeroInt()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenMinBlockLock randomized MinBlockLock
|
// GenMinBlockLock randomized MinBlockLock
|
||||||
func GenMinBlockLock(r *rand.Rand) uint64 {
|
func GenMinBlockLock(r *rand.Rand) uint64 {
|
||||||
min := int(1)
|
return MinBlockLock
|
||||||
max := int(types.DefaultMaxBlockLock)
|
|
||||||
return uint64(r.Intn(max-min) + min)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenMaxBlockLock randomized MaxBlockLock
|
// GenMaxBlockLock randomized MaxBlockLock
|
||||||
func GenMaxBlockLock(r *rand.Rand, minBlockLock uint64) uint64 {
|
func GenMaxBlockLock(r *rand.Rand, minBlockLock uint64) uint64 {
|
||||||
min := int(minBlockLock)
|
max := int(50)
|
||||||
max := int(types.DefaultMaxBlockLock)
|
return uint64(r.Intn(max-int(MinBlockLock)) + int(MinBlockLock+1))
|
||||||
return uint64(r.Intn(max-min) + min)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenSupportedAssets gets randomized SupportedAssets
|
// GenSupportedAssets gets randomized SupportedAssets
|
||||||
@ -92,12 +93,21 @@ func GenSupportedAssets(r *rand.Rand) types.AssetParams {
|
|||||||
|
|
||||||
func genSupportedAsset(r *rand.Rand, denom string) types.AssetParam {
|
func genSupportedAsset(r *rand.Rand, denom string) types.AssetParam {
|
||||||
coinID, _ := simulation.RandPositiveInt(r, sdk.NewInt(100000))
|
coinID, _ := simulation.RandPositiveInt(r, sdk.NewInt(100000))
|
||||||
limit, _ := simulation.RandPositiveInt(r, MaxSupplyLimit)
|
limit := GenSupplyLimit(r, MaxSupplyLimit)
|
||||||
|
|
||||||
|
minSwapAmount := GenMinSwapAmount(r)
|
||||||
|
minBlockLock := GenMinBlockLock(r)
|
||||||
return types.AssetParam{
|
return types.AssetParam{
|
||||||
Denom: denom,
|
Denom: denom,
|
||||||
CoinID: int(coinID.Int64()),
|
CoinID: int(coinID.Int64()),
|
||||||
Limit: limit,
|
SupplyLimit: limit,
|
||||||
Active: true,
|
Active: true,
|
||||||
|
DeputyAddress: GenRandBnbDeputy(r).Address,
|
||||||
|
FixedFee: GenRandFixedFee(r),
|
||||||
|
MinSwapAmount: minSwapAmount,
|
||||||
|
MaxSwapAmount: GenMaxSwapAmount(r, minSwapAmount, limit),
|
||||||
|
MinBlockLock: minBlockLock,
|
||||||
|
MaxBlockLock: GenMaxBlockLock(r, minBlockLock),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,31 +133,19 @@ func RandomizedGenState(simState *module.SimulationState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadRandomBep3GenState(simState *module.SimulationState) types.GenesisState {
|
func loadRandomBep3GenState(simState *module.SimulationState) types.GenesisState {
|
||||||
bnbDeputy := GenRandBnbDeputy(simState.Rand)
|
|
||||||
bnbDeputyFixedFee := GenRandBnbDeputyFixedFee(simState.Rand)
|
|
||||||
minAmount := types.DefaultMinAmount
|
|
||||||
maxAmount := GenMaxAmount(simState.Rand, minAmount)
|
|
||||||
|
|
||||||
// min/max block lock are hardcoded to 50/100 for expected -NumBlocks=100
|
supportedAssets := GenSupportedAssets(simState.Rand)
|
||||||
minBlockLock := uint64(50)
|
supplies := types.AssetSupplies{}
|
||||||
maxBlockLock := minBlockLock * 2
|
for _, asset := range supportedAssets {
|
||||||
|
supply := GenAssetSupply(simState.Rand, asset.Denom)
|
||||||
var supportedAssets types.AssetParams
|
supplies = append(supplies, supply)
|
||||||
simState.AppParams.GetOrGenerate(
|
}
|
||||||
simState.Cdc, SupportedAssets, &supportedAssets, simState.Rand,
|
|
||||||
func(r *rand.Rand) { supportedAssets = GenSupportedAssets(r) },
|
|
||||||
)
|
|
||||||
|
|
||||||
bep3Genesis := types.GenesisState{
|
bep3Genesis := types.GenesisState{
|
||||||
Params: types.Params{
|
Params: types.Params{
|
||||||
BnbDeputyAddress: bnbDeputy.Address,
|
AssetParams: supportedAssets,
|
||||||
BnbDeputyFixedFee: bnbDeputyFixedFee,
|
|
||||||
MinAmount: minAmount,
|
|
||||||
MaxAmount: maxAmount,
|
|
||||||
MinBlockLock: minBlockLock,
|
|
||||||
MaxBlockLock: maxBlockLock,
|
|
||||||
SupportedAssets: supportedAssets,
|
|
||||||
},
|
},
|
||||||
|
Supplies: supplies,
|
||||||
}
|
}
|
||||||
|
|
||||||
return bep3Genesis
|
return bep3Genesis
|
||||||
@ -156,22 +154,20 @@ func loadRandomBep3GenState(simState *module.SimulationState) types.GenesisState
|
|||||||
func loadAuthGenState(simState *module.SimulationState, bep3Genesis types.GenesisState) (auth.GenesisState, []sdk.Coins) {
|
func loadAuthGenState(simState *module.SimulationState, bep3Genesis types.GenesisState) (auth.GenesisState, []sdk.Coins) {
|
||||||
var authGenesis auth.GenesisState
|
var authGenesis auth.GenesisState
|
||||||
simState.Cdc.MustUnmarshalJSON(simState.GenState[auth.ModuleName], &authGenesis)
|
simState.Cdc.MustUnmarshalJSON(simState.GenState[auth.ModuleName], &authGenesis)
|
||||||
|
|
||||||
deputy, found := getAccount(authGenesis.Accounts, bep3Genesis.Params.BnbDeputyAddress)
|
|
||||||
if !found {
|
|
||||||
panic("deputy address not found in available accounts")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load total limit of each supported asset to deputy's account
|
// Load total limit of each supported asset to deputy's account
|
||||||
var totalCoins []sdk.Coins
|
var totalCoins []sdk.Coins
|
||||||
for _, asset := range bep3Genesis.Params.SupportedAssets {
|
for _, asset := range bep3Genesis.Params.AssetParams {
|
||||||
assetCoin := sdk.NewCoins(sdk.NewCoin(asset.Denom, asset.Limit))
|
deputy, found := getAccount(authGenesis.Accounts, asset.DeputyAddress)
|
||||||
|
if !found {
|
||||||
|
panic("deputy address not found in available accounts")
|
||||||
|
}
|
||||||
|
assetCoin := sdk.NewCoins(sdk.NewCoin(asset.Denom, asset.SupplyLimit))
|
||||||
if err := deputy.SetCoins(deputy.GetCoins().Add(assetCoin...)); err != nil {
|
if err := deputy.SetCoins(deputy.GetCoins().Add(assetCoin...)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
totalCoins = append(totalCoins, assetCoin)
|
totalCoins = append(totalCoins, assetCoin)
|
||||||
|
authGenesis.Accounts = replaceOrAppendAccount(authGenesis.Accounts, deputy)
|
||||||
}
|
}
|
||||||
authGenesis.Accounts = replaceOrAppendAccount(authGenesis.Accounts, deputy)
|
|
||||||
|
|
||||||
return authGenesis, totalCoins
|
return authGenesis, totalCoins
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
noOpMsg = simulation.NoOpMsg(types.ModuleName)
|
noOpMsg = simulation.NoOpMsg(types.ModuleName)
|
||||||
randomNumber = []byte{114, 21, 74, 180, 81, 92, 21, 91, 173, 164, 143, 111, 120, 58, 241, 58, 40, 22, 59, 133, 102, 233, 55, 149, 12, 199, 231, 63, 122, 23, 88, 9}
|
randomNumber = []byte{114, 21, 74, 180, 81, 92, 21, 91, 173, 164, 143, 111, 120, 58, 241, 58, 40, 22, 59, 133, 102, 233, 55, 149, 12, 199, 231, 63, 122, 23, 88, 9}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,50 +50,65 @@ func SimulateMsgCreateAtomicSwap(ak types.AccountKeeper, k keeper.Keeper) simula
|
|||||||
return func(
|
return func(
|
||||||
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, chainID string,
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, chainID string,
|
||||||
) (simulation.OperationMsg, []simulation.FutureOperation, error) {
|
) (simulation.OperationMsg, []simulation.FutureOperation, error) {
|
||||||
|
// Get asset supplies and shuffle them
|
||||||
// Set up deputy address as it's required for all atomic swaps
|
assets, found := k.GetAssets(ctx)
|
||||||
deputyAddr := k.GetBnbDeputyAddress(ctx)
|
if !found {
|
||||||
deputyAcc, foundDeputy := simulation.FindAccount(accs, deputyAddr)
|
|
||||||
if !foundDeputy {
|
|
||||||
return noOpMsg, nil, nil
|
return noOpMsg, nil, nil
|
||||||
}
|
}
|
||||||
|
r.Shuffle(len(assets), func(i, j int) {
|
||||||
// Get asset supplies and shuffle them
|
assets[i], assets[j] = assets[j], assets[i]
|
||||||
supplies := k.GetAllAssetSupplies(ctx)
|
|
||||||
r.Shuffle(len(supplies), func(i, j int) {
|
|
||||||
supplies[i], supplies[j] = supplies[j], supplies[i]
|
|
||||||
})
|
})
|
||||||
|
senderOutgoing, selectedAsset, found := findValidAccountAssetPair(accs, assets, func(simAcc simulation.Account, asset types.AssetParam) bool {
|
||||||
// Search for an account that holds coins received by an atomic swap
|
supply, found := k.GetAssetSupply(ctx, asset.Denom)
|
||||||
minAmountPlusFee := k.GetMinAmount(ctx).Add(k.GetBnbDeputyFixedFee(ctx))
|
if !found {
|
||||||
senderOut, asset, found := findValidAccountAssetSupplyPair(accs, supplies, func(acc simulation.Account, asset types.AssetSupply) bool {
|
return false
|
||||||
if asset.CurrentSupply.Amount.IsPositive() {
|
}
|
||||||
authAcc := ak.GetAccount(ctx, acc.Address)
|
if supply.CurrentSupply.Amount.IsPositive() {
|
||||||
|
authAcc := ak.GetAccount(ctx, simAcc.Address)
|
||||||
|
// deputy cannot be sender of outgoing swap
|
||||||
|
if authAcc.GetAddress().Equals(asset.DeputyAddress) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Search for an account that holds coins received by an atomic swap
|
||||||
|
minAmountPlusFee := asset.MinSwapAmount.Add(asset.FixedFee)
|
||||||
if authAcc.SpendableCoins(ctx.BlockTime()).AmountOf(asset.Denom).GT(minAmountPlusFee) {
|
if authAcc.SpendableCoins(ctx.BlockTime()).AmountOf(asset.Denom).GT(minAmountPlusFee) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Set sender, recipient, and denom depending on swap direction
|
|
||||||
var sender simulation.Account
|
var sender simulation.Account
|
||||||
var recipient simulation.Account
|
var recipient simulation.Account
|
||||||
var denom string
|
var asset types.AssetParam
|
||||||
|
|
||||||
// If an outgoing swap can be created, it's chosen 50% of the time.
|
// If an outgoing swap can be created, it's chosen 50% of the time.
|
||||||
if found && r.Intn(100) < 50 {
|
if found && r.Intn(100) < 50 {
|
||||||
sender = senderOut
|
deputy, found := simulation.FindAccount(accs, selectedAsset.DeputyAddress)
|
||||||
recipient = deputyAcc
|
if !found {
|
||||||
denom = asset.Denom
|
return noOpMsg, nil, nil
|
||||||
} else {
|
|
||||||
sender = deputyAcc
|
|
||||||
recipient, _ = simulation.RandomAcc(r, accs)
|
|
||||||
// Randomly select an asset from supported assets
|
|
||||||
assets, foundAsset := k.GetAssets(ctx)
|
|
||||||
if !foundAsset {
|
|
||||||
return noOpMsg, nil, fmt.Errorf("no supported assets found")
|
|
||||||
}
|
}
|
||||||
denom = assets[r.Intn(len(assets))].Denom
|
sender = senderOutgoing
|
||||||
|
recipient = deputy
|
||||||
|
asset = selectedAsset
|
||||||
|
} else {
|
||||||
|
// if an outgoing swap cannot be created or was not selected, simulate an incoming swap
|
||||||
|
assets, _ := k.GetAssets(ctx)
|
||||||
|
asset = assets[r.Intn(len(assets))]
|
||||||
|
var eligibleAccs []simulation.Account
|
||||||
|
for _, simAcc := range accs {
|
||||||
|
// don't allow recipient of incoming swap to be the deputy
|
||||||
|
if simAcc.Address.Equals(asset.DeputyAddress) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
eligibleAccs = append(eligibleAccs, simAcc)
|
||||||
|
}
|
||||||
|
recipient, _ = simulation.RandomAcc(r, eligibleAccs)
|
||||||
|
deputy, found := simulation.FindAccount(accs, asset.DeputyAddress)
|
||||||
|
if !found {
|
||||||
|
return noOpMsg, nil, nil
|
||||||
|
}
|
||||||
|
sender = deputy
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
recipientOtherChain := simulation.RandStringOfLength(r, 43)
|
recipientOtherChain := simulation.RandStringOfLength(r, 43)
|
||||||
@ -111,32 +126,33 @@ func SimulateMsgCreateAtomicSwap(ak types.AccountKeeper, k keeper.Keeper) simula
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get maximum valid amount
|
// Get maximum valid amount
|
||||||
maximumAmount := senderAcc.SpendableCoins(ctx.BlockTime()).Sub(fees).AmountOf(denom)
|
maximumAmount := senderAcc.SpendableCoins(ctx.BlockTime()).Sub(fees).AmountOf(asset.Denom)
|
||||||
// The maximum amount for outgoing swaps is limited by the asset's current supply
|
// The maximum amount for outgoing swaps is limited by the asset's current supply
|
||||||
if recipient.Equals(deputyAcc) {
|
if recipient.Address.Equals(asset.DeputyAddress) {
|
||||||
assetSupply, foundAssetSupply := k.GetAssetSupply(ctx, []byte(denom))
|
assetSupply, foundAssetSupply := k.GetAssetSupply(ctx, asset.Denom)
|
||||||
if !foundAssetSupply {
|
if !foundAssetSupply {
|
||||||
return noOpMsg, nil, fmt.Errorf("no asset supply found")
|
return noOpMsg, nil, fmt.Errorf("no asset supply found for %s", asset.Denom)
|
||||||
}
|
}
|
||||||
if maximumAmount.GT(assetSupply.CurrentSupply.Amount) {
|
if maximumAmount.GT(assetSupply.CurrentSupply.Amount.Sub(assetSupply.OutgoingSupply.Amount)) {
|
||||||
maximumAmount = assetSupply.CurrentSupply.Amount
|
maximumAmount = assetSupply.CurrentSupply.Amount.Sub(assetSupply.OutgoingSupply.Amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The maximum amount for all swaps is limited by the total max limit
|
// The maximum amount for all swaps is limited by the total max limit
|
||||||
if maximumAmount.GT(k.GetMaxAmount(ctx)) {
|
if maximumAmount.GT(asset.MaxSwapAmount) {
|
||||||
maximumAmount = k.GetMaxAmount(ctx)
|
maximumAmount = asset.MaxSwapAmount
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an amount of coins between 0.1 and 2% of total coins
|
// Get an amount of coins between 0.1 and 2% of total coins
|
||||||
amount := maximumAmount.Quo(sdk.NewInt(int64(simulation.RandIntBetween(r, 50, 1000))))
|
amount := maximumAmount.Quo(sdk.NewInt(int64(simulation.RandIntBetween(r, 50, 1000))))
|
||||||
|
minAmountPlusFee := asset.MinSwapAmount.Add(asset.FixedFee)
|
||||||
if amount.LT(minAmountPlusFee) {
|
if amount.LT(minAmountPlusFee) {
|
||||||
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (all funds exhausted for asset %s)", denom), "", false, nil), nil, nil
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (all funds exhausted for asset %s)", asset.Denom), "", false, nil), nil, nil
|
||||||
}
|
}
|
||||||
coins := sdk.NewCoins(sdk.NewCoin(denom, amount))
|
coins := sdk.NewCoins(sdk.NewCoin(asset.Denom, amount))
|
||||||
|
|
||||||
// We're assuming that sims are run with -NumBlocks=100
|
// We're assuming that sims are run with -NumBlocks=100
|
||||||
heightSpan := uint64(55)
|
heightSpan := uint64(simulation.RandIntBetween(r, int(asset.MinBlockLock), int(asset.MaxBlockLock)))
|
||||||
|
|
||||||
msg := types.NewMsgCreateAtomicSwap(
|
msg := types.NewMsgCreateAtomicSwap(
|
||||||
sender.Address, recipient.Address, recipientOtherChain, senderOtherChain,
|
sender.Address, recipient.Address, recipientOtherChain, senderOtherChain,
|
||||||
@ -162,8 +178,10 @@ func SimulateMsgCreateAtomicSwap(ak types.AccountKeeper, k keeper.Keeper) simula
|
|||||||
var futureOp simulation.FutureOperation
|
var futureOp simulation.FutureOperation
|
||||||
swapID := types.CalculateSwapID(msg.RandomNumberHash, msg.From, msg.SenderOtherChain)
|
swapID := types.CalculateSwapID(msg.RandomNumberHash, msg.From, msg.SenderOtherChain)
|
||||||
if r.Intn(100) < 50 {
|
if r.Intn(100) < 50 {
|
||||||
// Claim future operation
|
// Claim future operation - choose between next block and the block before height span
|
||||||
executionBlock := uint64(ctx.BlockHeight()) + msg.HeightSpan/2
|
executionBlock := uint64(
|
||||||
|
int(ctx.BlockHeight()+1) + r.Intn(int(heightSpan-1)))
|
||||||
|
|
||||||
futureOp = simulation.FutureOperation{
|
futureOp = simulation.FutureOperation{
|
||||||
BlockHeight: int(executionBlock),
|
BlockHeight: int(executionBlock),
|
||||||
Op: operationClaimAtomicSwap(ak, k, swapID, randomNumber),
|
Op: operationClaimAtomicSwap(ak, k, swapID, randomNumber),
|
||||||
@ -188,13 +206,51 @@ func operationClaimAtomicSwap(ak types.AccountKeeper, k keeper.Keeper, swapID []
|
|||||||
simAccount, _ := simulation.RandomAcc(r, accs)
|
simAccount, _ := simulation.RandomAcc(r, accs)
|
||||||
acc := ak.GetAccount(ctx, simAccount.Address)
|
acc := ak.GetAccount(ctx, simAccount.Address)
|
||||||
|
|
||||||
msg := types.NewMsgClaimAtomicSwap(acc.GetAddress(), swapID, randomNumber)
|
swap, found := k.GetAtomicSwap(ctx, swapID)
|
||||||
|
if !found {
|
||||||
|
return simulation.NoOpMsg(types.ModuleName), nil, fmt.Errorf("cannot claim: swap with ID %s not found", swapID)
|
||||||
|
}
|
||||||
|
// check that asset supply supports claiming (it could have changed due to a param change proposal)
|
||||||
|
// use CacheContext so changes don't take effect
|
||||||
|
cacheCtx, _ := ctx.CacheContext()
|
||||||
|
switch swap.Direction {
|
||||||
|
case types.Incoming:
|
||||||
|
err := k.DecrementIncomingAssetSupply(cacheCtx, swap.Amount[0])
|
||||||
|
if err != nil {
|
||||||
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (could not claim - unable to decrement incoming asset supply %s)", swap.Amount[0].Denom), "", false, nil), nil, nil
|
||||||
|
}
|
||||||
|
err = k.IncrementCurrentAssetSupply(cacheCtx, swap.Amount[0])
|
||||||
|
if err != nil {
|
||||||
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (could not claim - unable to increment current asset supply %s)", swap.Amount[0].Denom), "", false, nil), nil, nil
|
||||||
|
}
|
||||||
|
case types.Outgoing:
|
||||||
|
err := k.DecrementOutgoingAssetSupply(cacheCtx, swap.Amount[0])
|
||||||
|
if err != nil {
|
||||||
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (could not claim - unable to decrement outgoing asset supply %s)", swap.Amount[0].Denom), "", false, nil), nil, nil
|
||||||
|
}
|
||||||
|
err = k.DecrementCurrentAssetSupply(cacheCtx, swap.Amount[0])
|
||||||
|
if err != nil {
|
||||||
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (could not claim - unable to decrement current asset supply %s)", swap.Amount[0].Denom), "", false, nil), nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
asset, err := k.GetAsset(ctx, swap.Amount[0].Denom)
|
||||||
|
if err != nil {
|
||||||
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (could not claim - asset not found %s)", swap.Amount[0].Denom), "", false, nil), nil, nil
|
||||||
|
}
|
||||||
|
supply, found := k.GetAssetSupply(ctx, asset.Denom)
|
||||||
|
if !found {
|
||||||
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (could not claim - asset supply not found %s)", swap.Amount[0].Denom), "", false, nil), nil, nil
|
||||||
|
}
|
||||||
|
if asset.SupplyLimit.LT(supply.CurrentSupply.Amount.Add(swap.Amount[0].Amount)) {
|
||||||
|
return simulation.NoOpMsg(types.ModuleName), nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := types.NewMsgClaimAtomicSwap(acc.GetAddress(), swapID, randomNumber)
|
||||||
fees, err := simulation.RandomFees(r, ctx, acc.SpendableCoins(ctx.BlockTime()))
|
fees, err := simulation.RandomFees(r, ctx, acc.SpendableCoins(ctx.BlockTime()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return simulation.NoOpMsg(types.ModuleName), nil, err
|
return simulation.NoOpMsg(types.ModuleName), nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := helpers.GenTx(
|
tx := helpers.GenTx(
|
||||||
[]sdk.Msg{msg},
|
[]sdk.Msg{msg},
|
||||||
fees,
|
fees,
|
||||||
@ -204,12 +260,10 @@ func operationClaimAtomicSwap(ak types.AccountKeeper, k keeper.Keeper, swapID []
|
|||||||
[]uint64{acc.GetSequence()},
|
[]uint64{acc.GetSequence()},
|
||||||
simAccount.PrivKey,
|
simAccount.PrivKey,
|
||||||
)
|
)
|
||||||
|
|
||||||
_, result, err := app.Deliver(tx)
|
_, result, err := app.Deliver(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return simulation.NoOpMsg(types.ModuleName), nil, err
|
return simulation.NoOpMsg(types.ModuleName), nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return simulation.NewOperationMsg(msg, true, result.Log), nil, nil
|
return simulation.NewOperationMsg(msg, true, result.Log), nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,6 +275,22 @@ func operationRefundAtomicSwap(ak types.AccountKeeper, k keeper.Keeper, swapID [
|
|||||||
simAccount, _ := simulation.RandomAcc(r, accs)
|
simAccount, _ := simulation.RandomAcc(r, accs)
|
||||||
acc := ak.GetAccount(ctx, simAccount.Address)
|
acc := ak.GetAccount(ctx, simAccount.Address)
|
||||||
|
|
||||||
|
swap, found := k.GetAtomicSwap(ctx, swapID)
|
||||||
|
if !found {
|
||||||
|
return simulation.NoOpMsg(types.ModuleName), nil, fmt.Errorf("cannot refund: swap with ID %s not found", swapID)
|
||||||
|
}
|
||||||
|
cacheCtx, _ := ctx.CacheContext()
|
||||||
|
switch swap.Direction {
|
||||||
|
case types.Incoming:
|
||||||
|
if err := k.DecrementIncomingAssetSupply(cacheCtx, swap.Amount[0]); err != nil {
|
||||||
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (could not refund - unable to decrement incoming asset supply %s)", swap.Amount[0].Denom), "", false, nil), nil, nil
|
||||||
|
}
|
||||||
|
case types.Outgoing:
|
||||||
|
if err := k.DecrementOutgoingAssetSupply(cacheCtx, swap.Amount[0]); err != nil {
|
||||||
|
return simulation.NewOperationMsgBasic(types.ModuleName, fmt.Sprintf("no-operation (could not refund - unable to decrement outgoing asset supply %s)", swap.Amount[0].Denom), "", false, nil), nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
msg := types.NewMsgRefundAtomicSwap(acc.GetAddress(), swapID)
|
msg := types.NewMsgRefundAtomicSwap(acc.GetAddress(), swapID)
|
||||||
|
|
||||||
fees, err := simulation.RandomFees(r, ctx, acc.SpendableCoins(ctx.BlockTime()))
|
fees, err := simulation.RandomFees(r, ctx, acc.SpendableCoins(ctx.BlockTime()))
|
||||||
@ -242,20 +312,19 @@ func operationRefundAtomicSwap(ak types.AccountKeeper, k keeper.Keeper, swapID [
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return simulation.NoOpMsg(types.ModuleName), nil, err
|
return simulation.NoOpMsg(types.ModuleName), nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return simulation.NewOperationMsg(msg, true, result.Log), nil, nil
|
return simulation.NewOperationMsg(msg, true, result.Log), nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// findValidAccountAssetSupplyPair finds an account for which the callback func returns true
|
// findValidAccountAssetSupplyPair finds an account for which the callback func returns true
|
||||||
func findValidAccountAssetSupplyPair(accounts []simulation.Account, supplies types.AssetSupplies,
|
func findValidAccountAssetPair(accounts []simulation.Account, assets types.AssetParams,
|
||||||
cb func(simulation.Account, types.AssetSupply) bool) (simulation.Account, types.AssetSupply, bool) {
|
cb func(simulation.Account, types.AssetParam) bool) (simulation.Account, types.AssetParam, bool) {
|
||||||
for _, supply := range supplies {
|
for _, asset := range assets {
|
||||||
for _, acc := range accounts {
|
for _, acc := range accounts {
|
||||||
if isValid := cb(acc, supply); isValid {
|
if isValid := cb(acc, asset); isValid {
|
||||||
return acc, supply, true
|
return acc, asset, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return simulation.Account{}, types.AssetSupply{}, false
|
return simulation.Account{}, types.AssetParam{}, false
|
||||||
}
|
}
|
||||||
|
@ -10,55 +10,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
keyBnbDeputyAddress = "BnbDeputyAddress"
|
keyAssetParams = "AssetParams"
|
||||||
keyBnbDeputyFixedFee = "BnbDeputyFixedFee"
|
|
||||||
keyMinAmount = "MinAmount"
|
|
||||||
keyMaxAmount = "MaxAmount"
|
|
||||||
keyMinBlockLock = "MinBlockLock"
|
|
||||||
keyMaxBlockLock = "MaxBlockLock"
|
|
||||||
keySupportedAssets = "SupportedAssets"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParamChanges defines the parameters that can be modified by param change proposals
|
// ParamChanges defines the parameters that can be modified by param change proposals
|
||||||
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
|
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
|
||||||
// We generate MinBlockLock first because the result is required by GenMaxBlockLock()
|
|
||||||
minBlockLockVal := GenMinBlockLock(r)
|
|
||||||
minAmount := GenMinAmount(r)
|
|
||||||
|
|
||||||
return []simulation.ParamChange{
|
return []simulation.ParamChange{
|
||||||
simulation.NewSimParamChange(types.ModuleName, keyBnbDeputyAddress,
|
simulation.NewSimParamChange(types.ModuleName, keyAssetParams,
|
||||||
func(r *rand.Rand) string {
|
func(r *rand.Rand) string {
|
||||||
return fmt.Sprintf("\"%s\"", GenRandBnbDeputy(r).Address)
|
return fmt.Sprintf("\"%s\"", GenSupportedAssets(r))
|
||||||
},
|
|
||||||
),
|
|
||||||
simulation.NewSimParamChange(types.ModuleName, keyBnbDeputyFixedFee,
|
|
||||||
func(r *rand.Rand) string {
|
|
||||||
return fmt.Sprintf("\"%s\"", GenRandBnbDeputyFixedFee(r).String())
|
|
||||||
},
|
|
||||||
),
|
|
||||||
simulation.NewSimParamChange(types.ModuleName, keyMinAmount,
|
|
||||||
func(r *rand.Rand) string {
|
|
||||||
return fmt.Sprintf("\"%s\"", minAmount.String())
|
|
||||||
},
|
|
||||||
),
|
|
||||||
simulation.NewSimParamChange(types.ModuleName, keyMaxAmount,
|
|
||||||
func(r *rand.Rand) string {
|
|
||||||
return fmt.Sprintf("\"%s\"", GenMaxAmount(r, minAmount).String())
|
|
||||||
},
|
|
||||||
),
|
|
||||||
simulation.NewSimParamChange(types.ModuleName, keyMinBlockLock,
|
|
||||||
func(r *rand.Rand) string {
|
|
||||||
return fmt.Sprintf("\"%d\"", minBlockLockVal)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
simulation.NewSimParamChange(types.ModuleName, keyMaxBlockLock,
|
|
||||||
func(r *rand.Rand) string {
|
|
||||||
return fmt.Sprintf("\"%d\"", GenMaxBlockLock(r, minBlockLockVal))
|
|
||||||
},
|
|
||||||
),
|
|
||||||
simulation.NewSimParamChange(types.ModuleName, keySupportedAssets,
|
|
||||||
func(r *rand.Rand) string {
|
|
||||||
return fmt.Sprintf("\"%v\"", GenSupportedAssets(r))
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ var (
|
|||||||
// ErrInsufficientAmount error for when a swap's amount cannot cover the deputy's fixed fee
|
// ErrInsufficientAmount error for when a swap's amount cannot cover the deputy's fixed fee
|
||||||
ErrInsufficientAmount = sdkerrors.Register(ModuleName, 4, "amount cannot cover the deputy fixed fee")
|
ErrInsufficientAmount = sdkerrors.Register(ModuleName, 4, "amount cannot cover the deputy fixed fee")
|
||||||
// ErrAssetNotSupported error for when an asset is not supported
|
// ErrAssetNotSupported error for when an asset is not supported
|
||||||
ErrAssetNotSupported = sdkerrors.Register(ModuleName, 5, "asset not on the list of supported assets")
|
ErrAssetNotSupported = sdkerrors.Register(ModuleName, 5, "asset not found")
|
||||||
// ErrAssetNotActive error for when an asset is currently inactive
|
// ErrAssetNotActive error for when an asset is currently inactive
|
||||||
ErrAssetNotActive = sdkerrors.Register(ModuleName, 6, "asset is currently inactive")
|
ErrAssetNotActive = sdkerrors.Register(ModuleName, 6, "asset is currently inactive")
|
||||||
// ErrAssetSupplyNotFound error for when an asset's supply is not found in the store
|
// ErrAssetSupplyNotFound error for when an asset's supply is not found in the store
|
||||||
@ -41,6 +41,6 @@ var (
|
|||||||
ErrSwapNotClaimable = sdkerrors.Register(ModuleName, 17, "atomic swap is not claimable")
|
ErrSwapNotClaimable = sdkerrors.Register(ModuleName, 17, "atomic swap is not claimable")
|
||||||
// ErrInvalidAmount error for when a swap's amount is outside acceptable range
|
// ErrInvalidAmount error for when a swap's amount is outside acceptable range
|
||||||
ErrInvalidAmount = sdkerrors.Register(ModuleName, 18, "amount is outside acceptable range")
|
ErrInvalidAmount = sdkerrors.Register(ModuleName, 18, "amount is outside acceptable range")
|
||||||
// ErrInvalidOutgoingAccount error for when an outgoing swap has a recipient value that is not the deputy address
|
// ErrInvalidSwapAccount error for when a swap involves an invalid account
|
||||||
ErrInvalidOutgoingAccount = sdkerrors.Register(ModuleName, 19, "invalid recipient address for outgoing swap")
|
ErrInvalidSwapAccount = sdkerrors.Register(ModuleName, 19, "atomic swap has invalid account")
|
||||||
)
|
)
|
||||||
|
@ -8,17 +8,17 @@ import (
|
|||||||
|
|
||||||
// GenesisState - all bep3 state that must be provided at genesis
|
// GenesisState - all bep3 state that must be provided at genesis
|
||||||
type GenesisState struct {
|
type GenesisState struct {
|
||||||
Params Params `json:"params" yaml:"params"`
|
Params Params `json:"params" yaml:"params"`
|
||||||
AtomicSwaps AtomicSwaps `json:"atomic_swaps" yaml:"atomic_swaps"`
|
AtomicSwaps AtomicSwaps `json:"atomic_swaps" yaml:"atomic_swaps"`
|
||||||
AssetSupplies AssetSupplies `json:"assets_supplies" yaml:"assets_supplies"`
|
Supplies AssetSupplies `json:"supplies" yaml:"supplies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGenesisState creates a new GenesisState object
|
// NewGenesisState creates a new GenesisState object
|
||||||
func NewGenesisState(params Params, swaps AtomicSwaps, supplies AssetSupplies) GenesisState {
|
func NewGenesisState(params Params, swaps AtomicSwaps, supplies AssetSupplies) GenesisState {
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
Params: params,
|
Params: params,
|
||||||
AtomicSwaps: swaps,
|
AtomicSwaps: swaps,
|
||||||
AssetSupplies: supplies,
|
Supplies: supplies,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,19 +49,6 @@ func (gs GenesisState) Validate() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
denoms := map[string]bool{}
|
|
||||||
for _, asset := range gs.AssetSupplies {
|
|
||||||
if denoms[asset.Denom] {
|
|
||||||
return fmt.Errorf("found duplicate asset denom %s", asset.Denom)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := asset.Validate(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
denoms[asset.Denom] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
ids := map[string]bool{}
|
ids := map[string]bool{}
|
||||||
for _, swap := range gs.AtomicSwaps {
|
for _, swap := range gs.AtomicSwaps {
|
||||||
if ids[hex.EncodeToString(swap.GetSwapID())] {
|
if ids[hex.EncodeToString(swap.GetSwapID())] {
|
||||||
@ -74,5 +61,16 @@ func (gs GenesisState) Validate() error {
|
|||||||
|
|
||||||
ids[hex.EncodeToString(swap.GetSwapID())] = true
|
ids[hex.EncodeToString(swap.GetSwapID())] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supplyDenoms := map[string]bool{}
|
||||||
|
for _, supply := range gs.Supplies {
|
||||||
|
if err := supply.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if supplyDenoms[supply.GetDenom()] {
|
||||||
|
return fmt.Errorf("found duplicate denom in asset supplies %s", supply.GetDenom())
|
||||||
|
}
|
||||||
|
supplyDenoms[supply.GetDenom()] = true
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,13 @@ func (suite *GenesisTestSuite) SetupTest() {
|
|||||||
coin := sdk.NewCoin("kava", sdk.OneInt())
|
coin := sdk.NewCoin("kava", sdk.OneInt())
|
||||||
suite.swaps = atomicSwaps(10)
|
suite.swaps = atomicSwaps(10)
|
||||||
|
|
||||||
supply := types.NewAssetSupply("kava", coin, coin, coin, coin)
|
supply := types.NewAssetSupply(coin, coin, coin)
|
||||||
suite.supplies = types.AssetSupplies{supply}
|
suite.supplies = types.AssetSupplies{supply}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *GenesisTestSuite) TestValidate() {
|
func (suite *GenesisTestSuite) TestValidate() {
|
||||||
type args struct {
|
type args struct {
|
||||||
swaps types.AtomicSwaps
|
swaps types.AtomicSwaps
|
||||||
supplies types.AssetSupplies
|
|
||||||
}
|
}
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -41,74 +40,50 @@ func (suite *GenesisTestSuite) TestValidate() {
|
|||||||
{
|
{
|
||||||
"default",
|
"default",
|
||||||
args{
|
args{
|
||||||
swaps: types.AtomicSwaps{},
|
swaps: types.AtomicSwaps{},
|
||||||
supplies: types.AssetSupplies{},
|
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"with swaps",
|
"with swaps",
|
||||||
args{
|
args{
|
||||||
swaps: suite.swaps,
|
swaps: suite.swaps,
|
||||||
supplies: types.AssetSupplies{},
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"with supplies",
|
|
||||||
args{
|
|
||||||
swaps: types.AtomicSwaps{},
|
|
||||||
supplies: suite.supplies,
|
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"duplicate swaps",
|
"duplicate swaps",
|
||||||
args{
|
args{
|
||||||
swaps: types.AtomicSwaps{suite.swaps[2], suite.swaps[2]},
|
swaps: types.AtomicSwaps{suite.swaps[2], suite.swaps[2]},
|
||||||
supplies: types.AssetSupplies{},
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid swap",
|
"invalid swap",
|
||||||
args{
|
args{
|
||||||
swaps: types.AtomicSwaps{types.AtomicSwap{Amount: sdk.Coins{sdk.Coin{Denom: "Invalid Denom", Amount: sdk.NewInt(-1)}}}},
|
swaps: types.AtomicSwaps{types.AtomicSwap{Amount: sdk.Coins{sdk.Coin{Denom: "Invalid Denom", Amount: sdk.NewInt(-1)}}}},
|
||||||
supplies: types.AssetSupplies{},
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
"invalid supply",
|
|
||||||
args{
|
|
||||||
swaps: types.AtomicSwaps{},
|
|
||||||
supplies: types.AssetSupplies{types.AssetSupply{Denom: "Invalid Denom"}},
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"duplicate supplies",
|
|
||||||
args{
|
|
||||||
swaps: types.AtomicSwaps{},
|
|
||||||
supplies: types.AssetSupplies{suite.supplies[0], suite.supplies[0]},
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
}}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
var gs types.GenesisState
|
suite.Run(tc.name, func() {
|
||||||
if tc.name == "default" {
|
var gs types.GenesisState
|
||||||
gs = types.DefaultGenesisState()
|
if tc.name == "default" {
|
||||||
} else {
|
gs = types.DefaultGenesisState()
|
||||||
gs = types.NewGenesisState(types.DefaultParams(), tc.args.swaps, tc.args.supplies)
|
} else {
|
||||||
}
|
gs = types.NewGenesisState(types.DefaultParams(), tc.args.swaps, suite.supplies)
|
||||||
|
}
|
||||||
|
|
||||||
err := gs.Validate()
|
err := gs.Validate()
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
suite.Require().NoError(err, tc.name)
|
suite.Require().NoError(err, tc.name)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err, tc.name)
|
suite.Require().Error(err, tc.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,13 +26,10 @@ const (
|
|||||||
|
|
||||||
// Key prefixes
|
// Key prefixes
|
||||||
var (
|
var (
|
||||||
// SupplyLimitUpgradeTime is the block time after which the asset supply limits are updated from params
|
|
||||||
SupplyLimitUpgradeTime time.Time = time.Date(2020, 7, 10, 14, 0, 0, 0, time.UTC)
|
|
||||||
|
|
||||||
AtomicSwapKeyPrefix = []byte{0x00} // prefix for keys that store AtomicSwaps
|
AtomicSwapKeyPrefix = []byte{0x00} // prefix for keys that store AtomicSwaps
|
||||||
AtomicSwapByBlockPrefix = []byte{0x01} // prefix for keys of the AtomicSwapsByBlock index
|
AtomicSwapByBlockPrefix = []byte{0x01} // prefix for keys of the AtomicSwapsByBlock index
|
||||||
AssetSupplyKeyPrefix = []byte{0x02} // prefix for keys that store global asset supply counts
|
AtomicSwapLongtermStoragePrefix = []byte{0x02} // prefix for keys of the AtomicSwapLongtermStorage index
|
||||||
AtomicSwapLongtermStoragePrefix = []byte{0x03} // prefix for keys of the AtomicSwapLongtermStorage index
|
AssetSupplyPrefix = []byte{0x03}
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetAtomicSwapByHeightKey is used by the AtomicSwapByBlock index and AtomicSwapLongtermStorage index
|
// GetAtomicSwapByHeightKey is used by the AtomicSwapByBlock index and AtomicSwapLongtermStorage index
|
||||||
|
@ -1,100 +1,80 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/params"
|
"github.com/cosmos/cosmos-sdk/x/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
bech32MainPrefix = "kava"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Parameter keys
|
// Parameter keys
|
||||||
var (
|
var (
|
||||||
KeyBnbDeputyAddress = []byte("BnbDeputyAddress")
|
KeyAssetParams = []byte("AssetParams")
|
||||||
KeyBnbDeputyFixedFee = []byte("BnbDeputyFixedFee")
|
|
||||||
KeyMinAmount = []byte("MinAmount")
|
|
||||||
KeyMaxAmount = []byte("MaxAmount")
|
|
||||||
KeyMinBlockLock = []byte("MinBlockLock")
|
|
||||||
KeyMaxBlockLock = []byte("MaxBlockLock")
|
|
||||||
KeySupportedAssets = []byte("SupportedAssets")
|
|
||||||
|
|
||||||
DefaultBnbDeputyFixedFee sdk.Int = sdk.NewInt(1000) // 0.00001 BNB
|
DefaultBnbDeputyFixedFee sdk.Int = sdk.NewInt(1000) // 0.00001 BNB
|
||||||
DefaultMinAmount sdk.Int = sdk.ZeroInt()
|
DefaultMinAmount sdk.Int = sdk.ZeroInt()
|
||||||
DefaultMaxAmount sdk.Int = sdk.NewInt(1000000000000) // 10,000 BNB
|
DefaultMaxAmount sdk.Int = sdk.NewInt(1000000000000) // 10,000 BNB
|
||||||
DefaultMinBlockLock uint64 = 220
|
DefaultMinBlockLock uint64 = 220
|
||||||
DefaultMaxBlockLock uint64 = 270
|
DefaultMaxBlockLock uint64 = 270
|
||||||
DefaultSupportedAssets = AssetParams{
|
|
||||||
AssetParam{
|
|
||||||
Denom: "bnb",
|
|
||||||
CoinID: 714,
|
|
||||||
Limit: sdk.NewInt(350000000000000), // 3,500,000 BNB
|
|
||||||
Active: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Params governance parameters for bep3 module
|
// Params governance parameters for bep3 module
|
||||||
type Params struct {
|
type Params struct {
|
||||||
BnbDeputyAddress sdk.AccAddress `json:"bnb_deputy_address" yaml:"bnb_deputy_address"` // Bnbchain deputy address
|
AssetParams AssetParams `json:"asset_params" yaml:"asset_params"`
|
||||||
BnbDeputyFixedFee sdk.Int `json:"bnb_deputy_fixed_fee" yaml:"bnb_deputy_fixed_fee"` // Deputy fixed fee in BNB
|
|
||||||
MinAmount sdk.Int `json:"min_amount" yaml:"min_amount"` // Minimum swap amount
|
|
||||||
MaxAmount sdk.Int `json:"max_amount" yaml:"max_amount"` // Maximum swap amount
|
|
||||||
MinBlockLock uint64 `json:"min_block_lock" yaml:"min_block_lock"` // Minimum swap block lock
|
|
||||||
MaxBlockLock uint64 `json:"max_block_lock" yaml:"max_block_lock"` // Maximum swap block lock
|
|
||||||
SupportedAssets AssetParams `json:"supported_assets" yaml:"supported_assets"` // Supported assets
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements fmt.Stringer
|
// String implements fmt.Stringer
|
||||||
func (p Params) String() string {
|
func (p Params) String() string {
|
||||||
return fmt.Sprintf(`Params:
|
return fmt.Sprintf(`Params:
|
||||||
Bnbchain deputy address: %s,
|
AssetParams: %s`,
|
||||||
Deputy fixed fee (BNB): %d,
|
p.AssetParams)
|
||||||
Min amount: %d,
|
|
||||||
Max amount: %d,
|
|
||||||
Min block lock: %d,
|
|
||||||
Max block lock: %d,
|
|
||||||
Supported assets: %s`,
|
|
||||||
p.BnbDeputyAddress.String(), p.BnbDeputyFixedFee, p.MinAmount,
|
|
||||||
p.MaxAmount, p.MinBlockLock, p.MaxBlockLock, p.SupportedAssets)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewParams returns a new params object
|
// NewParams returns a new params object
|
||||||
func NewParams(bnbDeputyAddress sdk.AccAddress, bnbDeputyFixedFee, minAmount,
|
func NewParams(ap AssetParams,
|
||||||
maxAmount sdk.Int, minBlockLock, maxBlockLock uint64, supportedAssets AssetParams,
|
|
||||||
) Params {
|
) Params {
|
||||||
return Params{
|
return Params{
|
||||||
BnbDeputyAddress: bnbDeputyAddress,
|
AssetParams: ap,
|
||||||
BnbDeputyFixedFee: bnbDeputyFixedFee,
|
|
||||||
MinAmount: minAmount,
|
|
||||||
MaxAmount: maxAmount,
|
|
||||||
MinBlockLock: minBlockLock,
|
|
||||||
MaxBlockLock: maxBlockLock,
|
|
||||||
SupportedAssets: supportedAssets,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultParams returns default params for bep3 module
|
// DefaultParams returns default params for bep3 module
|
||||||
func DefaultParams() Params {
|
func DefaultParams() Params {
|
||||||
defaultBnbDeputyAddress, err := sdk.AccAddressFromBech32("kava1r4v2zdhdalfj2ydazallqvrus9fkphmglhn6u6")
|
return NewParams(AssetParams{})
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewParams(defaultBnbDeputyAddress, DefaultBnbDeputyFixedFee, DefaultMinAmount,
|
|
||||||
DefaultMaxAmount, DefaultMinBlockLock, DefaultMaxBlockLock, DefaultSupportedAssets)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetParam governance parameters for each asset within a supported chain
|
// AssetParam parameters that must be specified for each bep3 asset
|
||||||
type AssetParam struct {
|
type AssetParam struct {
|
||||||
Denom string `json:"denom" yaml:"denom"` // name of the asset
|
Denom string `json:"denom" yaml:"denom"` // name of the asset
|
||||||
CoinID int `json:"coin_id" yaml:"coin_id"` // internationally recognized coin ID
|
CoinID int `json:"coin_id" yaml:"coin_id"` // SLIP-0044 registered coin type - see https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||||
Limit sdk.Int `json:"limit" yaml:"limit"` // asset supply limit
|
SupplyLimit sdk.Int `json:"supply_limit" yaml:"supply_limit"` // asset supply limit
|
||||||
Active bool `json:"active" yaml:"active"` // denotes if asset is available or paused
|
Active bool `json:"active" yaml:"active"` // denotes if asset is available or paused
|
||||||
|
DeputyAddress sdk.AccAddress `json:"deputy_address" yaml:"deputy_address"` // the address of the relayer process
|
||||||
|
FixedFee sdk.Int `json:"fixed_fee" yaml:"fixed_fee"` // the fixed fee charged by the relayer process for outgoing swaps
|
||||||
|
MinSwapAmount sdk.Int `json:"min_swap_amount" yaml:"min_swap_amount"` // Minimum swap amount
|
||||||
|
MaxSwapAmount sdk.Int `json:"max_swap_amount" yaml:"max_swap_amount"` // Maximum swap amount
|
||||||
|
MinBlockLock uint64 `json:"min_block_lock" yaml:"min_block_lock"` // Minimum swap block lock
|
||||||
|
MaxBlockLock uint64 `json:"max_block_lock" yaml:"max_block_lock"` // Maximum swap block lock
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAssetParam returns a new AssetParam
|
||||||
|
func NewAssetParam(
|
||||||
|
denom string, coinID int, limit sdk.Int, active bool,
|
||||||
|
deputyAddr sdk.AccAddress, fixedFee sdk.Int, minSwapAmount sdk.Int,
|
||||||
|
maxSwapAmount sdk.Int, minBlockLock uint64, maxBlockLock uint64,
|
||||||
|
) AssetParam {
|
||||||
|
return AssetParam{
|
||||||
|
Denom: denom,
|
||||||
|
CoinID: coinID,
|
||||||
|
SupplyLimit: limit,
|
||||||
|
Active: active,
|
||||||
|
DeputyAddress: deputyAddr,
|
||||||
|
FixedFee: fixedFee,
|
||||||
|
MinSwapAmount: minSwapAmount,
|
||||||
|
MaxSwapAmount: maxSwapAmount,
|
||||||
|
MinBlockLock: minBlockLock,
|
||||||
|
MaxBlockLock: maxBlockLock,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements fmt.Stringer
|
// String implements fmt.Stringer
|
||||||
@ -103,8 +83,15 @@ func (ap AssetParam) String() string {
|
|||||||
Denom: %s
|
Denom: %s
|
||||||
Coin ID: %d
|
Coin ID: %d
|
||||||
Limit: %s
|
Limit: %s
|
||||||
Active: %t`,
|
Active: %t
|
||||||
ap.Denom, ap.CoinID, ap.Limit.String(), ap.Active)
|
Deputy Address: %s
|
||||||
|
Fixed Fee: %s
|
||||||
|
Min Swap Amount: %s
|
||||||
|
Max Swap Amount: %s
|
||||||
|
Min Block Lock: %d
|
||||||
|
Max Block Lock: %d`,
|
||||||
|
ap.Denom, ap.CoinID, ap.SupplyLimit, ap.Active, ap.DeputyAddress, ap.FixedFee,
|
||||||
|
ap.MinSwapAmount, ap.MaxSwapAmount, ap.MinBlockLock, ap.MaxBlockLock)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetParams array of AssetParam
|
// AssetParams array of AssetParam
|
||||||
@ -129,149 +116,69 @@ func ParamKeyTable() params.KeyTable {
|
|||||||
// nolint
|
// nolint
|
||||||
func (p *Params) ParamSetPairs() params.ParamSetPairs {
|
func (p *Params) ParamSetPairs() params.ParamSetPairs {
|
||||||
return params.ParamSetPairs{
|
return params.ParamSetPairs{
|
||||||
params.NewParamSetPair(KeyBnbDeputyAddress, &p.BnbDeputyAddress, validateBnbDeputyAddressParam),
|
params.NewParamSetPair(KeyAssetParams, &p.AssetParams, validateAssetParams),
|
||||||
params.NewParamSetPair(KeyBnbDeputyFixedFee, &p.BnbDeputyFixedFee, validateBnbDeputyFixedFeeParam),
|
|
||||||
params.NewParamSetPair(KeyMinAmount, &p.MinAmount, validateMinAmountParam),
|
|
||||||
params.NewParamSetPair(KeyMaxAmount, &p.MaxAmount, validateMaxAmountParam),
|
|
||||||
params.NewParamSetPair(KeyMinBlockLock, &p.MinBlockLock, validateMinBlockLockParam),
|
|
||||||
params.NewParamSetPair(KeyMaxBlockLock, &p.MaxBlockLock, validateMaxBlockLockParam),
|
|
||||||
params.NewParamSetPair(KeySupportedAssets, &p.SupportedAssets, validateSupportedAssetsParams),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate ensure that params have valid values
|
// Validate ensure that params have valid values
|
||||||
func (p Params) Validate() error {
|
func (p Params) Validate() error {
|
||||||
if err := validateBnbDeputyAddressParam(p.BnbDeputyAddress); err != nil {
|
return validateAssetParams(p.AssetParams)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateBnbDeputyFixedFeeParam(p.BnbDeputyFixedFee); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateMinAmountParam(p.MinAmount); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateMaxAmountParam(p.MaxAmount); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.MinAmount.GT(p.MaxAmount) {
|
|
||||||
return fmt.Errorf("minimum amount cannot be > maximum amount, got %d > %d", p.MinAmount, p.MaxAmount)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateMinBlockLockParam(p.MinBlockLock); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateMaxBlockLockParam(p.MaxBlockLock); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.MinBlockLock > p.MaxBlockLock {
|
|
||||||
return fmt.Errorf("minimum block lock cannot be > maximum block lock, got %d > %d", p.MinBlockLock, p.MaxBlockLock)
|
|
||||||
}
|
|
||||||
|
|
||||||
return validateSupportedAssetsParams(p.SupportedAssets)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateBnbDeputyAddressParam(i interface{}) error {
|
func validateAssetParams(i interface{}) error {
|
||||||
addr, ok := i.(sdk.AccAddress)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("invalid parameter type: %T", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
if addr.Empty() {
|
|
||||||
return errors.New("bnb deputy address cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(addr.Bytes()) != sdk.AddrLen {
|
|
||||||
return fmt.Errorf("bnb deputy address invalid bytes length got %d, want %d", len(addr.Bytes()), sdk.AddrLen)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateBnbDeputyFixedFeeParam(i interface{}) error {
|
|
||||||
_, ok := i.(sdk.Int)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("invalid parameter type: %T", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateMinAmountParam(i interface{}) error {
|
|
||||||
_, ok := i.(sdk.Int)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("invalid parameter type: %T", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateMaxAmountParam(i interface{}) error {
|
|
||||||
_, ok := i.(sdk.Int)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("invalid parameter type: %T", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateMinBlockLockParam(i interface{}) error {
|
|
||||||
_, ok := i.(uint64)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("invalid parameter type: %T", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateMaxBlockLockParam(i interface{}) error {
|
|
||||||
_, ok := i.(uint64)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("invalid parameter type: %T", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateSupportedAssetsParams(i interface{}) error {
|
|
||||||
assetParams, ok := i.(AssetParams)
|
assetParams, ok := i.(AssetParams)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid parameter type: %T", i)
|
return fmt.Errorf("invalid parameter type: %T", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
coinIDs := make(map[int]bool)
|
|
||||||
coinDenoms := make(map[string]bool)
|
coinDenoms := make(map[string]bool)
|
||||||
for _, asset := range assetParams {
|
for _, asset := range assetParams {
|
||||||
if strings.TrimSpace(asset.Denom) == "" {
|
if err := sdk.ValidateDenom(asset.Denom); err != nil {
|
||||||
return errors.New("asset denom cannot be empty")
|
return fmt.Errorf("asset denom invalid: %s", asset.Denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
if asset.CoinID < 0 {
|
if asset.CoinID < 0 {
|
||||||
return fmt.Errorf(fmt.Sprintf("asset %s must be a non negative integer", asset.Denom))
|
return fmt.Errorf("asset %s coin id must be a non negative integer", asset.Denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !asset.Limit.IsPositive() {
|
if asset.SupplyLimit.IsNegative() {
|
||||||
return fmt.Errorf(fmt.Sprintf("asset %s must have a positive supply limit", asset.Denom))
|
return fmt.Errorf("asset %s has invalid (negative) supply limit: %s", asset.Denom, asset.SupplyLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, found := coinDenoms[asset.Denom]
|
_, found := coinDenoms[asset.Denom]
|
||||||
if found {
|
if found {
|
||||||
return fmt.Errorf(fmt.Sprintf("asset %s cannot have duplicate denom", asset.Denom))
|
return fmt.Errorf("asset %s cannot have duplicate denom", asset.Denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
coinDenoms[asset.Denom] = true
|
coinDenoms[asset.Denom] = true
|
||||||
|
|
||||||
_, found = coinIDs[asset.CoinID]
|
if asset.DeputyAddress.Empty() {
|
||||||
if found {
|
return fmt.Errorf("deputy address cannot be empty for %s", asset.Denom)
|
||||||
return fmt.Errorf(fmt.Sprintf("asset %s cannot have duplicate coin id %d", asset.Denom, asset.CoinID))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coinIDs[asset.CoinID] = true
|
if len(asset.DeputyAddress.Bytes()) != sdk.AddrLen {
|
||||||
|
return fmt.Errorf("%s deputy address invalid bytes length got %d, want %d", asset.Denom, len(asset.DeputyAddress.Bytes()), sdk.AddrLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
if asset.FixedFee.IsNegative() {
|
||||||
|
return fmt.Errorf("asset %s cannot have a negative fixed fee %s", asset.Denom, asset.FixedFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
if asset.MinBlockLock > asset.MaxBlockLock {
|
||||||
|
return fmt.Errorf("asset %s has minimum block lock > maximum block lock %d > %d", asset.Denom, asset.MinBlockLock, asset.MaxBlockLock)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !asset.MinSwapAmount.IsPositive() {
|
||||||
|
return fmt.Errorf("asset %s must have a positive minimum swap amount, got %s", asset.Denom, asset.MinSwapAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !asset.MaxSwapAmount.IsPositive() {
|
||||||
|
return fmt.Errorf("asset %s must have a positive maximum swap amount, got %s", asset.Denom, asset.MaxSwapAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
if asset.MinSwapAmount.GT(asset.MaxSwapAmount) {
|
||||||
|
return fmt.Errorf("asset %s has minimum swap amount > maximum swap amount %s > %s", asset.Denom, asset.MinSwapAmount, asset.MaxSwapAmount)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -13,7 +13,8 @@ import (
|
|||||||
|
|
||||||
type ParamsTestSuite struct {
|
type ParamsTestSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
addr sdk.AccAddress
|
addr sdk.AccAddress
|
||||||
|
supply []sdk.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) SetupTest() {
|
func (suite *ParamsTestSuite) SetupTest() {
|
||||||
@ -21,20 +22,14 @@ func (suite *ParamsTestSuite) SetupTest() {
|
|||||||
app.SetBech32AddressPrefixes(config)
|
app.SetBech32AddressPrefixes(config)
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
||||||
suite.addr = addrs[0]
|
suite.addr = addrs[0]
|
||||||
|
suite.supply = append(suite.supply, sdk.NewInt(10000000000000), sdk.NewInt(10000000000000))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ParamsTestSuite) TestParamValidation() {
|
func (suite *ParamsTestSuite) TestParamValidation() {
|
||||||
type LoadParams func() types.Params
|
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
bnbDeputyAddress sdk.AccAddress
|
assetParams types.AssetParams
|
||||||
bnbDeputyFixedFee sdk.Int
|
|
||||||
minAmount sdk.Int
|
|
||||||
maxAmount sdk.Int
|
|
||||||
minBlockLock uint64
|
|
||||||
maxBlockLock uint64
|
|
||||||
supportedAssets types.AssetParams
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@ -46,189 +41,168 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
{
|
{
|
||||||
name: "default",
|
name: "default",
|
||||||
args: args{
|
args: args{
|
||||||
bnbDeputyAddress: suite.addr,
|
assetParams: types.AssetParams{},
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
|
||||||
minAmount: types.DefaultMinAmount,
|
|
||||||
maxAmount: types.DefaultMaxAmount,
|
|
||||||
minBlockLock: types.DefaultMinBlockLock,
|
|
||||||
maxBlockLock: types.DefaultMaxBlockLock,
|
|
||||||
supportedAssets: types.DefaultSupportedAssets,
|
|
||||||
},
|
},
|
||||||
expectPass: true,
|
expectPass: true,
|
||||||
expectedErr: "",
|
expectedErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "minimum block lock == maximum block lock",
|
name: "valid single asset",
|
||||||
args: args{
|
args: args{
|
||||||
bnbDeputyAddress: suite.addr,
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
"bnb", 714, suite.supply[0], true,
|
||||||
minAmount: types.DefaultMinAmount,
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
maxAmount: types.DefaultMaxAmount,
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock)},
|
||||||
minBlockLock: 243,
|
|
||||||
maxBlockLock: 243,
|
|
||||||
supportedAssets: types.DefaultSupportedAssets,
|
|
||||||
},
|
},
|
||||||
expectPass: true,
|
expectPass: true,
|
||||||
expectedErr: "",
|
expectedErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "minimum amount greater than maximum amount",
|
name: "valid multi asset",
|
||||||
args: args{
|
args: args{
|
||||||
bnbDeputyAddress: suite.addr,
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
"bnb", 714, suite.supply[0], true,
|
||||||
minAmount: sdk.NewInt(10000000),
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
maxAmount: sdk.NewInt(100000),
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock),
|
||||||
minBlockLock: types.DefaultMinBlockLock,
|
types.NewAssetParam(
|
||||||
maxBlockLock: types.DefaultMaxBlockLock,
|
"btcb", 0, suite.supply[1], true,
|
||||||
supportedAssets: types.DefaultSupportedAssets,
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(10000000), sdk.NewInt(100000000000),
|
||||||
},
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock),
|
||||||
expectPass: false,
|
|
||||||
expectedErr: "minimum amount cannot be > maximum amount",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "minimum block lock greater than maximum block lock",
|
|
||||||
args: args{
|
|
||||||
bnbDeputyAddress: suite.addr,
|
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
|
||||||
minAmount: types.DefaultMinAmount,
|
|
||||||
maxAmount: types.DefaultMaxAmount,
|
|
||||||
minBlockLock: 500,
|
|
||||||
maxBlockLock: 400,
|
|
||||||
supportedAssets: types.DefaultSupportedAssets,
|
|
||||||
},
|
|
||||||
expectPass: false,
|
|
||||||
expectedErr: "minimum block lock cannot be > maximum block lock",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "empty asset denom",
|
|
||||||
args: args{
|
|
||||||
bnbDeputyAddress: suite.addr,
|
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
|
||||||
minAmount: types.DefaultMinAmount,
|
|
||||||
maxAmount: types.DefaultMaxAmount,
|
|
||||||
minBlockLock: types.DefaultMinBlockLock,
|
|
||||||
maxBlockLock: types.DefaultMaxBlockLock,
|
|
||||||
supportedAssets: types.AssetParams{
|
|
||||||
types.AssetParam{
|
|
||||||
Denom: "",
|
|
||||||
CoinID: 714,
|
|
||||||
Limit: sdk.NewInt(100000000000),
|
|
||||||
Active: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectPass: false,
|
expectPass: true,
|
||||||
expectedErr: "asset denom cannot be empty",
|
expectedErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negative asset coin ID",
|
name: "invalid denom - empty",
|
||||||
args: args{
|
args: args{
|
||||||
bnbDeputyAddress: suite.addr,
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
"", 714, suite.supply[0], true,
|
||||||
minAmount: types.DefaultMinAmount,
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
maxAmount: types.DefaultMaxAmount,
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock)},
|
||||||
minBlockLock: types.DefaultMinBlockLock,
|
|
||||||
maxBlockLock: types.DefaultMaxBlockLock,
|
|
||||||
supportedAssets: types.AssetParams{
|
|
||||||
types.AssetParam{
|
|
||||||
Denom: "bnb",
|
|
||||||
CoinID: -1,
|
|
||||||
Limit: sdk.NewInt(100000000000),
|
|
||||||
Active: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
expectedErr: "must be a non negative integer",
|
expectedErr: "denom invalid",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid denom - bad format",
|
||||||
|
args: args{
|
||||||
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
|
"BNB", 714, suite.supply[0], true,
|
||||||
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock)},
|
||||||
|
},
|
||||||
|
expectPass: false,
|
||||||
|
expectedErr: "denom invalid",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "min block lock equal max block lock",
|
||||||
|
args: args{
|
||||||
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
|
"bnb", 714, suite.supply[0], true,
|
||||||
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
|
243, 243)},
|
||||||
|
},
|
||||||
|
expectPass: true,
|
||||||
|
expectedErr: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "min block lock greater max block lock",
|
||||||
|
args: args{
|
||||||
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
|
"bnb", 714, suite.supply[0], true,
|
||||||
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
|
244, 243)},
|
||||||
|
},
|
||||||
|
expectPass: false,
|
||||||
|
expectedErr: "minimum block lock > maximum block lock",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "min swap not positive",
|
||||||
|
args: args{
|
||||||
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
|
"bnb", 714, suite.supply[0], true,
|
||||||
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(0), sdk.NewInt(10000000000),
|
||||||
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock)},
|
||||||
|
},
|
||||||
|
expectPass: false,
|
||||||
|
expectedErr: "must have a positive minimum swap",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "max swap not positive",
|
||||||
|
args: args{
|
||||||
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
|
"bnb", 714, suite.supply[0], true,
|
||||||
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(10000), sdk.NewInt(0),
|
||||||
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock)},
|
||||||
|
},
|
||||||
|
expectPass: false,
|
||||||
|
expectedErr: "must have a positive maximum swap",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "min swap greater max swap",
|
||||||
|
args: args{
|
||||||
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
|
"bnb", 714, suite.supply[0], true,
|
||||||
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000000), sdk.NewInt(10000000000),
|
||||||
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock)},
|
||||||
|
},
|
||||||
|
expectPass: false,
|
||||||
|
expectedErr: "minimum swap amount > maximum swap amount",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "negative coin id",
|
||||||
|
args: args{
|
||||||
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
|
"bnb", -714, suite.supply[0], true,
|
||||||
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock)},
|
||||||
|
},
|
||||||
|
expectPass: false,
|
||||||
|
expectedErr: "coin id must be a non negative",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negative asset limit",
|
name: "negative asset limit",
|
||||||
args: args{
|
args: args{
|
||||||
bnbDeputyAddress: suite.addr,
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
"bnb", 714,
|
||||||
minAmount: types.DefaultMinAmount,
|
sdk.NewInt(-10000000000000), true,
|
||||||
maxAmount: types.DefaultMaxAmount,
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
minBlockLock: types.DefaultMinBlockLock,
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock)},
|
||||||
maxBlockLock: types.DefaultMaxBlockLock,
|
|
||||||
supportedAssets: types.AssetParams{
|
|
||||||
types.AssetParam{
|
|
||||||
Denom: "bnb",
|
|
||||||
CoinID: 714,
|
|
||||||
Limit: sdk.NewInt(-10000),
|
|
||||||
Active: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
expectedErr: "must have a positive supply limit",
|
expectedErr: "invalid (negative) supply limit",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "duplicate asset denom",
|
name: "duplicate denom",
|
||||||
args: args{
|
args: args{
|
||||||
bnbDeputyAddress: suite.addr,
|
assetParams: types.AssetParams{types.NewAssetParam(
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
"bnb", 714, suite.supply[0], true,
|
||||||
minAmount: types.DefaultMinAmount,
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(100000000), sdk.NewInt(100000000000),
|
||||||
maxAmount: types.DefaultMaxAmount,
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock),
|
||||||
minBlockLock: types.DefaultMinBlockLock,
|
types.NewAssetParam(
|
||||||
maxBlockLock: types.DefaultMaxBlockLock,
|
"bnb", 0, suite.supply[0], true,
|
||||||
supportedAssets: types.AssetParams{
|
suite.addr, sdk.NewInt(1000), sdk.NewInt(10000000), sdk.NewInt(100000000000),
|
||||||
types.AssetParam{
|
types.DefaultMinBlockLock, types.DefaultMaxBlockLock),
|
||||||
Denom: "bnb",
|
|
||||||
CoinID: 714,
|
|
||||||
Limit: sdk.NewInt(100000000000),
|
|
||||||
Active: true,
|
|
||||||
},
|
|
||||||
types.AssetParam{
|
|
||||||
Denom: "bnb",
|
|
||||||
CoinID: 114,
|
|
||||||
Limit: sdk.NewInt(500000000),
|
|
||||||
Active: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
expectedErr: "cannot have duplicate denom",
|
expectedErr: "duplicate denom",
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "duplicate asset coin ID",
|
|
||||||
args: args{
|
|
||||||
bnbDeputyAddress: suite.addr,
|
|
||||||
bnbDeputyFixedFee: types.DefaultBnbDeputyFixedFee,
|
|
||||||
minAmount: types.DefaultMinAmount,
|
|
||||||
maxAmount: types.DefaultMaxAmount,
|
|
||||||
minBlockLock: types.DefaultMinBlockLock,
|
|
||||||
maxBlockLock: types.DefaultMaxBlockLock,
|
|
||||||
supportedAssets: types.AssetParams{
|
|
||||||
types.AssetParam{
|
|
||||||
Denom: "bnb",
|
|
||||||
CoinID: 714,
|
|
||||||
Limit: sdk.NewInt(100000000000),
|
|
||||||
Active: true,
|
|
||||||
},
|
|
||||||
types.AssetParam{
|
|
||||||
Denom: "fake",
|
|
||||||
CoinID: 714,
|
|
||||||
Limit: sdk.NewInt(500000000),
|
|
||||||
Active: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectPass: false,
|
|
||||||
expectedErr: "cannot have duplicate coin id",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
params := types.NewParams(tc.args.bnbDeputyAddress, tc.args.bnbDeputyFixedFee, tc.args.minAmount,
|
suite.Run(tc.name, func() {
|
||||||
tc.args.maxAmount, tc.args.minBlockLock, tc.args.maxBlockLock, tc.args.supportedAssets)
|
params := types.NewParams(tc.args.assetParams)
|
||||||
|
err := params.Validate()
|
||||||
|
if tc.expectPass {
|
||||||
|
suite.Require().NoError(err, tc.name)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err, tc.name)
|
||||||
|
suite.Require().Contains(err.Error(), tc.expectedErr)
|
||||||
|
}
|
||||||
|
|
||||||
err := params.Validate()
|
})
|
||||||
if tc.expectPass {
|
|
||||||
suite.Require().NoError(err, tc.name)
|
|
||||||
} else {
|
|
||||||
suite.Require().Error(err, tc.name)
|
|
||||||
suite.Require().Contains(err.Error(), tc.expectedErr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ const (
|
|||||||
|
|
||||||
// QueryAssetSupply contains the params for query 'custom/bep3/supply'
|
// QueryAssetSupply contains the params for query 'custom/bep3/supply'
|
||||||
type QueryAssetSupply struct {
|
type QueryAssetSupply struct {
|
||||||
Denom tmbytes.HexBytes `json:"denom" yaml:"denom"`
|
Denom string `json:"denom" yaml:"denom"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQueryAssetSupply creates a new QueryAssetSupply
|
// NewQueryAssetSupply creates a new QueryAssetSupply
|
||||||
func NewQueryAssetSupply(denom tmbytes.HexBytes) QueryAssetSupply {
|
func NewQueryAssetSupply(denom string) QueryAssetSupply {
|
||||||
return QueryAssetSupply{
|
return QueryAssetSupply{
|
||||||
Denom: denom,
|
Denom: denom,
|
||||||
}
|
}
|
||||||
|
@ -9,21 +9,17 @@ import (
|
|||||||
|
|
||||||
// AssetSupply contains information about an asset's supply
|
// AssetSupply contains information about an asset's supply
|
||||||
type AssetSupply struct {
|
type AssetSupply struct {
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
|
||||||
IncomingSupply sdk.Coin `json:"incoming_supply" yaml:"incoming_supply"`
|
IncomingSupply sdk.Coin `json:"incoming_supply" yaml:"incoming_supply"`
|
||||||
OutgoingSupply sdk.Coin `json:"outgoing_supply" yaml:"outgoing_supply"`
|
OutgoingSupply sdk.Coin `json:"outgoing_supply" yaml:"outgoing_supply"`
|
||||||
CurrentSupply sdk.Coin `json:"current_supply" yaml:"current_supply"`
|
CurrentSupply sdk.Coin `json:"current_supply" yaml:"current_supply"`
|
||||||
SupplyLimit sdk.Coin `json:"supply_limit" yaml:"supply_limit"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAssetSupply initializes a new AssetSupply
|
// NewAssetSupply initializes a new AssetSupply
|
||||||
func NewAssetSupply(denom string, incomingSupply, outgoingSupply, currentSupply, supplyLimit sdk.Coin) AssetSupply {
|
func NewAssetSupply(incomingSupply, outgoingSupply, currentSupply sdk.Coin) AssetSupply {
|
||||||
return AssetSupply{
|
return AssetSupply{
|
||||||
Denom: denom,
|
|
||||||
IncomingSupply: incomingSupply,
|
IncomingSupply: incomingSupply,
|
||||||
OutgoingSupply: outgoingSupply,
|
OutgoingSupply: outgoingSupply,
|
||||||
CurrentSupply: currentSupply,
|
CurrentSupply: currentSupply,
|
||||||
SupplyLimit: supplyLimit,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,22 +34,35 @@ func (a AssetSupply) Validate() error {
|
|||||||
if !a.CurrentSupply.IsValid() {
|
if !a.CurrentSupply.IsValid() {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "current supply %s", a.CurrentSupply)
|
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "current supply %s", a.CurrentSupply)
|
||||||
}
|
}
|
||||||
if !a.SupplyLimit.IsValid() {
|
denom := a.CurrentSupply.Denom
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "supply limit %s", a.SupplyLimit)
|
if (a.IncomingSupply.Denom != denom) ||
|
||||||
|
(a.OutgoingSupply.Denom != denom) {
|
||||||
|
return fmt.Errorf("asset supply denoms do not match %s %s %s", a.CurrentSupply.Denom, a.IncomingSupply.Denom, a.OutgoingSupply.Denom)
|
||||||
}
|
}
|
||||||
return sdk.ValidateDenom(a.Denom)
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns if two asset supplies are equal
|
||||||
|
func (a AssetSupply) Equal(b AssetSupply) bool {
|
||||||
|
return (a.IncomingSupply.IsEqual(b.IncomingSupply) &&
|
||||||
|
a.CurrentSupply.IsEqual(b.CurrentSupply) &&
|
||||||
|
a.OutgoingSupply.IsEqual(b.OutgoingSupply))
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements stringer
|
// String implements stringer
|
||||||
func (a AssetSupply) String() string {
|
func (a AssetSupply) String() string {
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
%s supply:
|
asset supply:
|
||||||
Incoming supply: %s
|
Incoming supply: %s
|
||||||
Outgoing supply: %s
|
Outgoing supply: %s
|
||||||
Current supply: %s
|
Current supply: %s
|
||||||
Supply limit: %s
|
|
||||||
`,
|
`,
|
||||||
a.Denom, a.IncomingSupply, a.OutgoingSupply, a.CurrentSupply, a.SupplyLimit)
|
a.IncomingSupply, a.OutgoingSupply, a.CurrentSupply)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDenom getter method for the denom of the asset supply
|
||||||
|
func (a AssetSupply) GetDenom() string {
|
||||||
|
return a.CurrentSupply.Denom
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetSupplies is a slice of AssetSupply
|
// AssetSupplies is a slice of AssetSupply
|
@ -17,7 +17,7 @@ func TestAssetSupplyValidate(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
msg: "valid asset",
|
msg: "valid asset",
|
||||||
asset: NewAssetSupply("kava", coin, coin, coin, coin),
|
asset: NewAssetSupply(coin, coin, coin),
|
||||||
expPass: true,
|
expPass: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -42,21 +42,6 @@ func TestAssetSupplyValidate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"invalid supply limit",
|
|
||||||
AssetSupply{
|
|
||||||
IncomingSupply: coin,
|
|
||||||
OutgoingSupply: coin,
|
|
||||||
CurrentSupply: coin,
|
|
||||||
SupplyLimit: invalidCoin,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
msg: "invalid denom",
|
|
||||||
asset: NewAssetSupply("Invalid Denom", coin, coin, coin, coin),
|
|
||||||
expPass: false,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
@ -76,19 +76,33 @@ func (suite *PermissionTestSuite) TestSubParamChangePermission_Allows() {
|
|||||||
testCDPParams.DebtParam = testDP
|
testCDPParams.DebtParam = testDP
|
||||||
testCDPParams.GlobalDebtLimit = testCPs[0].DebtLimit.Add(testCPs[0].DebtLimit) // correct global debt limit to pass genesis validation
|
testCDPParams.GlobalDebtLimit = testCPs[0].DebtLimit.Add(testCPs[0].DebtLimit) // correct global debt limit to pass genesis validation
|
||||||
|
|
||||||
|
testDeputy, err := sdk.AccAddressFromBech32("kava1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj")
|
||||||
|
suite.Require().NoError(err)
|
||||||
// bep3 Asset Params
|
// bep3 Asset Params
|
||||||
testAPs := bep3types.AssetParams{
|
testAPs := bep3types.AssetParams{
|
||||||
{
|
bep3types.AssetParam{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
CoinID: 714,
|
CoinID: 714,
|
||||||
Limit: i(100000000000),
|
SupplyLimit: sdk.NewInt(350000000000000),
|
||||||
Active: true,
|
Active: true,
|
||||||
|
DeputyAddress: testDeputy,
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: bep3types.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: bep3types.DefaultMaxBlockLock,
|
||||||
},
|
},
|
||||||
{
|
bep3types.AssetParam{
|
||||||
Denom: "inc",
|
Denom: "inc",
|
||||||
CoinID: 9999,
|
CoinID: 9999,
|
||||||
Limit: i(100),
|
SupplyLimit: sdk.NewInt(100),
|
||||||
Active: false,
|
Active: false,
|
||||||
|
DeputyAddress: testDeputy,
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: bep3types.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: bep3types.DefaultMaxBlockLock,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
testAPsUpdatedActive := make(bep3types.AssetParams, len(testAPs))
|
testAPsUpdatedActive := make(bep3types.AssetParams, len(testAPs))
|
||||||
@ -97,7 +111,7 @@ func (suite *PermissionTestSuite) TestSubParamChangePermission_Allows() {
|
|||||||
|
|
||||||
// bep3 Genesis
|
// bep3 Genesis
|
||||||
testBep3Params := bep3types.DefaultParams()
|
testBep3Params := bep3types.DefaultParams()
|
||||||
testBep3Params.SupportedAssets = testAPs
|
testBep3Params.AssetParams = testAPs
|
||||||
|
|
||||||
// pricefeed Markets
|
// pricefeed Markets
|
||||||
testMs := pricefeedtypes.Markets{
|
testMs := pricefeedtypes.Markets{
|
||||||
@ -139,7 +153,7 @@ func (suite *PermissionTestSuite) TestSubParamChangePermission_Allows() {
|
|||||||
{Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyDebtThreshold)},
|
{Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyDebtThreshold)},
|
||||||
{Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyCollateralParams)},
|
{Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyCollateralParams)},
|
||||||
{Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyDebtParam)},
|
{Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyDebtParam)},
|
||||||
{Subspace: bep3types.ModuleName, Key: string(bep3types.KeySupportedAssets)},
|
{Subspace: bep3types.ModuleName, Key: string(bep3types.KeyAssetParams)},
|
||||||
{Subspace: pricefeedtypes.ModuleName, Key: string(pricefeedtypes.KeyMarkets)},
|
{Subspace: pricefeedtypes.ModuleName, Key: string(pricefeedtypes.KeyMarkets)},
|
||||||
},
|
},
|
||||||
AllowedCollateralParams: types.AllowedCollateralParams{
|
AllowedCollateralParams: types.AllowedCollateralParams{
|
||||||
@ -195,7 +209,7 @@ func (suite *PermissionTestSuite) TestSubParamChangePermission_Allows() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Subspace: bep3types.ModuleName,
|
Subspace: bep3types.ModuleName,
|
||||||
Key: string(bep3types.KeySupportedAssets),
|
Key: string(bep3types.KeyAssetParams),
|
||||||
Value: string(suite.cdc.MustMarshalJSON(testAPsUpdatedActive)),
|
Value: string(suite.cdc.MustMarshalJSON(testAPsUpdatedActive)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
bep3types "github.com/kava-labs/kava/x/bep3/types"
|
bep3types "github.com/kava-labs/kava/x/bep3/types"
|
||||||
cdptypes "github.com/kava-labs/kava/x/cdp/types"
|
cdptypes "github.com/kava-labs/kava/x/cdp/types"
|
||||||
pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types"
|
pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types"
|
||||||
|
"github.com/tendermint/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Avoid cluttering test cases with long function names
|
// Avoid cluttering test cases with long function names
|
||||||
@ -155,24 +156,43 @@ func (suite *PermissionsTestSuite) TestAllowedCollateralParams_Allows() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PermissionsTestSuite) TestAllowedAssetParams_Allows() {
|
func (suite *PermissionsTestSuite) TestAllowedAssetParams_Allows() {
|
||||||
|
deputyAddress := sdk.AccAddress(crypto.AddressHash([]byte("KavaTestUser1")))
|
||||||
testAPs := bep3types.AssetParams{
|
testAPs := bep3types.AssetParams{
|
||||||
{
|
bep3types.AssetParam{
|
||||||
Denom: "bnb",
|
Denom: "btc",
|
||||||
CoinID: 714,
|
CoinID: 0,
|
||||||
Limit: i(1000000000000),
|
SupplyLimit: sdk.NewInt(100),
|
||||||
Active: true,
|
Active: false,
|
||||||
|
DeputyAddress: deputyAddress,
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: bep3types.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: bep3types.DefaultMaxBlockLock,
|
||||||
},
|
},
|
||||||
{
|
bep3types.AssetParam{
|
||||||
Denom: "btc",
|
Denom: "bnb",
|
||||||
CoinID: 0,
|
CoinID: 714,
|
||||||
Limit: i(1000000000000),
|
SupplyLimit: sdk.NewInt(350000000000000),
|
||||||
Active: true,
|
Active: true,
|
||||||
|
DeputyAddress: deputyAddress,
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: bep3types.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: bep3types.DefaultMaxBlockLock,
|
||||||
},
|
},
|
||||||
{
|
bep3types.AssetParam{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
CoinID: 144,
|
CoinID: 414,
|
||||||
Limit: i(1000000000000),
|
SupplyLimit: sdk.NewInt(350000000000000),
|
||||||
Active: true,
|
Active: true,
|
||||||
|
DeputyAddress: deputyAddress,
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: bep3types.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: bep3types.DefaultMaxBlockLock,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
updatedTestAPs := make(bep3types.AssetParams, len(testAPs))
|
updatedTestAPs := make(bep3types.AssetParams, len(testAPs))
|
||||||
@ -180,10 +200,10 @@ func (suite *PermissionsTestSuite) TestAllowedAssetParams_Allows() {
|
|||||||
updatedTestAPs[1] = testAPs[0]
|
updatedTestAPs[1] = testAPs[0]
|
||||||
updatedTestAPs[2] = testAPs[2]
|
updatedTestAPs[2] = testAPs[2]
|
||||||
|
|
||||||
updatedTestAPs[0].Limit = i(1000) // btc
|
updatedTestAPs[0].SupplyLimit = i(1000) // btc
|
||||||
updatedTestAPs[1].Active = false // bnb
|
updatedTestAPs[1].Active = false // bnb
|
||||||
updatedTestAPs[2].Limit = i(1000) // xrp
|
updatedTestAPs[2].SupplyLimit = i(1000) // xrp
|
||||||
updatedTestAPs[2].Active = false // xrp
|
updatedTestAPs[2].Active = false // xrp
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -238,6 +258,7 @@ func (suite *PermissionsTestSuite) TestAllowedAssetParams_Allows() {
|
|||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
Active: true,
|
Active: true,
|
||||||
|
Limit: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "btc",
|
Denom: "btc",
|
||||||
@ -575,20 +596,26 @@ func (suite *PermissionsTestSuite) TestAllowedDebtParam_Allows() {
|
|||||||
|
|
||||||
func (suite *PermissionsTestSuite) TestAllowedAssetParam_Allows() {
|
func (suite *PermissionsTestSuite) TestAllowedAssetParam_Allows() {
|
||||||
testAP := bep3types.AssetParam{
|
testAP := bep3types.AssetParam{
|
||||||
Denom: "usdx",
|
Denom: "usdx",
|
||||||
CoinID: 999,
|
CoinID: 999,
|
||||||
Limit: i(1000000000),
|
SupplyLimit: sdk.NewInt(1000000000),
|
||||||
Active: true,
|
Active: true,
|
||||||
|
DeputyAddress: sdk.AccAddress(crypto.AddressHash([]byte("KavaTestUser1"))),
|
||||||
|
FixedFee: sdk.NewInt(1000),
|
||||||
|
MinSwapAmount: sdk.OneInt(),
|
||||||
|
MaxSwapAmount: sdk.NewInt(1000000000000),
|
||||||
|
MinBlockLock: bep3types.DefaultMinBlockLock,
|
||||||
|
MaxBlockLock: bep3types.DefaultMaxBlockLock,
|
||||||
}
|
}
|
||||||
newCoinidAP := testAP
|
newCoinidAP := testAP
|
||||||
newCoinidAP.CoinID = 0
|
newCoinidAP.CoinID = 0
|
||||||
|
|
||||||
newLimitAP := testAP
|
newLimitAP := testAP
|
||||||
newLimitAP.Limit = i(1000)
|
newLimitAP.SupplyLimit = i(1000)
|
||||||
|
|
||||||
newCoinidAndLimitAP := testAP
|
newCoinidAndLimitAP := testAP
|
||||||
newCoinidAndLimitAP.CoinID = 0
|
newCoinidAndLimitAP.CoinID = 0
|
||||||
newCoinidAndLimitAP.Limit = i(1000)
|
newCoinidAndLimitAP.SupplyLimit = i(1000)
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -260,7 +260,7 @@ func (perm SubParamChangePermission) Allows(ctx sdk.Context, appCdc *codec.Codec
|
|||||||
var foundIncomingAPs bool
|
var foundIncomingAPs bool
|
||||||
var incomingAPs bep3types.AssetParams
|
var incomingAPs bep3types.AssetParams
|
||||||
for _, change := range proposal.Changes {
|
for _, change := range proposal.Changes {
|
||||||
if !(change.Subspace == bep3types.ModuleName && change.Key == string(bep3types.KeySupportedAssets)) {
|
if !(change.Subspace == bep3types.ModuleName && change.Key == string(bep3types.KeyAssetParams)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// note: in case of duplicates take the last value
|
// note: in case of duplicates take the last value
|
||||||
@ -277,7 +277,7 @@ func (perm SubParamChangePermission) Allows(ctx sdk.Context, appCdc *codec.Codec
|
|||||||
return false // not using a panic to help avoid begin blocker panics
|
return false // not using a panic to help avoid begin blocker panics
|
||||||
}
|
}
|
||||||
var currentAPs bep3types.AssetParams
|
var currentAPs bep3types.AssetParams
|
||||||
subspace.Get(ctx, bep3types.KeySupportedAssets, ¤tAPs) // panics if something goes wrong
|
subspace.Get(ctx, bep3types.KeyAssetParams, ¤tAPs) // panics if something goes wrong
|
||||||
|
|
||||||
// Check all the incoming changes in the CollateralParams are allowed
|
// Check all the incoming changes in the CollateralParams are allowed
|
||||||
assetParamsChangesAllowed := perm.AllowedAssetParams.Allows(currentAPs, incomingAPs)
|
assetParamsChangesAllowed := perm.AllowedAssetParams.Allows(currentAPs, incomingAPs)
|
||||||
@ -473,9 +473,10 @@ type AllowedAssetParam struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (aap AllowedAssetParam) Allows(current, incoming bep3types.AssetParam) bool {
|
func (aap AllowedAssetParam) Allows(current, incoming bep3types.AssetParam) bool {
|
||||||
|
|
||||||
allowed := ((aap.Denom == current.Denom) && (aap.Denom == incoming.Denom)) && // require denoms to be all equal
|
allowed := ((aap.Denom == current.Denom) && (aap.Denom == incoming.Denom)) && // require denoms to be all equal
|
||||||
((current.CoinID == incoming.CoinID) || aap.CoinID) &&
|
((current.CoinID == incoming.CoinID) || aap.CoinID) &&
|
||||||
(current.Limit.Equal(incoming.Limit) || aap.Limit) &&
|
(current.SupplyLimit.Equal(incoming.SupplyLimit) || aap.Limit) &&
|
||||||
((current.Active == incoming.Active) || aap.Active)
|
((current.Active == incoming.Active) || aap.Active)
|
||||||
return allowed
|
return allowed
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user