Skip to content

Commit

Permalink
feat: improve create batch error response (ethersphere#4729)
Browse files Browse the repository at this point in the history
  • Loading branch information
acha-bill authored Jul 31, 2024
1 parent 429a275 commit c518552
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 7 deletions.
6 changes: 6 additions & 0 deletions pkg/api/postage.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ func (s *Service) postageCreateHandler(w http.ResponseWriter, r *http.Request) {
jsonhttp.BadRequest(w, "invalid depth")
return
}
if errors.Is(err, postagecontract.ErrInsufficientValidity) {
logger.Debug("create batch: insufficient validity", "error", err)
logger.Error(nil, "create batch: insufficient validity")
jsonhttp.BadRequest(w, "insufficient amount for 24h minimum validity")
return
}
logger.Debug("create batch: create failed", "error", err)
logger.Error(nil, "create batch: create failed")
jsonhttp.InternalServerError(w, "cannot create batch")
Expand Down
65 changes: 58 additions & 7 deletions pkg/postage/postagecontract/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ var (

erc20ABI = abiutil.MustParseABI(sw3abi.ERC20ABIv0_6_5)

ErrBatchCreate = errors.New("batch creation failed")
ErrInsufficientFunds = errors.New("insufficient token balance")
ErrInvalidDepth = errors.New("invalid depth")
ErrBatchTopUp = errors.New("batch topUp failed")
ErrBatchDilute = errors.New("batch dilute failed")
ErrChainDisabled = errors.New("chain disabled")
ErrNotImplemented = errors.New("not implemented")
ErrBatchCreate = errors.New("batch creation failed")
ErrInsufficientFunds = errors.New("insufficient token balance")
ErrInvalidDepth = errors.New("invalid depth")
ErrBatchTopUp = errors.New("batch topUp failed")
ErrBatchDilute = errors.New("batch dilute failed")
ErrChainDisabled = errors.New("chain disabled")
ErrNotImplemented = errors.New("not implemented")
ErrInsufficientValidity = errors.New("insufficient validity")

approveDescription = "Approve tokens for postage operations"
createBatchDescription = "Postage batch creation"
Expand Down Expand Up @@ -301,6 +302,47 @@ func (c *postageContract) getBalance(ctx context.Context) (*big.Int, error) {
return abi.ConvertType(results[0], new(big.Int)).(*big.Int), nil
}

func (c *postageContract) getProperty(ctx context.Context, propertyName string, out any) error {
callData, err := c.postageStampContractABI.Pack(propertyName)
if err != nil {
return err
}

result, err := c.transactionService.Call(ctx, &transaction.TxRequest{
To: &c.postageStampContractAddress,
Data: callData,
})
if err != nil {
return err
}

results, err := c.postageStampContractABI.Unpack(propertyName, result)
if err != nil {
return err
}

if len(results) == 0 {
return errors.New("unexpected empty results")
}

abi.ConvertType(results[0], out)
return nil
}

func (c *postageContract) getMinInitialBalance(ctx context.Context) (uint64, error) {
var lastPrice uint64
err := c.getProperty(ctx, "lastPrice", &lastPrice)
if err != nil {
return 0, err
}
var minimumValidityBlocks uint64
err = c.getProperty(ctx, "minimumValidityBlocks", &minimumValidityBlocks)
if err != nil {
return 0, err
}
return lastPrice * minimumValidityBlocks, nil
}

func (c *postageContract) CreateBatch(ctx context.Context, initialBalance *big.Int, depth uint8, immutable bool, label string) (txHash common.Hash, batchID []byte, err error) {
if depth <= BucketDepth {
err = ErrInvalidDepth
Expand All @@ -318,6 +360,15 @@ func (c *postageContract) CreateBatch(ctx context.Context, initialBalance *big.I
return
}

minInitialBalance, err := c.getMinInitialBalance(ctx)
if err != nil {
return
}
if initialBalance.Cmp(big.NewInt(int64(minInitialBalance))) <= 0 {
err = fmt.Errorf("insufficient initial balance for 24h minimum validity. balance %d, minimum amount: %d: %w", initialBalance, minInitialBalance, ErrInsufficientValidity)
return
}

err = c.ExpireBatches(ctx)
if err != nil {
return
Expand Down
63 changes: 63 additions & 0 deletions pkg/postage/postagecontract/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ func TestCreateBatch(t *testing.T) {
if err != nil {
t.Fatal(err)
}

lastPriceCallData, err := postageStampContractABI.Pack("lastPrice")
if err != nil {
t.Fatal(err)
}

minValidityBlocksCallData, err := postageStampContractABI.Pack("minimumValidityBlocks")
if err != nil {
t.Fatal(err)
}

counter := 0
contract := postagecontract.New(
owner,
Expand Down Expand Up @@ -115,6 +126,12 @@ func TestCreateBatch(t *testing.T) {
}
}
}
if bytes.Equal(lastPriceCallData, request.Data) {
return big.NewInt(2).FillBytes(make([]byte, 32)), nil
}
if bytes.Equal(minValidityBlocksCallData, request.Data) {
return big.NewInt(25).FillBytes(make([]byte, 32)), nil
}
}
return nil, errors.New("unexpected call")
}),
Expand Down Expand Up @@ -193,6 +210,52 @@ func TestCreateBatch(t *testing.T) {
t.Fatalf("expected error %v. got %v", postagecontract.ErrInsufficientFunds, err)
}
})

t.Run("insufficient validity", func(t *testing.T) {
depth := uint8(10)
totalAmount := big.NewInt(102399)

lastPriceCallData, err := postageStampContractABI.Pack("lastPrice")
if err != nil {
t.Fatal(err)
}

minValidityBlocksCallData, err := postageStampContractABI.Pack("minimumValidityBlocks")
if err != nil {
t.Fatal(err)
}

contract := postagecontract.New(
owner,
postageStampAddress,
postageStampContractABI,
bzzTokenAddress,
transactionMock.New(
transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) {
if *request.To == bzzTokenAddress {
return big.NewInt(0).Add(totalAmount, big.NewInt(1)).FillBytes(make([]byte, 32)), nil
}
if bytes.Equal(lastPriceCallData, request.Data) {
return big.NewInt(2).FillBytes(make([]byte, 32)), nil
}
if bytes.Equal(minValidityBlocksCallData, request.Data) {
return big.NewInt(100).FillBytes(make([]byte, 32)), nil
}
return nil, errors.New("unexpected call")
}),
),
postageMock.New(),
postagestoreMock.New(),
true,
false,
)

_, _, err = contract.CreateBatch(ctx, initialBalance, depth, false, label)
if !errors.Is(err, postagecontract.ErrInsufficientValidity) {
t.Fatalf("expected error %v. got %v", postagecontract.ErrInsufficientValidity, err)
}
})

}

func newCreateEvent(postageContractAddress common.Address, batchId common.Hash) *types.Log {
Expand Down

0 comments on commit c518552

Please sign in to comment.