Skip to content

Commit

Permalink
feat: unwrap custom abi errors
Browse files Browse the repository at this point in the history
  • Loading branch information
mrekucci committed Oct 2, 2023
1 parent 0ca9296 commit 9eedee7
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 36 deletions.
20 changes: 4 additions & 16 deletions pkg/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down
27 changes: 22 additions & 5 deletions pkg/postage/postagecontract/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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)
Expand Down
9 changes: 8 additions & 1 deletion pkg/storageincentives/redistribution/redistribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
32 changes: 26 additions & 6 deletions pkg/storageincentives/staking/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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,
Expand All @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/transaction/mock/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
25 changes: 18 additions & 7 deletions pkg/transaction/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package transaction

import (
"bytes"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
}

Expand Down

0 comments on commit 9eedee7

Please sign in to comment.