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

[PVM] limit AddDepositOfferTx zero-limits offer check to berlin phase #384

Merged
merged 1 commit into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions vms/platformvm/test/expect/camino_expect.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import (
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/vms/components/avax"
"github.com/ava-labs/avalanchego/vms/components/multisig"
"github.com/ava-labs/avalanchego/vms/platformvm/config"
"github.com/ava-labs/avalanchego/vms/platformvm/deposit"
"github.com/ava-labs/avalanchego/vms/platformvm/locked"
"github.com/ava-labs/avalanchego/vms/platformvm/state"
"github.com/ava-labs/avalanchego/vms/platformvm/status"
"github.com/ava-labs/avalanchego/vms/platformvm/test"
"github.com/ava-labs/avalanchego/vms/platformvm/txs"
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
)
Expand Down Expand Up @@ -195,3 +197,8 @@ func Lock(t *testing.T, s *state.MockState, utxosMap map[ids.ShortID][]*avax.UTX
s.EXPECT().GetMultisigAlias(addr).Return(nil, database.ErrNotFound).AnyTimes()
}
}

func PhaseTime(t *testing.T, s *state.MockDiff, cfg *config.Config, phase test.Phase) {
t.Helper()
s.EXPECT().GetTimestamp().Return(test.PhaseTime(t, phase, cfg))
}
3 changes: 0 additions & 3 deletions vms/platformvm/txs/camino_add_deposit_offer_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ var (
errEmptyDepositOfferCreatorAddress = errors.New("deposit offer creator address is empty")
errWrongDepositOfferVersion = errors.New("wrong deposit offer version")
errNotZeroDepositOfferAmounts = errors.New("deposit offer rewardedAmount or depositedAmount isn't zero")
errZeroDepositOfferLimits = errors.New("deposit offer TotalMaxAmount and TotalMaxRewardAmount are zero")
)

// AddDepositOfferTx is an unsigned depositTx
Expand Down Expand Up @@ -50,8 +49,6 @@ func (tx *AddDepositOfferTx) SyntacticVerify(ctx *snow.Context) error {
return errWrongDepositOfferVersion
case tx.DepositOffer.RewardedAmount > 0 || tx.DepositOffer.DepositedAmount > 0:
return errNotZeroDepositOfferAmounts
case tx.DepositOffer.TotalMaxAmount == 0 && tx.DepositOffer.TotalMaxRewardAmount == 0:
return errZeroDepositOfferLimits
}

if err := tx.BaseTx.SyntacticVerify(ctx); err != nil {
Expand Down
10 changes: 0 additions & 10 deletions vms/platformvm/txs/camino_add_deposit_offer_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,6 @@ func TestAddDepositOfferTxSyntacticVerify(t *testing.T) {
},
expectedErr: errNotZeroDepositOfferAmounts,
},
"Zero TotalMaxAmount and TotalMaxRewardAmount": {
tx: &AddDepositOfferTx{
BaseTx: baseTx,
DepositOfferCreatorAddress: creatorAddress,
DepositOffer: &deposit.Offer{
UpgradeVersionID: codec.UpgradeVersion1,
},
},
expectedErr: errZeroDepositOfferLimits,
},
"Bad deposit offer": {
tx: &AddDepositOfferTx{
BaseTx: baseTx,
Expand Down
6 changes: 6 additions & 0 deletions vms/platformvm/txs/executor/camino_tx_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ var (
errExpiredProposalsMismatch = errors.New("expired proposals mismatch")
errWrongAdminProposal = errors.New("this type of proposal can't be admin-proposal")
errNotPermittedToCreateProposal = errors.New("don't have permission to create proposal of this type")
errZeroDepositOfferLimits = errors.New("deposit offer TotalMaxAmount and TotalMaxRewardAmount are zero")

ErrInvalidProposal = errors.New("proposal is semantically invalid")
)
Expand Down Expand Up @@ -1650,6 +1651,11 @@ func (e *CaminoStandardTxExecutor) AddDepositOfferTx(tx *txs.AddDepositOfferTx)
return errNotAthensPhase
}

if e.Config.IsBerlinPhaseActivated(chainTime) &&
tx.DepositOffer.TotalMaxAmount == 0 && tx.DepositOffer.TotalMaxRewardAmount == 0 {
return errZeroDepositOfferLimits
}

if len(e.Tx.Creds) < 2 {
return errWrongCredentialsNumber
}
Expand Down
79 changes: 73 additions & 6 deletions vms/platformvm/txs/executor/camino_tx_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5855,6 +5855,14 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
InterestRateNominator: 1,
TotalMaxRewardAmount: 100,
}
offerZeroLimits := &deposit.Offer{
UpgradeVersionID: codec.UpgradeVersion1,
Start: 0,
End: 1,
MinDuration: 1,
MaxDuration: 1,
MinAmount: deposit.OfferMinDepositAmount,
}

baseTx := txs.BaseTx{BaseTx: avax.BaseTx{
NetworkID: ctx.NetworkID,
Expand All @@ -5864,6 +5872,7 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {

tests := map[string]struct {
state func(*testing.T, *gomock.Controller, *txs.AddDepositOfferTx, ids.ID, *config.Config) *state.MockDiff
phase test.Phase
utx func() *txs.AddDepositOfferTx
signers [][]*secp256k1.PrivateKey
expectedErr error
Expand All @@ -5874,6 +5883,7 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
s.EXPECT().GetTimestamp().Return(cfg.AthensPhaseTime.Add(-1 * time.Second))
return s
},
phase: test.PhaseSunrise,
utx: func() *txs.AddDepositOfferTx {
return &txs.AddDepositOfferTx{
BaseTx: baseTx,
Expand All @@ -5887,15 +5897,36 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
},
expectedErr: errNotAthensPhase,
},
"BerlinPhase, zero TotalMaxAmount and TotalMaxRewardAmount": {
state: func(t *testing.T, c *gomock.Controller, utx *txs.AddDepositOfferTx, txID ids.ID, cfg *config.Config) *state.MockDiff {
s := state.NewMockDiff(c)
s.EXPECT().GetTimestamp().Return(cfg.BerlinPhaseTime)
return s
},
phase: test.PhaseLast,
utx: func() *txs.AddDepositOfferTx {
return &txs.AddDepositOfferTx{
BaseTx: baseTx,
DepositOffer: offerZeroLimits,
DepositOfferCreatorAddress: offerCreatorAddr,
DepositOfferCreatorAuth: &secp256k1fx.Input{SigIndices: []uint32{0}},
}
},
signers: [][]*secp256k1.PrivateKey{
{feeOwnerKey}, {offerCreatorKey},
},
expectedErr: errZeroDepositOfferLimits,
},
"Not offer creator": {
state: func(t *testing.T, c *gomock.Controller, utx *txs.AddDepositOfferTx, txID ids.ID, cfg *config.Config) *state.MockDiff {
s := state.NewMockDiff(c)
s.EXPECT().GetTimestamp().Return(cfg.AthensPhaseTime)
expect.PhaseTime(t, s, cfg, test.PhaseLast)
s.EXPECT().GetBaseFee().Return(test.TxFee, nil)
expect.VerifyLock(t, s, utx.Ins, []*avax.UTXO{feeUTXO}, []ids.ShortID{feeOwnerAddr}, nil)
s.EXPECT().GetAddressStates(utx.DepositOfferCreatorAddress).Return(as.AddressStateEmpty, nil)
return s
},
phase: test.PhaseLast,
utx: func() *txs.AddDepositOfferTx {
return &txs.AddDepositOfferTx{
BaseTx: baseTx,
Expand All @@ -5912,13 +5943,14 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
"Bad offer creator signature": {
state: func(t *testing.T, c *gomock.Controller, utx *txs.AddDepositOfferTx, txID ids.ID, cfg *config.Config) *state.MockDiff {
s := state.NewMockDiff(c)
s.EXPECT().GetTimestamp().Return(cfg.AthensPhaseTime)
expect.PhaseTime(t, s, cfg, test.PhaseLast)
s.EXPECT().GetBaseFee().Return(test.TxFee, nil)
expect.VerifyLock(t, s, utx.Ins, []*avax.UTXO{feeUTXO}, []ids.ShortID{feeOwnerAddr}, nil)
s.EXPECT().GetAddressStates(utx.DepositOfferCreatorAddress).Return(as.AddressStateOffersCreator, nil)
expect.VerifyMultisigPermission(t, s, []ids.ShortID{utx.DepositOfferCreatorAddress}, nil)
return s
},
phase: test.PhaseLast,
utx: func() *txs.AddDepositOfferTx {
return &txs.AddDepositOfferTx{
BaseTx: baseTx,
Expand All @@ -5935,7 +5967,7 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
"Supply overflow (v1, no existing offers)": {
state: func(t *testing.T, c *gomock.Controller, utx *txs.AddDepositOfferTx, txID ids.ID, cfg *config.Config) *state.MockDiff {
s := state.NewMockDiff(c)
s.EXPECT().GetTimestamp().Return(cfg.AthensPhaseTime)
expect.PhaseTime(t, s, cfg, test.PhaseLast)
s.EXPECT().GetBaseFee().Return(test.TxFee, nil)
expect.VerifyLock(t, s, utx.Ins, []*avax.UTXO{feeUTXO}, []ids.ShortID{feeOwnerAddr}, nil)
s.EXPECT().GetAddressStates(utx.DepositOfferCreatorAddress).Return(as.AddressStateOffersCreator, nil)
Expand All @@ -5945,6 +5977,7 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
s.EXPECT().GetAllDepositOffers().Return(nil, nil)
return s
},
phase: test.PhaseLast,
utx: func() *txs.AddDepositOfferTx {
return &txs.AddDepositOfferTx{
BaseTx: baseTx,
Expand All @@ -5961,7 +5994,7 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
},
"Supply overflow (v1, existing offers)": {
state: func(t *testing.T, c *gomock.Controller, utx *txs.AddDepositOfferTx, txID ids.ID, cfg *config.Config) *state.MockDiff {
chainTime := cfg.AthensPhaseTime
chainTime := test.PhaseTime(t, test.PhaseLast, cfg)
existingOffers := []*deposit.Offer{
{ // [0], expired
UpgradeVersionID: 1,
Expand Down Expand Up @@ -6031,6 +6064,7 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
s.EXPECT().GetAllDepositOffers().Return(existingOffers, nil)
return s
},
phase: test.PhaseLast,
utx: func() *txs.AddDepositOfferTx {
return &txs.AddDepositOfferTx{
BaseTx: baseTx,
Expand All @@ -6045,10 +6079,42 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
},
expectedErr: errSupplyOverflow,
},
"OK: v1, not BerlinPhase, zero TotalMaxAmount and TotalMaxRewardAmount": {
state: func(t *testing.T, c *gomock.Controller, utx *txs.AddDepositOfferTx, txID ids.ID, cfg *config.Config) *state.MockDiff {
s := state.NewMockDiff(c)
expect.PhaseTime(t, s, cfg, test.PhaseAthens)
s.EXPECT().GetBaseFee().Return(test.TxFee, nil)
expect.VerifyLock(t, s, utx.Ins, []*avax.UTXO{feeUTXO}, []ids.ShortID{feeOwnerAddr}, nil)
s.EXPECT().GetAddressStates(utx.DepositOfferCreatorAddress).Return(as.AddressStateOffersCreator, nil)
expect.VerifyMultisigPermission(t, s, []ids.ShortID{utx.DepositOfferCreatorAddress}, nil)
s.EXPECT().GetCurrentSupply(constants.PrimaryNetworkID).
Return(cfg.RewardConfig.SupplyCap-offer1.TotalMaxRewardAmount, nil)
s.EXPECT().GetAllDepositOffers().Return(nil, nil)

offer := *utx.DepositOffer
offer.ID = txID
s.EXPECT().SetDepositOffer(&offer)

expect.ConsumeUTXOs(t, s, utx.Ins)
return s
},
phase: test.PhaseAthens,
utx: func() *txs.AddDepositOfferTx {
return &txs.AddDepositOfferTx{
BaseTx: baseTx,
DepositOffer: offerZeroLimits,
DepositOfferCreatorAddress: offerCreatorAddr,
DepositOfferCreatorAuth: &secp256k1fx.Input{SigIndices: []uint32{0}},
}
},
signers: [][]*secp256k1.PrivateKey{
{feeOwnerKey}, {offerCreatorKey},
},
},
"OK: v1": {
state: func(t *testing.T, c *gomock.Controller, utx *txs.AddDepositOfferTx, txID ids.ID, cfg *config.Config) *state.MockDiff {
s := state.NewMockDiff(c)
s.EXPECT().GetTimestamp().Return(cfg.AthensPhaseTime)
expect.PhaseTime(t, s, cfg, test.PhaseLast)
s.EXPECT().GetBaseFee().Return(test.TxFee, nil)
expect.VerifyLock(t, s, utx.Ins, []*avax.UTXO{feeUTXO}, []ids.ShortID{feeOwnerAddr}, nil)
s.EXPECT().GetAddressStates(utx.DepositOfferCreatorAddress).Return(as.AddressStateOffersCreator, nil)
Expand All @@ -6064,6 +6130,7 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
expect.ConsumeUTXOs(t, s, utx.Ins)
return s
},
phase: test.PhaseLast,
utx: func() *txs.AddDepositOfferTx {
return &txs.AddDepositOfferTx{
BaseTx: baseTx,
Expand All @@ -6080,7 +6147,7 @@ func TestCaminoStandardTxExecutorAddDepositOfferTx(t *testing.T) {
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
backend := newExecutorBackend(t, caminoGenesisConf, test.PhaseLast, nil)
backend := newExecutorBackend(t, caminoGenesisConf, tt.phase, nil)

utx := tt.utx()
avax.SortTransferableInputsWithSigners(utx.Ins, tt.signers)
Expand Down
Loading