Skip to content

Commit

Permalink
fix: update height if staked when height decreases
Browse files Browse the repository at this point in the history
  • Loading branch information
istae committed Oct 22, 2024
1 parent 253d382 commit 9e186ce
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 24 deletions.
34 changes: 15 additions & 19 deletions pkg/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1006,36 +1006,32 @@ func NewBee(

if chainEnabled {

if changedOverlay {
stake, err := stakingContract.GetPotentialStake(ctx)
if err != nil {
return nil, err
}
if stake.Cmp(big.NewInt(0)) > 0 {
stake, err := stakingContract.GetPotentialStake(ctx)
if err != nil {
return nil, err
}

if stake.Cmp(big.NewInt(0)) > 0 {

if changedOverlay {
logger.Debug("changing overlay address in staking contract")
tx, err := stakingContract.ChangeStakeOverlay(ctx, common.BytesToHash(nonce))
if err != nil {
return nil, fmt.Errorf("cannot change staking overlay address: %v", err.Error())
}
logger.Info("overlay address changed in staking contract", "transaction", tx)
}
}

// make sure that the staking contract has the up to date height
tx, updated, err := stakingContract.UpdateHeight(ctx)
if err != nil {
return nil, err
}
if updated {
logger.Info("updated new reserve capacity doubling height in the staking contract", "transaction", tx, "new_height", o.ReserveCapacityDoubling)
}

if o.ReserveCapacityDoubling > 0 {
stake, err := stakingContract.GetPotentialStake(ctx)
// make sure that the staking contract has the up to date height
tx, updated, err := stakingContract.UpdateHeight(ctx)
if err != nil {
return nil, err
}
if stake.Cmp(big.NewInt(0)) > 0 {
if updated {
logger.Info("updated new reserve capacity doubling height in the staking contract", "transaction", tx, "new_height", o.ReserveCapacityDoubling)
}

if o.ReserveCapacityDoubling > 0 {
// Check if the staked amount is sufficient to cover the additional neighborhoods.
// The staked amount must be at least 2^h * MinimumStake.
if stake.Cmp(big.NewInt(0).Mul(big.NewInt(1<<o.ReserveCapacityDoubling), staking.MinimumStakeAmount)) < 0 {
Expand Down
4 changes: 4 additions & 0 deletions pkg/storageincentives/staking/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ func (c *contract) DepositStake(ctx context.Context, stakedAmount *big.Int) (com
}
}

if big.NewInt(0).Add(prevStakedAmount, stakedAmount).Cmp(big.NewInt(0).Mul(big.NewInt(1<<c.height), MinimumStakeAmount)) < 0 {
return common.Hash{}, fmt.Errorf("stake amount does not sufficiently cover the additional reserve capacity: %w", ErrInsufficientStakeAmount)
}

balance, err := c.getBalance(ctx)
if err != nil {
return common.Hash{}, err
Expand Down
73 changes: 68 additions & 5 deletions pkg/storageincentives/staking/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,73 @@ func TestDepositStake(t *testing.T) {
}
})

t.Run("insufficient stake amount", func(t *testing.T) {
t.Run("sufficient stake amount extra height", func(t *testing.T) {
t.Parallel()

totalAmount := big.NewInt(0)
balance := big.NewInt(0).Mul(staking.MinimumStakeAmount, big.NewInt(2))
prevStake := staking.MinimumStakeAmount

expectedCallData, err := stakingContractABI.Pack("manageStake", nonce, staking.MinimumStakeAmount, stakingHeight)
if err != nil {
t.Fatal(err)
}

contract := staking.New(
owner,
stakingContractAddress,
stakingContractABI,
bzzTokenAddress,
transactionMock.New(
transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) {
if *request.To == bzzTokenAddress {
return txHashApprove, nil
}
if *request.To == stakingContractAddress {
if !bytes.Equal(expectedCallData[:80], request.Data[:80]) {
return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data)
}
return txHashDeposited, nil
}
return common.Hash{}, errors.New("sent to wrong contract")
}),
transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) {
if txHash == txHashDeposited {
return &types.Receipt{
Status: 1,
}, nil
}
if txHash == txHashApprove {
return &types.Receipt{
Status: 1,
}, nil
}
return nil, errors.New("unknown tx hash")
}),
transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) {
if *request.To == bzzTokenAddress {
return balance.FillBytes(make([]byte, 32)), nil
}
if *request.To == stakingContractAddress {
return getPotentialStakeResponse(t, prevStake), nil
}
return nil, errors.New("unexpected call")
}),
),
nonce,
false,
1,
)

_, err = contract.DepositStake(ctx, stakedAmount)
if err != nil {
t.Fatal(err)
}
})

t.Run("insufficient stake amount extra height", func(t *testing.T) {
t.Parallel()

totalAmount := big.NewInt(0).Mul(staking.MinimumStakeAmount, big.NewInt(10))
prevStake := big.NewInt(0)

contract := staking.New(
Expand All @@ -314,11 +377,11 @@ func TestDepositStake(t *testing.T) {
),
nonce,
false,
stakingHeight,
1,
)

_, err := contract.DepositStake(ctx, big.NewInt(100000000000000000))
if !errors.Is(err, staking.ErrInsufficientFunds) {
_, err := contract.DepositStake(ctx, stakedAmount)
if !errors.Is(err, staking.ErrInsufficientStakeAmount) {
t.Fatal(fmt.Errorf("wanted %w, got %w", staking.ErrInsufficientStakeAmount, err))
}
})
Expand Down

0 comments on commit 9e186ce

Please sign in to comment.