Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(audit): resolve some findings #192

Merged
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ WORKDIR /root
COPY --from=build-env /go/src/github.com/ExocoreNetwork/exocore/build/exocored /usr/bin/exocored
COPY --from=build-env /go/bin/toml-cli /usr/bin/toml-cli

RUN apk add --no-cache ca-certificates=20240226-r0 libstdc++=13.2.1_git20231014-r0 jq=1.7.1-r0 curl=8.9.1-r0 bash=5.2.21-r0 vim=9.0.2127-r0 lz4=1.9.4-r5 rclone=1.65.0-r3 \
RUN apk add --no-cache ca-certificates=20240226-r0 libstdc++=13.2.1_git20231014-r0 jq=1.7.1-r0 curl=8.9.1-r1 bash=5.2.21-r0 vim=9.0.2127-r0 lz4=1.9.4-r5 rclone=1.65.0-r3 \
&& addgroup -g 1000 exocore \
&& adduser -S -h /home/exocore -D exocore -u 1000 -G exocore

Expand Down
13 changes: 12 additions & 1 deletion app/ante/sigverify.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,26 @@ func ConsumeMultisignatureVerificationGas(
meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey,
params authtypes.Params, accSeq uint64,
) error {
pubkeys := pubkey.GetPubKeys()
size := sig.BitArray.Count()
if size != len(pubkeys) {
return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "bitarray length doesn't match the number of public keys")
}
if len(sig.Signatures) != sig.BitArray.NumTrueBitsBefore(size) {
return errorsmod.Wrapf(errortypes.ErrTooManySignatures, "number of signatures exceeds number of bits in bitarray")
}
// we have verified that size == len(pubkeys)
// and that the number of signatures == number of true bits in the bitarray
// so we can safely iterate over the pubkeys and signatures
sigIndex := 0

for i := 0; i < size; i++ {
if !sig.BitArray.GetIndex(i) {
// not signed
continue
}
sigV2 := signing.SignatureV2{
PubKey: pubkey.GetPubKeys()[i],
PubKey: pubkeys[i],
Data: sig.Signatures[sigIndex],
Sequence: accSeq,
}
Expand Down
6 changes: 3 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,9 +675,9 @@ func NewExocoreApp(
app.GetSubspace(evmtypes.ModuleName),
)

// the AVS manager keeper is the AVS registry. it allows registered operators to add or
// remove AVSs. this keeper is initialized after the EVM keeper because it depends on the EVM keeper
// to set a lookup from codeHash to code, at genesis.
// the AVS manager keeper is the AVS registry. this keeper is initialized after the EVM
// keeper because it depends on the EVM keeper to set a lookup from codeHash to code,
// at genesis.
app.AVSManagerKeeper = avsManagerKeeper.NewKeeper(
appCodec, keys[avsManagerTypes.StoreKey],
&app.OperatorKeeper,
Expand Down
2 changes: 1 addition & 1 deletion networks/local/exocore/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ RUN LEDGER_ENABLED=false make build

#####################################
FROM alpine:3.19 AS run
RUN apk add --no-cache libstdc++=13.2.1_git20231014-r0 bash=5.2.21-r0 curl=8.9.1-r0 jq=1.7.1-r0 \
RUN apk add --no-cache libstdc++=13.2.1_git20231014-r0 bash=5.2.21-r0 curl=8.9.1-r1 jq=1.7.1-r0 \
&& addgroup -g 1000 exocore \
&& adduser -S -h /home/exocore -D exocore -u 1000 -G exocore
EXPOSE 26656 26657 1317 9090 8545 8546
Expand Down
11 changes: 5 additions & 6 deletions precompiles/assets/IAssets.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ IAssets constant ASSETS_CONTRACT = IAssets(ASSETS_PRECOMPILE_ADDRESS);
interface IAssets {

/// TRANSACTIONS
/// @dev deposit the client chain assets, mainly LSTs, for the staker,
/// that will change the state in deposit module
/// @dev deposit the client chain assets, only LSTs, for the staker,
/// that will change the state in assets module
/// Note that this address cannot be a module account.
/// @param clientChainID is the layerZero chainID if it is supported.
// It might be allocated by Exocore when the client chain isn't supported
Expand All @@ -30,9 +30,8 @@ interface IAssets {
uint256 opAmount
) external returns (bool success, uint256 latestAssetState);

/// TRANSACTIONS
/// @dev deposit the client chain assets, native staking tokens, for the staker,
/// that will change the state in deposit module
/// that will change the state in assets module
/// Note that this address cannot be a module account.
/// @param clientChainID is the layerZero chainID if it is supported.
// It might be allocated by Exocore when the client chain isn't supported
Expand All @@ -47,7 +46,7 @@ interface IAssets {
uint256 opAmount
) external returns (bool success, uint256 latestAssetState);

/// @dev withdraw LST To the staker, that will change the state in withdraw module
/// @dev withdraw LST To the staker, that will change the state in assets module
/// Note that this address cannot be a module account.
/// @param clientChainID is the layerZero chainID if it is supported.
// It might be allocated by Exocore when the client chain isn't supported
Expand All @@ -62,7 +61,7 @@ interface IAssets {
uint256 opAmount
) external returns (bool success, uint256 latestAssetState);

/// @dev withdraw NST To the staker, that will change the state in withdraw module
/// @dev withdraw NST To the staker, that will change the state in assets module
/// Note that this address cannot be a module account.
/// @param clientChainID is the layerZero chainID if it is supported.
// It might be allocated by Exocore when the client chain isn't supported
Expand Down
13 changes: 2 additions & 11 deletions precompiles/assets/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,18 +189,9 @@ func (p Precompile) UpdateToken(
return nil, err
}

// check that the asset being updated actually exists
_, assetID := assetstypes.GetStakerIDAndAssetIDFromStr(uint64(clientChainID), "", hexAssetAddr)
assetInfo, err := p.assetsKeeper.GetStakingAssetInfo(ctx, assetID)
if err != nil {
// fails if asset does not exist with ErrNoClientChainAssetKey
return nil, err
}

// finally, execute the update
assetInfo.AssetBasicInfo.MetaInfo = metadata

if err := p.assetsKeeper.SetStakingAssetInfo(ctx, assetInfo); err != nil {
// this verifies the existence of the asset and returns an error if it doesn't exist
if err := p.assetsKeeper.UpdateStakingAssetMetaInfo(ctx, assetID, metadata); err != nil {
return nil, err
}

Expand Down
30 changes: 15 additions & 15 deletions precompiles/bls/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func (p Precompile) Verify(
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 3 {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
if len(args) != len(p.ABI.Methods[MethodVerify].Inputs) {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, len(p.ABI.Methods[MethodVerify].Inputs), len(args))
}

sigBz, ok := args[1].([]byte)
Expand Down Expand Up @@ -64,8 +64,8 @@ func (p Precompile) FastAggregateVerify(
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 3 {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
if len(args) != len(p.ABI.Methods[MethodFastAggregateVerify].Inputs) {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, len(p.ABI.Methods[MethodFastAggregateVerify].Inputs), len(args))
}

sigBz, ok := args[1].([]byte)
Expand Down Expand Up @@ -102,8 +102,8 @@ func (p Precompile) GeneratePrivateKey(
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 0 {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
if len(args) != len(p.ABI.Methods[MethodGeneratePrivateKey].Inputs) {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, len(p.ABI.Methods[MethodGeneratePrivateKey].Inputs), len(args))
}

privkey, err := blst.RandKey()
Expand Down Expand Up @@ -138,8 +138,8 @@ func (p Precompile) Sign(
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 2 {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
if len(args) != len(p.ABI.Methods[MethodSign].Inputs) {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, len(p.ABI.Methods[MethodSign].Inputs), len(args))
}

privkeyBz, ok := args[0].([]byte)
Expand All @@ -163,8 +163,8 @@ func (p Precompile) AggregatePubkeys(
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
if len(args) != len(p.ABI.Methods[MethodAggregatePubkeys].Inputs) {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, len(p.ABI.Methods[MethodAggregatePubkeys].Inputs), len(args))
}

pubkeysBz, ok := args[0].([][]byte)
Expand All @@ -184,8 +184,8 @@ func (p Precompile) AggregateSignatures(
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 3, len(args))
if len(args) != len(p.ABI.Methods[MethodAggregateSignatures].Inputs) {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, len(p.ABI.Methods[MethodAggregateSignatures].Inputs), len(args))
}

sigsBz, ok := args[0].([][]byte)
Expand All @@ -195,7 +195,7 @@ func (p Precompile) AggregateSignatures(

aggregatedSig, err := blst.AggregateCompressedSignatures(sigsBz)
if err != nil {
return nil, fmt.Errorf("failed to aggregate public keys")
return nil, fmt.Errorf("failed to aggregate signatures")
}

return method.Outputs.Pack(aggregatedSig.Marshal())
Expand All @@ -205,8 +205,8 @@ func (p Precompile) AddTwoPubkeys(
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 2 {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args))
if len(args) != len(p.ABI.Methods[MethodAddTwoPubkeys].Inputs) {
return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, len(p.ABI.Methods[MethodAddTwoPubkeys].Inputs), len(args))
}

pubkeyOneBz, ok := args[0].([]byte)
Expand Down
12 changes: 11 additions & 1 deletion proto/exocore/oracle/v1/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,19 @@
// voting power need to reach more than threshold_a/threshold_b
int32 threshold_b = 8;
// for v1, mode=1, get final price as soon as voting power reach threshold_a/threshold_b
int32 mode = 9;
ConsensusMode mode = 9;

Check failure on line 30 in proto/exocore/oracle/v1/params.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "9" on message "Params" changed type from "int32" to "enum".
// for each round, a validator only allowed to provide at most max_det_id continuos rounds of prices for DS
int32 max_det_id = 10;
// for each token, only keep max_size_prices round of prices
int32 max_size_prices = 11;
}

// ConsensusMode defines the consensus mode for the prices.
enum ConsensusMode {
option (gogoproto.goproto_enum_prefix) = false;
// CONSENSUS_MODE_UNSPECIFIED defines an invalid mode.
CONSENSUS_MODE_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "ConsensusModeUnspecified"];
// CONSENSUS_MODE_ASAP defines the mode to get final price immediately when the voting power
// exceeds the threshold.
CONSENSUS_MODE_ASAP = 1 [(gogoproto.enumvalue_customname) = "ConsensusModeASAP"];
}
2 changes: 1 addition & 1 deletion x/assets/keeper/bank.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type DepositWithdrawParams struct {
func (k Keeper) PerformDepositOrWithdraw(ctx sdk.Context, params *DepositWithdrawParams) error {
// check params parameter before executing deposit operation
if params.OpAmount.IsNegative() {
return errorsmod.Wrapf(assetstypes.ErrInvalidDepositAmount, "negative deposit amount:%s", params.OpAmount)
return assetstypes.ErrInvalidDepositAmount.Wrapf("negative deposit amount:%s", params.OpAmount)
}
stakerID, assetID := assetstypes.GetStakerIDAndAssetID(params.ClientChainLzID, params.StakerAddress, params.AssetsAddress)
if !k.IsStakingAsset(ctx, assetID) {
Expand Down
31 changes: 27 additions & 4 deletions x/assets/keeper/client_chain_asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ func (k Keeper) UpdateStakingAssetTotalAmount(ctx sdk.Context, assetID string, c
}

// SetStakingAssetInfo todo: Temporarily use clientChainAssetAddr+'_'+LayerZeroChainID as the key.
// It provides a function to register the client chain assets supported by exoCore.It's called by genesis configuration now,however it will be called by the governance in the future
// It provides a function to register the client chain assets supported by Exocore.
// New assets may be registered via ExocoreGateway, which uses precompiles to call this function.
// If an asset with the provided assetID already exists, it will return an error.
func (k Keeper) SetStakingAssetInfo(ctx sdk.Context, info *assetstype.StakingAssetInfo) (err error) {
if info.AssetBasicInfo.Decimals > assetstype.MaxDecimal {
return errorsmod.Wrapf(assetstype.ErrInvalidInputParameter, "the decimal is greater than the MaxDecimal,decimal:%v,MaxDecimal:%v", info.AssetBasicInfo.Decimals, assetstype.MaxDecimal)
Expand All @@ -44,19 +46,39 @@ func (k Keeper) SetStakingAssetInfo(ctx sdk.Context, info *assetstype.StakingAss
return errorsmod.Wrapf(assetstype.ErrInvalidInputParameter, "the total staking amount is negative, StakingTotalAmount:%v", info.StakingTotalAmount)
}
store := prefix.NewStore(ctx.KVStore(k.storeKey), assetstype.KeyPrefixReStakingAssetInfo)
// key := common.HexToAddress(incentive.Contract)
bz := k.cdc.MustMarshal(info)

_, assetID := assetstype.GetStakerIDAndAssetIDFromStr(info.AssetBasicInfo.LayerZeroChainID, "", info.AssetBasicInfo.Address)
if store.Has([]byte(assetID)) {
return assetstype.ErrRegisterDuplicateAssetID.Wrapf(
"the asset has already been registered,assetID:%v,LayerZeroChainID:%v,ClientChainAssetAddr:%v",
assetID, info.AssetBasicInfo.LayerZeroChainID, info.AssetBasicInfo.Address,
)
}
bz := k.cdc.MustMarshal(info)
store.Set([]byte(assetID), bz)
return nil
}

// IsStakingAsset checks if the assetID is a staking asset.
func (k Keeper) IsStakingAsset(ctx sdk.Context, assetID string) bool {
store := prefix.NewStore(ctx.KVStore(k.storeKey), assetstype.KeyPrefixReStakingAssetInfo)
return store.Has([]byte(assetID))
}

// UpdateStakingAssetMetaInfo updates the meta information stored against a provided assetID.
// If the assetID does not exist, it returns an error.
func (k Keeper) UpdateStakingAssetMetaInfo(ctx sdk.Context, assetID string, metainfo string) error {
info, err := k.GetStakingAssetInfo(ctx, assetID)
if err != nil {
return err
}
store := prefix.NewStore(ctx.KVStore(k.storeKey), assetstype.KeyPrefixReStakingAssetInfo)
info.AssetBasicInfo.MetaInfo = metainfo
bz := k.cdc.MustMarshal(info)
store.Set([]byte(assetID), bz)
return nil
}

// GetStakingAssetInfo returns the asset information stored against a provided assetID.
func (k Keeper) GetStakingAssetInfo(ctx sdk.Context, assetID string) (info *assetstype.StakingAssetInfo, err error) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), assetstype.KeyPrefixReStakingAssetInfo)
value := store.Get([]byte(assetID))
Expand All @@ -69,6 +91,7 @@ func (k Keeper) GetStakingAssetInfo(ctx sdk.Context, assetID string) (info *asse
return &ret, nil
}

// GetAssetsDecimal returns the decimal of all the provided assets.
func (k Keeper) GetAssetsDecimal(ctx sdk.Context, assets map[string]interface{}) (decimals map[string]uint32, err error) {
if assets == nil {
return nil, errorsmod.Wrap(assetstype.ErrInputPointerIsNil, "assets is nil")
Expand Down
1 change: 1 addition & 0 deletions x/assets/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ var (
ErrInvalidOperationType = errorsmod.Register(
ModuleName, 18,
"the operation type is invalid")

ErrRegisterDuplicateAssetID = errorsmod.Register(
ModuleName, 19,
"register new asset with an existing assetID")
Expand Down
2 changes: 1 addition & 1 deletion x/assets/types/general.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const (
WithdrawLST
DepositNST
WithdrawNST
WithDrawReward
WithdrawReward
DelegateTo
UndelegateFrom
Slash
Expand Down
1 change: 1 addition & 0 deletions x/avs/keeper/avs.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func (k *Keeper) GetAVSInfoByTaskAddress(ctx sdk.Context, taskAddr string) types
k.IterateAVSInfo(ctx, func(_ int64, avsInfo types.AVSInfo) (stop bool) {
if taskAddr == avsInfo.GetTaskAddr() {
avs = avsInfo
return true // stop because we found the AVS
}
return false
})
Expand Down
12 changes: 9 additions & 3 deletions x/avs/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ const (
RouterKey = ModuleName

// MemStoreKey defines the in-memory store key
MemStoreKey = "mem_avs"
prefixAVSInfo = iota + 1
MemStoreKey = "mem_avs"
)

const (
// prefixAVSInfo is the prefix for the AVS info store. It starts with a value of 5
// for backward compatibility with the previous prefix used for the AVS info store.
// TODO at the time of a chain-id upgrade, this may be reset to 1.
prefixAVSInfo = iota + 5
prefixAVSOperatorInfo
prefixParams
prefixAVSTaskInfo = iota + 1
prefixAVSTaskInfo
prefixOperatePub
prefixAVSAddressToChainID
LatestTaskNum
Expand Down
Loading
Loading