Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: set 1000 sats as minimum amount that can be withdrawn #2362

Merged
merged 10 commits into from
Jun 21, 2024
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
* [2243](https://github.com/zeta-chain/node/pull/2243) - fix incorrect bitcoin outbound height in the CCTX outbound parameter
* [2256](https://github.com/zeta-chain/node/pull/2256) - fix rate limiter falsely included reverted non-withdraw cctxs
* [2327](https://github.com/zeta-chain/node/pull/2327) - partially cherry picked the fix to Bitcoin outbound dust amount
* [2362](https://github.com/zeta-chain/node/pull/2362) - set 1000 satoshis as minimum BTC amount that can be withdrawn from zEVM

### CI

Expand Down
14 changes: 10 additions & 4 deletions x/crosschain/keeper/evm_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/zeta-chain/zetacore/cmd/zetacored/config"
"github.com/zeta-chain/zetacore/pkg/chains"
"github.com/zeta-chain/zetacore/pkg/coin"
"github.com/zeta-chain/zetacore/pkg/constant"
"github.com/zeta-chain/zetacore/x/crosschain/types"
fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types"
observertypes "github.com/zeta-chain/zetacore/x/observer/types"
Expand Down Expand Up @@ -286,15 +287,20 @@ func ValidateZrc20WithdrawEvent(event *zrc20.ZRC20Withdrawal, chainID int64) err
// The event was parsed; that means the user has deposited tokens to the contract.

if chains.IsBitcoinChain(chainID) {
if event.Value.Cmp(big.NewInt(0)) <= 0 {
return fmt.Errorf("ParseZRC20WithdrawalEvent: invalid amount %s", event.Value.String())
if event.Value.Cmp(big.NewInt(constant.BTCWithdrawalDustAmount)) < 0 {
return errorsmod.Wrapf(
types.ErrInvalidWithdrawalAmount,
"withdraw amount %s is less than minimum amount %d",
event.Value.String(),
constant.BTCWithdrawalDustAmount,
)
}
addr, err := chains.DecodeBtcAddress(string(event.To), chainID)
if err != nil {
return fmt.Errorf("ParseZRC20WithdrawalEvent: invalid address %s: %s", event.To, err)
return errorsmod.Wrapf(types.ErrInvalidAddress, "invalid address %s", string(event.To))
}
if !chains.IsBtcAddressSupported(addr) {
return fmt.Errorf("ParseZRC20WithdrawalEvent: unsupported address %s", string(event.To))
return errorsmod.Wrapf(types.ErrInvalidAddress, "unsupported address %s", string(event.To))
}
}
return nil
Expand Down
16 changes: 12 additions & 4 deletions x/crosschain/keeper/evm_hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/zeta-chain/zetacore/cmd/zetacored/config"
"github.com/zeta-chain/zetacore/pkg/chains"
"github.com/zeta-chain/zetacore/pkg/constant"
keepertest "github.com/zeta-chain/zetacore/testutil/keeper"
"github.com/zeta-chain/zetacore/testutil/sample"
crosschainkeeper "github.com/zeta-chain/zetacore/x/crosschain/keeper"
Expand Down Expand Up @@ -164,14 +165,21 @@ func TestValidateZrc20WithdrawEvent(t *testing.T) {
require.NoError(t, err)
})

t.Run("unable to validate a event with an invalid amount", func(t *testing.T) {
t.Run("unable to validate a btc withdrawal event with an invalid amount", func(t *testing.T) {
btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent(
*sample.GetValidZRC20WithdrawToBTC(t).Logs[3],
)
require.NoError(t, err)
btcMainNetWithdrawalEvent.Value = big.NewInt(0)

// 1000 satoshis is the minimum amount that can be withdrawn
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
btcMainNetWithdrawalEvent.Value = big.NewInt(constant.BTCWithdrawalDustAmount)
err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId)
require.ErrorContains(t, err, "ParseZRC20WithdrawalEvent: invalid amount")
require.NoError(t, err)

// 999 satoshis cannot be withdrawn
btcMainNetWithdrawalEvent.Value = big.NewInt(constant.BTCWithdrawalDustAmount - 1)
err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId)
require.ErrorContains(t, err, "less than minimum amount")
})

t.Run("unable to validate a event with an invalid chain ID", func(t *testing.T) {
Expand Down Expand Up @@ -822,7 +830,7 @@ func TestKeeper_ProcessLogs(t *testing.T) {
}

err := k.ProcessLogs(ctx, block.Logs, sample.EthAddress(), "")
require.ErrorContains(t, err, "ParseZRC20WithdrawalEvent: invalid address")
require.ErrorContains(t, err, "invalid address")
cctxList := k.GetAllCrossChainTx(ctx)
require.Len(t, cctxList, 0)
})
Expand Down
1 change: 1 addition & 0 deletions x/crosschain/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ var (
ErrInvalidRateLimiterFlags = errorsmod.Register(ModuleName, 1152, "invalid rate limiter flags")
ErrMaxTxOutTrackerHashesReached = errorsmod.Register(ModuleName, 1153, "max tx out tracker hashes reached")
ErrInitiatitingOutbound = errorsmod.Register(ModuleName, 1154, "cannot initiate outbound")
ErrInvalidWithdrawalAmount = errorsmod.Register(ModuleName, 1155, "invalid withdrawal amount")
)
Loading