diff --git a/pkg/node/node.go b/pkg/node/node.go index 36fea876a8b..ddcdad37771 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -19,12 +19,10 @@ import ( "net/http" "path/filepath" "runtime" - "strings" "sync" "sync/atomic" "time" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/pkg/accounting" "github.com/ethersphere/bee/pkg/addressbook" @@ -71,6 +69,7 @@ import ( "github.com/ethersphere/bee/pkg/topology/lightnode" "github.com/ethersphere/bee/pkg/tracing" "github.com/ethersphere/bee/pkg/transaction" + "github.com/ethersphere/bee/pkg/util/abiutil" "github.com/ethersphere/bee/pkg/util/ioutil" "github.com/ethersphere/bee/pkg/util/nbhdutil" "github.com/ethersphere/bee/pkg/util/syncutil" @@ -681,10 +680,7 @@ func NewBee( return nil, errors.New("no known postage stamp addresses for this network") } - postageStampContractABI, err := abi.JSON(strings.NewReader(chainCfg.PostageStampABI)) - if err != nil { - return nil, fmt.Errorf("unable to parse postage stamp ABI: %w", err) - } + postageStampContractABI := abiutil.MustParseABI(chainCfg.PostageStampABI) bzzTokenAddress, err := postagecontract.LookupERC20Address(ctx, transactionService, postageStampContractAddress, postageStampContractABI, chainEnabled) if err != nil { @@ -1032,11 +1028,7 @@ func NewBee( stakingContractAddress = common.HexToAddress(o.StakingContractAddress) } - stakingContractABI, err := abi.JSON(strings.NewReader(chainCfg.StakingABI)) - if err != nil { - return nil, fmt.Errorf("unable to parse staking ABI: %w", err) - } - stakingContract := staking.New(swarmAddress, overlayEthAddress, stakingContractAddress, stakingContractABI, bzzTokenAddress, transactionService, common.BytesToHash(nonce)) + stakingContract := staking.New(swarmAddress, overlayEthAddress, stakingContractAddress, abiutil.MustParseABI(chainCfg.StakingABI), bzzTokenAddress, transactionService, common.BytesToHash(nonce)) var ( pullerService *puller.Puller @@ -1059,16 +1051,12 @@ func NewBee( } redistributionContractAddress = common.HexToAddress(o.RedistributionContractAddress) } - redistributionContractABI, err := abi.JSON(strings.NewReader(chainCfg.RedistributionABI)) - if err != nil { - return nil, fmt.Errorf("unable to parse redistribution ABI: %w", err) - } isFullySynced := func() bool { return localStore.ReserveSize() >= reserveTreshold && pullerService.SyncRate() == 0 } - redistributionContract := redistribution.New(swarmAddress, logger, transactionService, redistributionContractAddress, redistributionContractABI) + redistributionContract := redistribution.New(swarmAddress, logger, transactionService, redistributionContractAddress, abiutil.MustParseABI(chainCfg.RedistributionABI)) agent, err = storageincentives.New( swarmAddress, overlayEthAddress, diff --git a/pkg/postage/postagecontract/contract.go b/pkg/postage/postagecontract/contract.go index 666037c39d6..8674b786b43 100644 --- a/pkg/postage/postagecontract/contract.go +++ b/pkg/postage/postagecontract/contract.go @@ -148,25 +148,36 @@ func (c *postageContract) expireLimitedBatches(ctx context.Context, count *big.I return nil } -func (c *postageContract) sendApproveTransaction(ctx context.Context, amount *big.Int) (*types.Receipt, error) { +func (c *postageContract) sendApproveTransaction(ctx context.Context, amount *big.Int) (receipt *types.Receipt, err error) { callData, err := erc20ABI.Pack("approve", c.postageStampContractAddress, amount) if err != nil { return nil, err } - txHash, err := c.transactionService.Send(ctx, &transaction.TxRequest{ + request := &transaction.TxRequest{ To: &c.bzzTokenAddress, Data: callData, GasPrice: sctx.GetGasPrice(ctx), GasLimit: 65000, Value: big.NewInt(0), Description: approveDescription, - }, transaction.DefaultTipBoostPercent) + } + + defer func() { + err = c.transactionService.UnwrapABIError( + ctx, + request, + err, + c.postageStampContractABI.Errors, + ) + }() + + txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return nil, err } - receipt, err := c.transactionService.WaitForReceipt(ctx, txHash) + receipt, err = c.transactionService.WaitForReceipt(ctx, txHash) if err != nil { return nil, err } @@ -187,8 +198,14 @@ func (c *postageContract) sendTransaction(ctx context.Context, callData []byte, Value: big.NewInt(0), Description: desc, } + defer func() { - err = c.transactionService.UnwrapRevertReason(ctx, request, err) + err = c.transactionService.UnwrapABIError( + ctx, + request, + err, + c.postageStampContractABI.Errors, + ) }() txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) diff --git a/pkg/storageincentives/redistribution/redistribution.go b/pkg/storageincentives/redistribution/redistribution.go index ce0692da943..8b83537cf90 100644 --- a/pkg/storageincentives/redistribution/redistribution.go +++ b/pkg/storageincentives/redistribution/redistribution.go @@ -181,7 +181,14 @@ func (c *contract) ReserveSalt(ctx context.Context) ([]byte, error) { } func (c *contract) sendAndWait(ctx context.Context, request *transaction.TxRequest, boostPercent int) (txHash common.Hash, err error) { - defer func() { err = c.txService.UnwrapRevertReason(ctx, request, err) }() + defer func() { + err = c.txService.UnwrapABIError( + ctx, + request, + err, + c.incentivesContractABI.Errors, + ) + }() txHash, err = c.txService.Send(ctx, request, boostPercent) if err != nil { diff --git a/pkg/storageincentives/staking/contract.go b/pkg/storageincentives/staking/contract.go index aa05267c197..014b1a67adc 100644 --- a/pkg/storageincentives/staking/contract.go +++ b/pkg/storageincentives/staking/contract.go @@ -77,25 +77,36 @@ func New( } } -func (c *contract) sendApproveTransaction(ctx context.Context, amount *big.Int) (*types.Receipt, error) { +func (c *contract) sendApproveTransaction(ctx context.Context, amount *big.Int) (receipt *types.Receipt, err error) { callData, err := erc20ABI.Pack("approve", c.stakingContractAddress, amount) if err != nil { return nil, err } - txHash, err := c.transactionService.Send(ctx, &transaction.TxRequest{ + request := &transaction.TxRequest{ To: &c.bzzTokenAddress, Data: callData, GasPrice: sctx.GetGasPrice(ctx), GasLimit: 65000, Value: big.NewInt(0), Description: approveDescription, - }, 0) + } + + defer func() { + err = c.transactionService.UnwrapABIError( + ctx, + request, + err, + c.stakingContractABI.Errors, + ) + }() + + txHash, err := c.transactionService.Send(ctx, request, 0) if err != nil { return nil, err } - receipt, err := c.transactionService.WaitForReceipt(ctx, txHash) + receipt, err = c.transactionService.WaitForReceipt(ctx, txHash) if err != nil { return nil, err } @@ -107,7 +118,7 @@ func (c *contract) sendApproveTransaction(ctx context.Context, amount *big.Int) return receipt, nil } -func (c *contract) sendTransaction(ctx context.Context, callData []byte, desc string) (*types.Receipt, error) { +func (c *contract) sendTransaction(ctx context.Context, callData []byte, desc string) (receipt *types.Receipt, err error) { request := &transaction.TxRequest{ To: &c.stakingContractAddress, Data: callData, @@ -117,12 +128,21 @@ func (c *contract) sendTransaction(ctx context.Context, callData []byte, desc st Description: desc, } + defer func() { + err = c.transactionService.UnwrapABIError( + ctx, + request, + err, + c.stakingContractABI.Errors, + ) + }() + txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return nil, err } - receipt, err := c.transactionService.WaitForReceipt(ctx, txHash) + receipt, err = c.transactionService.WaitForReceipt(ctx, txHash) if err != nil { return nil, err } diff --git a/pkg/transaction/mock/transaction.go b/pkg/transaction/mock/transaction.go index 6110dfeea1d..7478daa63e6 100644 --- a/pkg/transaction/mock/transaction.go +++ b/pkg/transaction/mock/transaction.go @@ -97,7 +97,7 @@ func (m *transactionServiceMock) TransactionFee(ctx context.Context, txHash comm return big.NewInt(0), nil } -func (m *transactionServiceMock) UnwrapRevertReason(_ context.Context, _ *transaction.TxRequest, err error) error { +func (m *transactionServiceMock) UnwrapABIError(_ context.Context, _ *transaction.TxRequest, err error, _ map[string]abi.Error) error { return err } diff --git a/pkg/transaction/transaction.go b/pkg/transaction/transaction.go index c4246631023..1f9431c3c3a 100644 --- a/pkg/transaction/transaction.go +++ b/pkg/transaction/transaction.go @@ -5,6 +5,7 @@ package transaction import ( + "bytes" "errors" "fmt" "io" @@ -95,9 +96,9 @@ type Service interface { CancelTransaction(ctx context.Context, originalTxHash common.Hash) (common.Hash, error) // TransactionFee retrieves the transaction fee TransactionFee(ctx context.Context, txHash common.Hash) (*big.Int, error) - // UnwrapRevertReason tries to unwrap the revert reason if the given error is not nil. - // The original error is wrapped in case the revert reason exists. - UnwrapRevertReason(ctx context.Context, req *TxRequest, err error) error + // UnwrapABIError tries to unwrap the ABI error if the given error is not nil. + // The original error is wrapped together with the ABI error if it exists. + UnwrapABIError(ctx context.Context, req *TxRequest, err error, abiErrors map[string]abi.Error) error } type transactionService struct { @@ -589,14 +590,24 @@ func (t *transactionService) TransactionFee(ctx context.Context, txHash common.H return trx.Cost(), nil } -func (t *transactionService) UnwrapRevertReason(ctx context.Context, req *TxRequest, err error) error { +func (t *transactionService) UnwrapABIError(ctx context.Context, req *TxRequest, err error, abiErrors map[string]abi.Error) error { if err == nil { return nil } - if res, cErr := t.Call(ctx, req); cErr == nil { - if reason, uErr := abi.UnpackRevert(res); uErr == nil { - err = fmt.Errorf("%w: reason: %s", err, reason) + res, cErr := t.Call(ctx, req) + if cErr != nil { + return err + } + + if reason, uErr := abi.UnpackRevert(res); uErr == nil { + return fmt.Errorf("%w: %s", err, reason) + } + + for _, abiError := range abiErrors { + if bytes.Equal(res[:4], abiError.ID[:4]) { + //abiError.Unpack(res[4:]) + return fmt.Errorf("%w: %s", err, abiError) } }