Skip to content

Commit

Permalink
implement whitelist feature for AVS
Browse files Browse the repository at this point in the history
  • Loading branch information
trestinlsd committed Dec 6, 2024
1 parent 27a99e2 commit 7e89c4a
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 141 deletions.
4 changes: 4 additions & 0 deletions precompiles/avs/IAVSManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ interface IAVSManager {
/// @param slashAddr The slash address of AVS.
/// @param rewardAddr The reward address of AVS.
/// @param avsOwnerAddress The owners who have permission for AVS.
/// @param whitelistAddress The whitelist address of the operator.
/// @param assetIds The basic asset information of AVS.
/// @param avsUnbondingPeriod The unbonding duration of AVS.
/// @param minSelfDelegation The minimum delegation amount for an operator.
Expand All @@ -65,6 +66,7 @@ interface IAVSManager {
address slashAddr,
address rewardAddr,
string[] memory avsOwnerAddress,
string[] memory whitelistAddress,
string[] memory assetIds,
uint64 avsUnbondingPeriod,
uint64 minSelfDelegation,
Expand All @@ -80,6 +82,7 @@ interface IAVSManager {
/// @param slashAddr The slash address of AVS.
/// @param rewardAddr The reward address of AVS.
/// @param avsOwnerAddress The owners who have permission for AVS.
/// @param whitelistAddress The whitelist address of the operator.
/// @param assetIds The basic asset information of AVS.
/// @param avsUnbondingPeriod The unbonding duration of AVS.
/// @param minSelfDelegation The minimum delegation amount for an operator.
Expand All @@ -96,6 +99,7 @@ interface IAVSManager {
address slashAddr,
address rewardAddr,
string[] memory avsOwnerAddress,
string[] memory whitelistAddress,
string[] memory assetIds,
uint64 avsUnbondingPeriod,
uint64 minSelfDelegation,
Expand Down
10 changes: 10 additions & 0 deletions precompiles/avs/abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,11 @@
"name": "avsOwnerAddress",
"type": "string[]"
},
{
"internalType": "string[]",
"name": "whitelistAddress",
"type": "string[]"
},
{
"internalType": "string[]",
"name": "assetIds",
Expand Down Expand Up @@ -778,6 +783,11 @@
"name": "avsOwnerAddress",
"type": "string[]"
},
{
"internalType": "string[]",
"name": "whitelistAddress",
"type": "string[]"
},
{
"internalType": "string[]",
"name": "assetIds",
Expand Down
72 changes: 49 additions & 23 deletions precompiles/avs/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,38 +68,51 @@ func (p Precompile) GetAVSParamsFromInputs(_ sdk.Context, args []interface{}) (*
exoAddresses[i] = accAddr.String()
}
avsParams.AvsOwnerAddress = exoAddresses

// bech32
whitelistAddress, ok := args[7].([]string)
if !ok || whitelistAddress == nil {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 7, "[]string", whitelistAddress)
}
exoWhiteAddresses := make([]string, len(whitelistAddress))
for i, addr := range whitelistAddress {
accAddr, err := sdk.AccAddressFromBech32(addr)
if err != nil {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 7, "[]string", whitelistAddress)
}
exoAddresses[i] = accAddr.String()
}
avsParams.WhitelistAddress = exoWhiteAddresses
// string, since it is the address_id representation
assetID, ok := args[7].([]string)
assetID, ok := args[8].([]string)
if !ok || len(assetID) == 0 {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 7, "[]string", assetID)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 8, "[]string", assetID)
}
avsParams.AssetID = assetID

unbondingPeriod, ok := args[8].(uint64)
unbondingPeriod, ok := args[9].(uint64)
if !ok || unbondingPeriod == 0 {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 8, "uint64", unbondingPeriod)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 9, "uint64", unbondingPeriod)
}
avsParams.UnbondingPeriod = unbondingPeriod

minSelfDelegation, ok := args[9].(uint64)
minSelfDelegation, ok := args[10].(uint64)
if !ok {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 9, "uint64", minSelfDelegation)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 10, "uint64", minSelfDelegation)
}
avsParams.MinSelfDelegation = minSelfDelegation

epochIdentifier, ok := args[10].(string)
epochIdentifier, ok := args[11].(string)
if !ok || epochIdentifier == "" {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 10, "string", epochIdentifier)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 11, "string", epochIdentifier)
}
avsParams.EpochIdentifier = epochIdentifier

// The parameters below are used when creating tasks, to ensure that the minimum criteria are met by the set
// of operators.

taskParam, ok := args[11].([]uint64)
taskParam, ok := args[12].([]uint64)
if !ok || taskParam == nil || len(taskParam) != 4 {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 11, "[]string", taskParam)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 12, "[]string", taskParam)
}
minOptInOperators := taskParam[0]
avsParams.MinOptInOperators = minOptInOperators
Expand Down Expand Up @@ -166,43 +179,56 @@ func (p Precompile) GetAVSParamsFromUpdateInputs(_ sdk.Context, args []interface
for i, addr := range avsOwnerAddress {
accAddr, err := sdk.AccAddressFromBech32(addr)
if err != nil {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 7, "[]string", avsOwnerAddress)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 6, "[]string", avsOwnerAddress)
}
exoAddresses[i] = accAddr.String()
}
avsParams.AvsOwnerAddress = exoAddresses

// bech32
whitelistAddress, ok := args[7].([]string)
if !ok || whitelistAddress == nil {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 7, "[]string", whitelistAddress)
}
exoWhiteAddresses := make([]string, len(whitelistAddress))
for i, addr := range whitelistAddress {
accAddr, err := sdk.AccAddressFromBech32(addr)
if err != nil {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 7, "[]string", whitelistAddress)
}
exoAddresses[i] = accAddr.String()
}
avsParams.WhitelistAddress = exoWhiteAddresses
// string, since it is the address_id representation
assetID, ok := args[7].([]string)
assetID, ok := args[8].([]string)
if !ok {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 7, "[]string", assetID)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 8, "[]string", assetID)
}
avsParams.AssetID = assetID

unbondingPeriod, ok := args[8].(uint64)
unbondingPeriod, ok := args[9].(uint64)
if !ok {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 8, "uint64", unbondingPeriod)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 9, "uint64", unbondingPeriod)
}
avsParams.UnbondingPeriod = unbondingPeriod

minSelfDelegation, ok := args[9].(uint64)
minSelfDelegation, ok := args[10].(uint64)
if !ok {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 9, "uint64", minSelfDelegation)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 10, "uint64", minSelfDelegation)
}
avsParams.MinSelfDelegation = minSelfDelegation

epochIdentifier, ok := args[10].(string)
epochIdentifier, ok := args[11].(string)
if !ok {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 10, "string", epochIdentifier)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 11, "string", epochIdentifier)
}
avsParams.EpochIdentifier = epochIdentifier

// The parameters below are used when creating tasks, to ensure that the minimum criteria are met by the set
// of operators.

taskParam, ok := args[11].([]uint64)
taskParam, ok := args[12].([]uint64)
if !ok || taskParam == nil || len(taskParam) != 4 {
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 11, "[]string", taskParam)
return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 12, "[]string", taskParam)
}
minOptInOperators := taskParam[0]
avsParams.MinOptInOperators = minOptInOperators
Expand Down
3 changes: 2 additions & 1 deletion proto/exocore/avs/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ message AVSInfo {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];

// asset_reward_commission_epoch_basis is the avs reward distribution based on asset per eopch end.
map<string, int64> asset_reward_amount_epoch_basis = 18;
// whitelist_address are the bech32 addresses ,whitelist address of supported operators
repeated string whitelist_address = 19;
}

// Status and proof of each operator
Expand Down
26 changes: 23 additions & 3 deletions x/avs/keeper/avs.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package keeper

import (
errorsmod "cosmossdk.io/errors"

Check failure on line 4 in x/avs/keeper/avs.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

File is not `gofumpt`-ed (gofumpt)
sdkmath "cosmossdk.io/math"
"fmt"
"math/big"
"slices"
"strconv"
"strings"

Check failure on line 10 in x/avs/keeper/avs.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

File is not `gofumpt`-ed (gofumpt)

errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"

"github.com/ExocoreNetwork/exocore/x/avs/types"
"github.com/ethereum/go-ethereum/common"
"github.com/evmos/evmos/v16/x/evm/statedb"
Expand Down Expand Up @@ -224,3 +224,23 @@ func (k *Keeper) GetAllChainIDInfos(ctx sdk.Context) ([]types.ChainIDInfo, error
}
return ret, nil
}

// IsWhitelisted check if operator is in the whitelist
func (k *Keeper) IsWhitelisted(ctx sdk.Context, avsAddr, operatorAddr string) (bool, error) {
avsInfo, err := k.GetAVSInfo(ctx, avsAddr)
if err != nil {
return false, errorsmod.Wrap(err, fmt.Sprintf("IsWhitelisted: key is %s", avsAddr))
}
_, err = sdk.AccAddressFromBech32(operatorAddr)
if err != nil {
return false, errorsmod.Wrap(err, "IsWhitelisted: error occurred when parse acc address from Bech32")
}
// Currently avs has no whitelist set and any operator can optin
if len(avsInfo.Info.WhitelistAddress) == 0 {
return true, nil
}
if !slices.Contains(avsInfo.Info.WhitelistAddress, operatorAddr) {
return false, errorsmod.Wrap(err, "not in the whitelist address of supported operators")
}
return true, nil
}
6 changes: 6 additions & 0 deletions x/avs/keeper/avs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ func (suite *AVSTestSuite) TestAVS() {
avsAddress := suite.avsAddress
avsOwnerAddress := []string{"exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkjr", "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkj1", "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkj2"}
assetID := suite.AssetIDs
operatorAddress := sdk.AccAddress(utiltx.GenerateAddress().Bytes()).String()

avs := &types.AVSInfo{
Name: avsName,
AvsAddress: avsAddress.String(),
Expand All @@ -38,11 +40,15 @@ func (suite *AVSTestSuite) TestAVS() {
AvsSlash: sdk.MustNewDecFromStr("0.001"),
AvsReward: sdk.MustNewDecFromStr("0.002"),
TaskAddr: "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkjr",
WhitelistAddress: []string{operatorAddress},
}

err := suite.App.AVSManagerKeeper.SetAVSInfo(suite.Ctx, avs)
suite.NoError(err)

whitelisted, err := suite.App.AVSManagerKeeper.IsWhitelisted(suite.Ctx, avsAddress.String(), operatorAddress)
suite.NoError(err)
suite.Equal(whitelisted, true)
info, err := suite.App.AVSManagerKeeper.GetAVSInfo(suite.Ctx, avsAddress.String())

suite.NoError(err)
Expand Down
6 changes: 5 additions & 1 deletion x/avs/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ func (k Keeper) UpdateAVSInfo(ctx sdk.Context, params *types.AVSRegisterOrDeregi
// #nosec G115
AvsSlash: sdk.NewDecWithPrec(int64(params.AvsSlash), 2),
// #nosec G115
AvsReward: sdk.NewDecWithPrec(int64(params.AvsReward), 2),
AvsReward: sdk.NewDecWithPrec(int64(params.AvsReward), 2),
WhitelistAddress: params.WhitelistAddress,
}

return k.SetAVSInfo(ctx, avs)
Expand Down Expand Up @@ -185,6 +186,9 @@ func (k Keeper) UpdateAVSInfo(ctx sdk.Context, params *types.AVSRegisterOrDeregi
if params.AvsOwnerAddress != nil {
avs.AvsOwnerAddress = params.AvsOwnerAddress
}
if params.WhitelistAddress != nil {
avs.WhitelistAddress = params.WhitelistAddress
}
if params.AssetID != nil {
avs.AssetIDs = params.AssetID
if err := k.ValidateAssetIDs(ctx, params.AssetID); err != nil {
Expand Down
Loading

0 comments on commit 7e89c4a

Please sign in to comment.