From a7fce28f8829eff32c950c40e1c2d1f836334fd8 Mon Sep 17 00:00:00 2001 From: Maximo Palopoli <96491141+maximopalopoli@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:06:50 -0300 Subject: [PATCH] test: add test cases where contract returns an error (#446) --- chainio/clients/elcontracts/reader.go | 61 +++++++++++----------- chainio/clients/elcontracts/reader_test.go | 38 ++++++++++++++ 2 files changed, 69 insertions(+), 30 deletions(-) diff --git a/chainio/clients/elcontracts/reader.go b/chainio/clients/elcontracts/reader.go index 972b627d..128f7db0 100644 --- a/chainio/clients/elcontracts/reader.go +++ b/chainio/clients/elcontracts/reader.go @@ -99,15 +99,7 @@ func (r *ChainReader) IsOperatorRegistered( return false, errors.New("DelegationManager contract not provided") } - isOperator, err := r.delegationManager.IsOperator( - &bind.CallOpts{Context: ctx}, - gethcommon.HexToAddress(operator.Address), - ) - if err != nil { - return false, err - } - - return isOperator, nil + return r.delegationManager.IsOperator(&bind.CallOpts{Context: ctx}, gethcommon.HexToAddress(operator.Address)) } // GetStakerShares returns the amount of shares that a staker has in all of the strategies in which they have nonzero @@ -140,6 +132,7 @@ func (r *ChainReader) GetOperatorDetails( &bind.CallOpts{Context: ctx}, gethcommon.HexToAddress(operator.Address), ) + // This call should not fail since it's a getter if err != nil { return types.Operator{}, err } @@ -150,6 +143,7 @@ func (r *ChainReader) GetOperatorDetails( }, gethcommon.HexToAddress(operator.Address), ) + // This call should not fail if err != nil { return types.Operator{}, err } @@ -174,6 +168,7 @@ func (r *ChainReader) GetStrategyAndUnderlyingToken( strategyAddr gethcommon.Address, ) (*strategy.ContractIStrategy, gethcommon.Address, error) { contractStrategy, err := strategy.NewContractIStrategy(strategyAddr, r.ethClient) + // This call should not fail since it's an init if err != nil { return nil, gethcommon.Address{}, utils.WrapError("Failed to fetch strategy contract", err) } @@ -191,6 +186,7 @@ func (r *ChainReader) GetStrategyAndUnderlyingERC20Token( strategyAddr gethcommon.Address, ) (*strategy.ContractIStrategy, erc20.ContractIERC20Methods, gethcommon.Address, error) { contractStrategy, err := strategy.NewContractIStrategy(strategyAddr, r.ethClient) + // This call should not fail since it's an init if err != nil { return nil, nil, gethcommon.Address{}, utils.WrapError("Failed to fetch strategy contract", err) } @@ -199,6 +195,7 @@ func (r *ChainReader) GetStrategyAndUnderlyingERC20Token( return nil, nil, gethcommon.Address{}, utils.WrapError("Failed to fetch token contract", err) } contractUnderlyingToken, err := erc20.NewContractIERC20(underlyingTokenAddr, r.ethClient) + // This call should not fail, if the strategy does not have an underlying token then it would enter the if above if err != nil { return nil, nil, gethcommon.Address{}, utils.WrapError("Failed to fetch token contract", err) } @@ -334,13 +331,7 @@ func (r *ChainReader) GetOperatorAVSSplit( return 0, errors.New("RewardsCoordinator contract not provided") } - split, err := r.rewardsCoordinator.GetOperatorAVSSplit(&bind.CallOpts{Context: ctx}, operator, avs) - - if err != nil { - return 0, err - } - - return split, nil + return r.rewardsCoordinator.GetOperatorAVSSplit(&bind.CallOpts{Context: ctx}, operator, avs) } func (r *ChainReader) GetOperatorPISplit( @@ -351,13 +342,7 @@ func (r *ChainReader) GetOperatorPISplit( return 0, errors.New("RewardsCoordinator contract not provided") } - split, err := r.rewardsCoordinator.GetOperatorPISplit(&bind.CallOpts{Context: ctx}, operator) - - if err != nil { - return 0, err - } - - return split, nil + return r.rewardsCoordinator.GetOperatorPISplit(&bind.CallOpts{Context: ctx}, operator) } func (r *ChainReader) GetAllocatableMagnitude( @@ -398,6 +383,7 @@ func (r *ChainReader) GetAllocationInfo( operatorAddress, strategyAddress, ) + // This call should not fail since it's a getter if err != nil { return nil, err } @@ -474,6 +460,7 @@ func (r *ChainReader) IsOperatorRegisteredWithOperatorSet( if operatorSet.Id == 0 { // this is an M2 AVS status, err := r.avsDirectory.AvsOperatorStatus(&bind.CallOpts{Context: ctx}, operatorSet.Avs, operatorAddress) + // This call should not fail since it's a getter if err != nil { return false, err } @@ -481,6 +468,7 @@ func (r *ChainReader) IsOperatorRegisteredWithOperatorSet( return status == 1, nil } else { registeredOperatorSets, err := r.allocationManager.GetRegisteredSets(&bind.CallOpts{Context: ctx}, operatorAddress) + // This call should not fail since it's a getter if err != nil { return false, err } @@ -543,6 +531,7 @@ func (r *ChainReader) GetSlashableShares( } currentBlock, err := r.ethClient.BlockNumber(ctx) + // This call should not fail since it's a getter if err != nil { return nil, err } @@ -554,6 +543,7 @@ func (r *ChainReader) GetSlashableShares( strategies, uint32(currentBlock), ) + // This call should not fail since it's a getter if err != nil { return nil, err } @@ -578,6 +568,7 @@ func (r *ChainReader) GetSlashableSharesForOperatorSets( operatorSets []allocationmanager.OperatorSet, ) ([]OperatorSetStakes, error) { currentBlock, err := r.ethClient.BlockNumber(ctx) + // This call should not fail since it's a getter if err != nil { return nil, err } @@ -602,6 +593,7 @@ func (r *ChainReader) GetSlashableSharesForOperatorSetsBefore( } strategies, err := r.GetStrategiesForOperatorSet(ctx, operatorSet) + // If operator setId is 0 will fail on if above if err != nil { return nil, err } @@ -616,6 +608,7 @@ func (r *ChainReader) GetSlashableSharesForOperatorSetsBefore( strategies, futureBlock, ) + // This call should not fail since it's a getter if err != nil { return nil, err } @@ -639,6 +632,7 @@ func (r *ChainReader) GetAllocationDelay( return 0, errors.New("AllocationManager contract not provided") } isSet, delay, err := r.allocationManager.GetAllocationDelay(&bind.CallOpts{Context: ctx}, operatorAddress) + // This call should not fail since it's a getter if err != nil { return 0, err } @@ -672,8 +666,9 @@ func (r *ChainReader) CanCall( target, selector, ) + // This call should not fail since it's a getter if err != nil { - return false, errors.New("call to permission controller failed: " + err.Error()) + return false, utils.WrapError("call to permission controller failed", err) } return canCall, nil } @@ -690,8 +685,9 @@ func (r *ChainReader) ListAppointees( target, selector, ) + // This call should not fail since it's a getter if err != nil { - return nil, errors.New("call to permission controller failed: " + err.Error()) + return nil, utils.WrapError("call to permission controller failed", err) } return appointees, nil } @@ -706,8 +702,9 @@ func (r *ChainReader) ListAppointeePermissions( accountAddress, appointeeAddress, ) + // This call should not fail since it's a getter if err != nil { - return nil, nil, errors.New("call to permission controller failed: " + err.Error()) + return nil, nil, utils.WrapError("call to permission controller failed", err) } return targets, selectors, nil } @@ -717,8 +714,9 @@ func (r *ChainReader) ListPendingAdmins( accountAddress gethcommon.Address, ) ([]gethcommon.Address, error) { pendingAdmins, err := r.permissionController.GetPendingAdmins(&bind.CallOpts{Context: ctx}, accountAddress) + // This call should not fail since it's a getter if err != nil { - return nil, errors.New("call to permission controller failed: " + err.Error()) + return nil, utils.WrapError("call to permission controller failed", err) } return pendingAdmins, nil } @@ -728,8 +726,9 @@ func (r *ChainReader) ListAdmins( accountAddress gethcommon.Address, ) ([]gethcommon.Address, error) { pendingAdmins, err := r.permissionController.GetAdmins(&bind.CallOpts{Context: ctx}, accountAddress) + // This call should not fail since it's a getter if err != nil { - return nil, errors.New("call to permission controller failed: " + err.Error()) + return nil, utils.WrapError("call to permission controller failed", err) } return pendingAdmins, nil } @@ -744,8 +743,9 @@ func (r *ChainReader) IsPendingAdmin( accountAddress, pendingAdminAddress, ) + // This call should not fail since it's a getter if err != nil { - return isPendingAdmin, errors.New("call to permission controller failed: " + err.Error()) + return false, utils.WrapError("call to permission controller failed", err) } return isPendingAdmin, nil } @@ -756,8 +756,9 @@ func (r *ChainReader) IsAdmin( adminAddress gethcommon.Address, ) (bool, error) { isAdmin, err := r.permissionController.IsAdmin(&bind.CallOpts{Context: ctx}, accountAddress, adminAddress) + // This call should not fail since it's a getter if err != nil { - return isAdmin, errors.New("call to permission controller failed: " + err.Error()) + return false, utils.WrapError("call to permission controller failed", err) } return isAdmin, nil } diff --git a/chainio/clients/elcontracts/reader_test.go b/chainio/clients/elcontracts/reader_test.go index 0604ef79..b7a31ab3 100644 --- a/chainio/clients/elcontracts/reader_test.go +++ b/chainio/clients/elcontracts/reader_test.go @@ -735,6 +735,44 @@ func TestAppointeesFunctions(t *testing.T) { }) } +func TestContractErrorCases(t *testing.T) { + ctx := context.Background() + + testConfig := testutils.GetDefaultTestConfig() + anvilC, err := testutils.StartAnvilContainer(testConfig.AnvilStateFileName) + require.NoError(t, err) + + anvilHttpEndpoint, err := anvilC.Endpoint(context.Background(), "http") + require.NoError(t, err) + contractAddrs := testutils.GetContractAddressesFromContractRegistry(anvilHttpEndpoint) + + config := elcontracts.Config{ + DelegationManagerAddress: contractAddrs.DelegationManager, + } + + chainReader, err := testclients.NewTestChainReaderFromConfig(anvilHttpEndpoint, config) + require.NoError(t, err) + + strategyAddr := common.HexToAddress("34634374736473673643") + + t.Run("GetStrategyAndUnderlyingToken", func(t *testing.T) { + strategy, undToken, err := chainReader.GetStrategyAndUnderlyingToken(ctx, strategyAddr) + assert.Zero(t, strategy) + assert.Zero(t, undToken) + assert.Error(t, err) + assert.Equal(t, err.Error(), "Failed to fetch token contract: no contract code at given address") + }) + + t.Run("GetStrategyAndUnderlyingERC20Token", func(t *testing.T) { + strategy, methods, undToken, err := chainReader.GetStrategyAndUnderlyingERC20Token(ctx, strategyAddr) + assert.Zero(t, strategy) + assert.Zero(t, methods) + assert.Zero(t, undToken) + assert.Error(t, err) + assert.Equal(t, err.Error(), "Failed to fetch token contract: no contract code at given address") + }) +} + func TestOperatorSetsAndSlashableShares(t *testing.T) { testConfig := testutils.GetDefaultTestConfig() anvilC, err := testutils.StartAnvilContainer(testConfig.AnvilStateFileName)