Skip to content

Commit

Permalink
more tests and improved burner to save burns happening at the same he…
Browse files Browse the repository at this point in the history
…ight
  • Loading branch information
stefan.balea committed Aug 15, 2024
1 parent e5c01d6 commit 75e4371
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 19 deletions.
36 changes: 36 additions & 0 deletions x/burner/keeper/burned_coins.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/bze-alphateam/bze/x/burner/types"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
"strconv"
)

func (k Keeper) GetAllBurnedCoins(ctx sdk.Context) (list []types.BurnedCoins) {
Expand All @@ -28,3 +29,38 @@ func (k Keeper) SetBurnedCoins(ctx sdk.Context, burnedCoins types.BurnedCoins) {
val,
)
}

func (k Keeper) GetBurnedCoins(ctx sdk.Context, height string) (val types.BurnedCoins, found bool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.BurnedCoinsKeyPrefix))

b := store.Get(types.BurnedCoinsKey(height))
if b == nil {
return val, false
}

k.cdc.MustUnmarshal(b, &val)
return val, true
}

func (k Keeper) SaveBurnedCoins(ctx sdk.Context, coins sdk.Coins) error {
height := strconv.FormatInt(ctx.BlockHeader().Height, 10)
b, found := k.GetBurnedCoins(ctx, height)
if !found {
b = types.BurnedCoins{
Burned: coins.String(),
Height: height,
}
} else {
alreadyBurned, err := sdk.ParseCoinsNormalized(b.Burned)
if err != nil {
return err
}

alreadyBurned = alreadyBurned.Add(coins...)
b.Burned = alreadyBurned.String()
}

k.SetBurnedCoins(ctx, b)

return nil
}
10 changes: 2 additions & 8 deletions x/burner/keeper/gov.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"github.com/bze-alphateam/bze/x/burner/types"

sdk "github.com/cosmos/cosmos-sdk/types"

"strconv"
)

func (k Keeper) HandleBurnCoinsProposal(ctx sdk.Context, proposal *types.BurnCoinsProposal) error {
Expand All @@ -21,13 +19,9 @@ func (k Keeper) HandleBurnCoinsProposal(ctx sdk.Context, proposal *types.BurnCoi
panic(err)
}

var burnedCoins = types.BurnedCoins{
Burned: coins.String(),
Height: strconv.FormatInt(ctx.BlockHeader().Height, 10),
}
k.SetBurnedCoins(ctx, burnedCoins)
k.SaveBurnedCoins(ctx, coins)

err = ctx.EventManager().EmitTypedEvent(&types.CoinsBurnedEvent{Burned: burnedCoins.Burned})
err = ctx.EventManager().EmitTypedEvent(&types.CoinsBurnedEvent{Burned: coins.String()})
if err != nil {
return err
}
Expand Down
8 changes: 8 additions & 0 deletions x/burner/keeper/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"github.com/bze-alphateam/bze/x/burner/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"strings"
)

const (
Expand Down Expand Up @@ -59,6 +60,13 @@ func (k Keeper) burnerRaffleCleanup(ctx sdk.Context, epochNumber int64) {
continue
}

if !strings.HasPrefix(item.Denom, "factory") {
err = k.SaveBurnedCoins(ctx, sdk.NewCoins(currentPot))
if err != nil {
logger.Error("failed to save burned coins", "error", err)
}
}

logger.Debug("burned raffle coins", "burned_current_pot", currentPot)

err = ctx.EventManager().EmitTypedEvent(&types.RaffleFinishedEvent{Denom: item.Denom})
Expand Down
21 changes: 20 additions & 1 deletion x/burner/keeper/hook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ func (suite *IntegrationTestSuite) TestBurnerRaffleCleanupHook_MultipleRaffles_S
//add to store some random data to delete
for i := 1; i <= 5; i++ {
denom := fmt.Sprintf("burner%d", i)
if i%2 == 0 {
denom = fmt.Sprintf("factory/%s", denom)
}
raffleDeleteHook := types.RaffleDeleteHook{
Denom: denom,
EndAt: 1,
Expand Down Expand Up @@ -146,8 +149,12 @@ func (suite *IntegrationTestSuite) TestBurnerRaffleCleanupHook_MultipleRaffles_S

suite.Require().NoError(hook.AfterEpochEnd(suite.ctx, "hour", int64(1)))
for i := 1; i <= 5; i++ {

isFactoryDenom := false
denom := fmt.Sprintf("burner%d", i)
if i%2 == 0 {
denom = fmt.Sprintf("factory/%s", denom)
isFactoryDenom = true
}

//check raffle was deleted
_, ok := suite.k.GetRaffle(suite.ctx, denom)
Expand All @@ -162,5 +169,17 @@ func (suite *IntegrationTestSuite) TestBurnerRaffleCleanupHook_MultipleRaffles_S

bal := suite.app.BankKeeper.GetBalance(suite.ctx, moduleAcc.GetAddress(), denom)
suite.Require().True(bal.IsZero())

allBurns := suite.k.GetAllBurnedCoins(suite.ctx)
if !isFactoryDenom {
suite.Require().NotEmpty(allBurns)
}
for _, b := range allBurns {
if isFactoryDenom {
suite.Require().NotContains(b.Burned, denom)
} else {
suite.Require().Contains(b.Burned, denom)
}
}
}
}
133 changes: 123 additions & 10 deletions x/burner/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"strconv"
"strings"
"time"
)

func (suite *IntegrationTestSuite) TestFundBurner_InvalidAmount() {
Expand Down Expand Up @@ -573,7 +574,7 @@ func (suite *IntegrationTestSuite) TestJoinRaffle_RaffleNotFound() {

msg := types.MsgJoinRaffle{
Creator: "",
Denom: "dsa",
Denom: "aau",
}

_, err := suite.msgServer.JoinRaffle(goCtx, &msg)
Expand Down Expand Up @@ -612,39 +613,42 @@ func (suite *IntegrationTestSuite) TestJoinRaffle_InvalidCreator() {

func (suite *IntegrationTestSuite) TestJoinRaffle_Stress() {
goCtx := sdk.WrapSDKContext(suite.ctx)

addr1 := sdk.AccAddress("addr1_______________")
balances := sdk.NewCoins(sdk.NewInt64Coin("aau", 1_000_000_000_000_000))
initialBalanceAmount := sdk.NewInt(1_000_000_000_000_000)
balances := sdk.NewCoins(sdk.NewInt64Coin("aau", initialBalanceAmount.Int64()))
suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, balances))

potInt := sdk.NewInt(150_000_000_000)
ticketCost := sdk.NewInt(10_000_000)
msg := types.MsgStartRaffle{
Creator: addr1.String(),
Pot: "150_000_000_000",
Pot: potInt.String(),
Duration: "1",
Chances: "100",
Ratio: "0.1",
TicketPrice: "10000000",
TicketPrice: ticketCost.String(),
Denom: "aau",
}
_, err := suite.msgServer.StartRaffle(goCtx, &msg)
suite.Require().NoError(err)

addrBalance := suite.app.BankKeeper.GetBalance(suite.ctx, addr1, "aau")
suite.Require().EqualValues(addrBalance.Amount.Int64(), 1_000_000_000_000_000-150_000_000_000)
suite.Require().EqualValues(addrBalance.Amount, initialBalanceAmount.Sub(potInt))

moduleAddress := suite.app.AccountKeeper.GetModuleAddress(types.RaffleModuleName)
moduleBalance := suite.app.BankKeeper.GetBalance(suite.ctx, moduleAddress, "aau")
suite.Require().EqualValues(moduleBalance.Amount.String(), "150000000000")
suite.Require().EqualValues(moduleBalance.Amount, potInt)

ratio, err := sdk.NewDecFromStr(msg.Ratio)
suite.Require().NoError(err)
ticketCost := sdk.NewInt(10000000)

winCount := 0
ticketsToPlace := 100000
ticketsToPlace := time.Now().Unix()
totalPotWon := sdk.ZeroInt()

for i := ticketsToPlace * 15; i <= ticketsToPlace*20; i++ {
appHash := strconv.Itoa(i)
for i := ticketsToPlace; i <= ticketsToPlace+100000; i++ {
appHash := fmt.Sprintf("%x", i)
blockHash := []byte("block_id" + appHash)
suite.ctx = suite.ctx.WithBlockHeader(tmproto.Header{
LastBlockId: tmproto.BlockID{
Expand Down Expand Up @@ -700,6 +704,115 @@ func (suite *IntegrationTestSuite) TestJoinRaffle_Stress() {
}
}

newModuleBalance := suite.app.BankKeeper.GetBalance(suite.ctx, moduleAddress, "aau")
suite.ctx.Logger().Info(fmt.Sprintf("test finished"))
suite.ctx.Logger().Info(fmt.Sprintf("%d users won. total participants %d", winCount, 100000))
suite.ctx.Logger().Info(fmt.Sprintf("total pot won: %s", totalPotWon.QuoRaw(1_000_000).String()))
suite.ctx.Logger().Info(fmt.Sprintf("module balance is: %s", newModuleBalance.Amount.QuoRaw(1_000_000).String()))
}

func (suite *IntegrationTestSuite) TestJoinRaffle_Simulation() {
goCtx := sdk.WrapSDKContext(suite.ctx)

addr1 := sdk.AccAddress("addr1_______________")
addr2 := sdk.AccAddress("addr2_______________")
initialBalanceAmount := sdk.NewInt(1_000_000_000_000_000)
balances := sdk.NewCoins(sdk.NewInt64Coin("aau", initialBalanceAmount.Int64()))
suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, balances))
suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr2, balances))

potInt := sdk.NewInt(50_000_000_000)
ticketCost := sdk.NewInt(10_000_000)
msg := types.MsgStartRaffle{
Creator: addr1.String(),
Pot: potInt.String(),
Duration: "1",
Chances: "100",
Ratio: "0.15",
TicketPrice: ticketCost.String(),
Denom: "aau",
}
_, err := suite.msgServer.StartRaffle(goCtx, &msg)
suite.Require().NoError(err)

addrBalance := suite.app.BankKeeper.GetBalance(suite.ctx, addr1, "aau")
suite.Require().EqualValues(addrBalance.Amount, initialBalanceAmount.Sub(potInt))

addr2Balance := suite.app.BankKeeper.GetBalance(suite.ctx, addr2, "aau")
suite.Require().EqualValues(addr2Balance.Amount, initialBalanceAmount)

moduleAddress := suite.app.AccountKeeper.GetModuleAddress(types.RaffleModuleName)
moduleBalance := suite.app.BankKeeper.GetBalance(suite.ctx, moduleAddress, "aau")
suite.Require().EqualValues(moduleBalance.Amount, potInt)

ratio, err := sdk.NewDecFromStr(msg.Ratio)
suite.Require().NoError(err)

winCount := 0
ticketsStart := time.Now().Unix()
ticketsToPlace := int64(10000)
totalPotWon := sdk.ZeroInt()

for i := ticketsStart; i < ticketsStart+ticketsToPlace; i++ {
appHash := fmt.Sprintf("%x", i)
blockHash := []byte("block_id" + appHash)
suite.ctx = suite.ctx.WithBlockHeader(tmproto.Header{
LastBlockId: tmproto.BlockID{
Hash: tmhash.Sum(blockHash),
},
AppHash: tmhash.Sum([]byte(appHash)),
Height: i,
}).WithEventManager(sdk.NewEventManager())

goCtx = sdk.WrapSDKContext(suite.ctx)
addrBalance = suite.app.BankKeeper.GetBalance(suite.ctx, addr1, "aau")
addr2Balance = suite.app.BankKeeper.GetBalance(suite.ctx, addr2, "aau")
moduleBalance = suite.app.BankKeeper.GetBalance(suite.ctx, moduleAddress, "aau")
winners := suite.k.GetRaffleWinners(suite.ctx, "aau")

join := types.MsgJoinRaffle{
Creator: addr1.String(),
Denom: "aau",
}
join2 := types.MsgJoinRaffle{
Creator: addr2.String(),
Denom: "aau",
}

_, err = suite.msgServer.JoinRaffle(goCtx, &join)
suite.Require().NoError(err)
_, err = suite.msgServer.JoinRaffle(goCtx, &join2)
suite.Require().NoError(err)

suite.k.WithdrawLuckyRaffleParticipants(suite.ctx, suite.ctx.BlockHeight())

for _, e := range suite.ctx.EventManager().Events() {
if strings.Contains(e.Type, "RaffleWinnerEvent") {
winCount++
//wonAmount := currentPot.Amount.Sub(ticketPriceInt).ToDec().Mul(winRatio).TruncateInt()
prize := moduleBalance.Amount.ToDec().Mul(ratio).TruncateInt()
if !prize.IsPositive() {
prize = moduleBalance.SubAmount(ticketCost).Amount
}
totalPotWon = totalPotWon.Add(prize)

wantedAddress := addr1
compareAddress := addrBalance
for _, attr := range e.Attributes {
if strings.Contains(attr.String(), addr2.String()) {
wantedAddress = addr2
compareAddress = addr2Balance
}
}
newBalance := suite.app.BankKeeper.GetBalance(suite.ctx, wantedAddress, "aau")
suite.Require().True(newBalance.Amount.GT(compareAddress.Amount))

newWinners := suite.k.GetRaffleWinners(suite.ctx, "aau")
suite.Require().True(len(newWinners) > len(winners) || len(newWinners) == 100)
}
}
}

newModuleBalance := suite.app.BankKeeper.GetBalance(suite.ctx, moduleAddress, "aau")
suite.ctx.Logger().Info(fmt.Sprintf("test finished"))
suite.ctx.Logger().Info(fmt.Sprintf("%d users won. total participants %d", winCount, ticketsToPlace))
Expand Down

0 comments on commit 75e4371

Please sign in to comment.