Skip to content

Commit

Permalink
More fixes for Chardonnay testnet (#273)
Browse files Browse the repository at this point in the history
* move AxelarBody back to []byte

* axelarcork validator cap, check cork count

* fix axelarcork module account sweep

* Make sure cellar IDs are always sorted

* sort cellar IDs when written to state

* Always store fee accrual counters sorted

* always sort allowed addresses for publisher intents

* update v7 upgrade with new cellars

* appease linter
  • Loading branch information
EricBolten authored Feb 1, 2024
1 parent 73e0166 commit d7023e5
Show file tree
Hide file tree
Showing 19 changed files with 145 additions and 59 deletions.
9 changes: 6 additions & 3 deletions app/upgrades/v7/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,10 @@ func pubsubInitGenesis(ctx sdk.Context, pubsubKeeper pubsubkeeper.Keeper) {
"1:0x05641a27C82799AaF22b436F20A3110410f29652", // Steady MATIC
"1:0x6F069F711281618467dAe7873541EcC082761B33", // Steady UNI
"1:0x6a6731f1754e3088ea35c8ddfd55cFF4d0FA5052", // Turbo CRVUSD
"1:0x6c1edce139291Af5b84fB1e496c9747F83E876c9", // Turbo DIVETH
"1:0x9a7b4980C6F0FCaa50CD5f288Ad7038f434c692e", // Turbo EETH
"1:0xdAdC82e26b3739750E036dFd9dEfd3eD459b877A", // Turbo EETH V2
"1:0x19B8D8FC682fC56FbB42653F68c7d48Dd3fe597E", // Turbo ETHX
"1:0x0C190DEd9Be5f512Bd72827bdaD4003e9Cc7975C", // Turbo GHO
"1:0x5195222f69c5821f8095ec565E71e18aB6A2298f", // Turbo SOMM
"1:0xc7372Ab5dd315606dB799246E8aA112405abAeFf", // Turbo stETH (stETH deposit)
Expand All @@ -259,7 +262,7 @@ func pubsubInitGenesis(ctx sdk.Context, pubsubKeeper pubsubkeeper.Keeper) {
}

// Set 7seas publisher intents for existing cellars
publisherIntents := make([]*pubsubtypes.PublisherIntent, 0, 28)
publisherIntents := make([]*pubsubtypes.PublisherIntent, 0, 31)
for _, cellar := range cellars {
publisherIntents = append(publisherIntents, &pubsubtypes.PublisherIntent{
SubscriptionId: cellar,
Expand All @@ -270,7 +273,7 @@ func pubsubInitGenesis(ctx sdk.Context, pubsubKeeper pubsubkeeper.Keeper) {
}

// Set default subscriptions for 7seas as the publisher for existing cellars
defaultSubscriptions := make([]*pubsubtypes.DefaultSubscription, 0, 28)
defaultSubscriptions := make([]*pubsubtypes.DefaultSubscription, 0, 31)
for _, cellar := range cellars {
defaultSubscriptions = append(defaultSubscriptions, &pubsubtypes.DefaultSubscription{
SubscriptionId: cellar,
Expand All @@ -280,7 +283,7 @@ func pubsubInitGenesis(ctx sdk.Context, pubsubKeeper pubsubkeeper.Keeper) {

// Create subscribers and intents for existing validators
subscribers := createSubscribers()
subscriberIntents := make([]*pubsubtypes.SubscriberIntent, 0, 980)
subscriberIntents := make([]*pubsubtypes.SubscriberIntent, 0, 1085)
for _, subscriber := range subscribers {
for _, cellar := range cellars {
subscriberIntents = append(subscriberIntents, &pubsubtypes.SubscriberIntent{
Expand Down
14 changes: 6 additions & 8 deletions integration_tests/axelarcork_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,16 +496,14 @@ func (s *IntegrationTestSuite) TestAxelarCork() {
sendResponse, err := s.chain.sendMsgs(*orch0ClientCtx, sendFundsToAxelarcorkMsg)
s.Require().NoError(err)
s.Require().Zero(sendResponse.Code, "raw log: %s", sendResponse.RawLog)
s.T().Log("Verifying distribution community pool balances includes the swept funds")

// Short delay to ensure a new block is queried
time.Sleep(10 * time.Second)

// Verify fund appear in the community pool
distributionCommunityPoolResponse, err = distributionQueryClient.CommunityPool(context.Background(), &distributiontypes.QueryCommunityPoolRequest{})
s.Require().NoError(err)
s.T().Log("Verifying distribution community pool balances includes the swept funds")
poolAfterSweep := initialPool.Add(sdk.NewDecCoinsFromCoins(usommToSend)...).Add(sdk.NewDecCoinsFromCoins(sweepDenomToSend)...)
s.Require().Equal(poolAfterSweep, distributionCommunityPoolResponse.Pool)
s.Require().Eventually(func() bool {
distributionCommunityPoolResponse, err := distributionQueryClient.CommunityPool(context.Background(), &distributiontypes.QueryCommunityPoolRequest{})
s.Require().NoError(err)
return poolAfterSweep.IsEqual(distributionCommunityPoolResponse.Pool)
}, time.Second*60, time.Second*5, "swept funds never reached community pool")
})
}

Expand Down
14 changes: 4 additions & 10 deletions x/axelarcork/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,18 @@ func (k Keeper) EndBlocker(ctx sdk.Context) {
// transfer fails or gas is refunded.
moduleAcct := k.GetSenderAccount(ctx)
balances := k.bankKeeper.GetAllBalances(ctx, moduleAcct.GetAddress())
balancesForPool := sdk.Coins{}

for _, b := range balances {
if b.Amount.IsPositive() {
balancesForPool.Add(b)
}
}

if balancesForPool.Len() == 0 {
if balances.IsZero() {
return
}

if err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, distributionTypes.ModuleName, balancesForPool); err != nil {
k.Logger(ctx).Info("sweeping funds from axelarcork module account to community pool", "coins", balances.String())
if err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, distributionTypes.ModuleName, balances); err != nil {
panic(err)
}

feePool := k.distributionKeeper.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(balancesForPool...)...)
feePool.CommunityPool = feePool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(balances...)...)

k.distributionKeeper.SetFeePool(ctx, feePool)
}
6 changes: 5 additions & 1 deletion x/axelarcork/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"fmt"
"sort"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -82,9 +83,12 @@ func ExportGenesis(ctx sdk.Context, k Keeper) types.GenesisState {
cellarIDs := k.GetCellarIDs(ctx, config.Id)
var cellarIDSet types.CellarIDSet
cellarIDSet.ChainId = config.Id
cellarIDSetIDs := make([]string, 0, len(cellarIDs))
for _, id := range cellarIDs {
cellarIDSet.Ids = append(cellarIDSet.Ids, id.String())
cellarIDSetIDs = append(cellarIDSetIDs, id.String())
}
sort.Strings(cellarIDSetIDs)
cellarIDSet.Ids = cellarIDSetIDs
gs.CellarIds = append(gs.CellarIds, &cellarIDSet)

gs.ScheduledCorks.ScheduledCorks = append(gs.ScheduledCorks.ScheduledCorks, k.GetScheduledAxelarCorks(ctx, config.Id)...)
Expand Down
39 changes: 39 additions & 0 deletions x/axelarcork/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/binary"
"encoding/hex"
"reflect"
"sort"

"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
Expand Down Expand Up @@ -369,6 +370,7 @@ func (k Keeper) GetApprovedScheduledAxelarCorks(ctx sdk.Context, chainID uint64)
}

k.DeleteScheduledAxelarCork(ctx, chainID, currentBlockHeight, id, val, addr)
k.DecrementValidatorAxelarCorkCount(ctx, val)

return false
})
Expand Down Expand Up @@ -402,6 +404,11 @@ func (k Keeper) GetApprovedScheduledAxelarCorks(ctx sdk.Context, chainID uint64)

func (k Keeper) SetCellarIDs(ctx sdk.Context, chainID uint64, c types.CellarIDSet) {
bz := k.cdc.MustMarshal(&c)
// always sort before writing to the store
cellarIDs := make([]string, 0, len(c.Ids))
cellarIDs = append(cellarIDs, c.Ids...)
sort.Strings(cellarIDs)
c.Ids = cellarIDs
ctx.KVStore(k.storeKey).Set(types.MakeCellarIDsKey(chainID), bz)
}

Expand Down Expand Up @@ -524,6 +531,38 @@ func (k Keeper) IterateAxelarProxyUpgradeData(ctx sdk.Context, cb func(chainID u
}
}

///////////////////////////
// Validator Cork counts //
///////////////////////////

func (k Keeper) GetValidatorAxelarCorkCount(ctx sdk.Context, val sdk.ValAddress) (count uint64) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.GetValidatorAxelarCorkCountKey(val))
if len(bz) == 0 {
return 0
}

return binary.BigEndian.Uint64(bz)
}

func (k Keeper) SetValidatorAxelarCorkCount(ctx sdk.Context, val sdk.ValAddress, count uint64) {
bz := make([]byte, 8)
binary.BigEndian.PutUint64(bz, count)
ctx.KVStore(k.storeKey).Set(types.GetValidatorAxelarCorkCountKey(val), bz)
}

func (k Keeper) IncrementValidatorAxelarCorkCount(ctx sdk.Context, val sdk.ValAddress) {
count := k.GetValidatorAxelarCorkCount(ctx, val)
k.SetValidatorAxelarCorkCount(ctx, val, count+1)
}

func (k Keeper) DecrementValidatorAxelarCorkCount(ctx sdk.Context, val sdk.ValAddress) {
count := k.GetValidatorAxelarCorkCount(ctx, val)
if count > 0 {
k.SetValidatorAxelarCorkCount(ctx, val, count-1)
}
}

/////////////////////
// Module Accounts //
/////////////////////
Expand Down
21 changes: 10 additions & 11 deletions x/axelarcork/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ var _ types.MsgServer = Keeper{}
// ScheduleCork implements types.MsgServer
func (k Keeper) ScheduleCork(c context.Context, msg *types.MsgScheduleAxelarCorkRequest) (*types.MsgScheduleAxelarCorkResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
if !k.GetParamSet(ctx).Enabled {
params := k.GetParamSet(ctx)
if !params.Enabled {
return nil, types.ErrDisabled
}

Expand All @@ -34,6 +35,11 @@ func (k Keeper) ScheduleCork(c context.Context, msg *types.MsgScheduleAxelarCork
return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "signer %s is not a delegate", signer.String())
}

validatorAxelarCorkCount := k.GetValidatorAxelarCorkCount(ctx, validatorAddr)
if validatorAxelarCorkCount >= types.MaxAxelarCorksPerValidator {
return nil, types.ErrValidatorAxelarCorkCapacityReached
}

config, ok := k.GetChainConfigurationByID(ctx, msg.ChainId)
if !ok {
return nil, fmt.Errorf("chain by id %d not found", msg.ChainId)
Expand All @@ -48,6 +54,7 @@ func (k Keeper) ScheduleCork(c context.Context, msg *types.MsgScheduleAxelarCork
}

corkID := k.SetScheduledAxelarCork(ctx, config.Id, msg.BlockHeight, validatorAddr, *msg.Cork)
k.IncrementValidatorAxelarCorkCount(ctx, validatorAddr)

if err := ctx.EventManager().EmitTypedEvent(&types.ScheduleCorkEvent{
Signer: signer.String(),
Expand Down Expand Up @@ -97,7 +104,7 @@ func (k Keeper) RelayCork(c context.Context, msg *types.MsgRelayAxelarCorkReques
axelarMemo := types.AxelarBody{
DestinationChain: config.Name,
DestinationAddress: config.ProxyAddress,
Payload: bytesToInts(payload),
Payload: payload,
Type: types.PureMessage,
Fee: &types.Fee{
Amount: strconv.FormatUint(msg.Fee, 10),
Expand Down Expand Up @@ -161,7 +168,7 @@ func (k Keeper) RelayProxyUpgrade(c context.Context, msg *types.MsgRelayAxelarPr
axelarMemo := types.AxelarBody{
DestinationChain: config.Name,
DestinationAddress: config.ProxyAddress,
Payload: bytesToInts(upgradeData.Payload),
Payload: upgradeData.Payload,
Type: types.PureMessage,
Fee: &types.Fee{
Amount: strconv.FormatUint(msg.Fee, 10),
Expand Down Expand Up @@ -226,11 +233,3 @@ func (k Keeper) CancelScheduledCork(c context.Context, msg *types.MsgCancelAxela

return &types.MsgCancelAxelarCorkResponse{}, nil
}

func bytesToInts(payload []byte) []int {
intPayload := make([]int, len(payload))
for i, b := range payload {
intPayload[i] = int(b)
}
return intPayload
}
10 changes: 1 addition & 9 deletions x/axelarcork/keeper/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (k Keeper) ValidateAxelarPacket(ctx sdk.Context, sourceChannel string, data
if err := json.Unmarshal([]byte(packetData.Memo), &axelarBody); err != nil {
return err
}
payloadBytes := intsToBytes(axelarBody.Payload)
payloadBytes := axelarBody.Payload

// get the destination chain configuration
chainConfig, ok := k.GetChainConfigurationByName(ctx, axelarBody.DestinationChain)
Expand Down Expand Up @@ -144,11 +144,3 @@ func (k Keeper) ValidateAxelarPacket(ctx sdk.Context, sourceChannel string, data

return fmt.Errorf("invalid payload: %s", payloadBytes)
}

func intsToBytes(payload []int) []byte {
bytePayload := make([]byte, len(payload))
for i, b := range payload {
bytePayload[i] = byte(b)
}
return bytePayload
}
2 changes: 0 additions & 2 deletions x/axelarcork/keeper/proposal_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package keeper
import (
"encoding/json"
"fmt"
"sort"
"time"

distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
Expand Down Expand Up @@ -63,7 +62,6 @@ func HandleAddManagedCellarsProposal(ctx sdk.Context, k Keeper, p types.AddAxela
idStrings[i] = cid.String()
}

sort.Strings(idStrings)
k.SetCellarIDs(ctx, config.Id, types.CellarIDSet{ChainId: config.Id, Ids: idStrings})

return nil
Expand Down
2 changes: 1 addition & 1 deletion x/axelarcork/types/axelar.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const (
type AxelarBody struct {
DestinationChain string `json:"destination_chain"`
DestinationAddress string `json:"destination_address"`
Payload []int `json:"payload"`
Payload []byte `json:"payload"`
Type int64 `json:"type"`
Fee *Fee `json:"fee"`
}
Expand Down
21 changes: 21 additions & 0 deletions x/axelarcork/types/axelar_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,33 @@ package types

import (
"bytes"
"encoding/json"
"testing"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/stretchr/testify/require"
)

func TestEncodingMetadata(t *testing.T) {
axelarMemo := AxelarBody{
DestinationChain: "arbitrum",
DestinationAddress: "0xEe75bA2C81C04DcA4b0ED6d1B7077c188FEde4d2",
Payload: []byte("1234"),
Type: PureMessage,
Fee: &Fee{
Amount: "100",
Recipient: "axelar1aythygn6z5thymj6tmzfwekzh05ewg3l7d6y89",
},
}

memoBz, err := json.Marshal(axelarMemo)
require.NoError(t, err)

var body AxelarBody
err = json.Unmarshal(memoBz, &body)
require.NoError(t, err)
}

func TestEncodingDecodingLogicCalls(t *testing.T) {
targetContract := "0x1111111111111111111111111111111111111111"
nonce := uint64(1)
Expand Down
2 changes: 2 additions & 0 deletions x/axelarcork/types/axelarcork.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)

const MaxAxelarCorksPerValidator uint64 = 1000

func (c *AxelarCork) IDHash(blockHeight uint64) []byte {
blockHeightBytes := sdk.Uint64ToBigEndian(blockHeight)
chainIDBytes := sdk.Uint64ToBigEndian(c.ChainId)
Expand Down
15 changes: 8 additions & 7 deletions x/axelarcork/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (

// x/cork module sentinel errors
var (
ErrInvalidEVMAddress = errorsmod.Register(ModuleName, 2, "invalid evm address")
ErrUnmanagedCellarAddress = errorsmod.Register(ModuleName, 3, "cork sent to address that has not passed governance")
ErrEmptyContractCall = errorsmod.Register(ModuleName, 4, "cork has an empty contract call body")
ErrSchedulingInThePast = errorsmod.Register(ModuleName, 5, "cork is trying to be scheduled for a block that has already passed")
ErrInvalidJSON = errorsmod.Register(ModuleName, 6, "invalid json")
ErrValuelessSend = errorsmod.Register(ModuleName, 7, "transferring an empty token amount")
ErrDisabled = errorsmod.Register(ModuleName, 8, "axelar disabled")
ErrInvalidEVMAddress = errorsmod.Register(ModuleName, 2, "invalid evm address")
ErrUnmanagedCellarAddress = errorsmod.Register(ModuleName, 3, "cork sent to address that has not passed governance")
ErrEmptyContractCall = errorsmod.Register(ModuleName, 4, "cork has an empty contract call body")
ErrSchedulingInThePast = errorsmod.Register(ModuleName, 5, "cork is trying to be scheduled for a block that has already passed")
ErrInvalidJSON = errorsmod.Register(ModuleName, 6, "invalid json")
ErrValuelessSend = errorsmod.Register(ModuleName, 7, "transferring an empty token amount")
ErrDisabled = errorsmod.Register(ModuleName, 8, "axelar disabled")
ErrValidatorAxelarCorkCapacityReached = errorsmod.Register(ModuleName, 9, "validator Axelar cork capacity reached")
)
7 changes: 7 additions & 0 deletions x/axelarcork/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ const (

// AxelarProxyUpgradeDataPrefix - <prefix><chain_id> -> <payload>
AxelarProxyUpgradeDataPrefix

// ValidatorAxelarCorkCountKey - <prefix><val_address> -> uint64(count)
ValidatorAxelarCorkCountKey
)

// GetCorkValidatorKeyPrefix returns the key prefix for cork commits for a validator
Expand Down Expand Up @@ -118,3 +121,7 @@ func GetAxelarProxyUpgradeDataKey(chainID uint64) []byte {
binary.BigEndian.PutUint64(cid, chainID)
return bytes.Join([][]byte{{AxelarProxyUpgradeDataPrefix}, cid}, []byte{})
}

func GetValidatorAxelarCorkCountKey(val sdk.ValAddress) []byte {
return append([]byte{ValidatorAxelarCorkCountKey}, val.Bytes()...)
}
8 changes: 8 additions & 0 deletions x/cellarfees/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package keeper
import (
"fmt"
"math/big"
"sort"
"strings"

"cosmossdk.io/math"
"github.com/tendermint/tendermint/libs/log"
Expand Down Expand Up @@ -113,6 +115,12 @@ func (k Keeper) GetFeeAccrualCounters(ctx sdk.Context) (counters types.FeeAccrua

func (k Keeper) SetFeeAccrualCounters(ctx sdk.Context, counters types.FeeAccrualCounters) {
store := ctx.KVStore(k.storeKey)
counterSlice := make([]types.FeeAccrualCounter, 0, len(counters.Counters))
counterSlice = append(counterSlice, counters.Counters...)
sort.Slice(counterSlice, func(i, j int) bool {
return strings.Compare(counterSlice[i].Denom, counterSlice[j].Denom) == -1
})
counters.Counters = counterSlice
b := k.cdc.MustMarshal(&counters)
store.Set(types.GetFeeAccrualCountersKey(), b)
}
Expand Down
Loading

0 comments on commit d7023e5

Please sign in to comment.