Skip to content

Commit 50844ee

Browse files
committed
Improve swap RPC validation
1 parent a68e772 commit 50844ee

File tree

1 file changed

+48
-19
lines changed

1 file changed

+48
-19
lines changed

pkg/code/server/transaction/swap.go

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
commonpb "github.com/code-payments/code-protobuf-api/generated/go/common/v1"
1616
transactionpb "github.com/code-payments/code-protobuf-api/generated/go/transaction/v2"
1717

18+
"github.com/code-payments/code-server/pkg/code/balance"
1819
"github.com/code-payments/code-server/pkg/code/common"
1920
"github.com/code-payments/code-server/pkg/code/data/intent"
2021
"github.com/code-payments/code-server/pkg/code/data/nonce"
@@ -104,6 +105,14 @@ func (s *transactionServer) StartSwap(streamer transactionpb.Transaction_StartSw
104105
// Section: Validation
105106
//
106107

108+
_, err = s.data.GetSwapById(ctx, swapId)
109+
if err == nil {
110+
return handleStartSwapError(streamer, NewSwapDeniedError("attempt to reuse swap id"))
111+
} else if err != swap.ErrNotFound {
112+
log.WithError(err).Warn("failure checking for existing swap record")
113+
return handleStartSwapError(streamer, err)
114+
}
115+
107116
if bytes.Equal(fromMint.PublicKey().ToBytes(), toMint.PublicKey().ToBytes()) {
108117
return handleStartSwapError(streamer, NewSwapValidationError("must swap between two different mints"))
109118
}
@@ -112,22 +121,59 @@ func (s *transactionServer) StartSwap(streamer transactionpb.Transaction_StartSw
112121
return handleStartSwapError(streamer, NewSwapValidationError("amount must be positive"))
113122
}
114123

115-
_, err = common.GetVmConfigForMint(ctx, s.data, fromMint)
124+
sourceVmConfig, err := common.GetVmConfigForMint(ctx, s.data, fromMint)
116125
if err == common.ErrUnsupportedMint {
117126
return handleStartSwapError(streamer, NewSwapValidationError("invalid source mint"))
118127
} else if err != nil {
119128
log.WithError(err).Warn("failure getting source vm config")
120129
return handleStartSwapError(streamer, err)
121130
}
122131

123-
_, err = common.GetVmConfigForMint(ctx, s.data, toMint)
132+
destinationVmConfig, err := common.GetVmConfigForMint(ctx, s.data, toMint)
124133
if err == common.ErrUnsupportedMint {
125134
return handleStartSwapError(streamer, NewSwapValidationError("invalid destination mint"))
126135
} else if err != nil {
127136
log.WithError(err).Warn("failure getting destination vm config")
128137
return handleStartSwapError(streamer, err)
129138
}
130139

140+
ownerSourceTimelockVault, err := owner.ToTimelockVault(sourceVmConfig)
141+
if err != nil {
142+
log.WithError(err).Warn("failure getting owner destination timelock vault")
143+
return handleStartSwapError(streamer, err)
144+
}
145+
146+
_, err = s.data.GetTimelockByVault(ctx, ownerSourceTimelockVault.PublicKey().ToBase58())
147+
if err == timelock.ErrTimelockNotFound {
148+
return handleStartSwapError(streamer, NewSwapValidationError("source timelock vault account not opened"))
149+
} else if err != nil {
150+
log.WithError(err).Warn("failure getting source timelock record")
151+
return handleStartSwapError(streamer, err)
152+
}
153+
154+
balance, err := balance.CalculateFromCache(ctx, s.data, ownerSourceTimelockVault)
155+
if err != nil {
156+
log.WithError(err).Warn("failure getting owner source timelock vault balance")
157+
return handleStartSwapError(streamer, err)
158+
}
159+
if balance < startCurrencyCreatorSwapReq.Amount {
160+
return handleStartSwapError(streamer, NewSwapValidationError("insufficient balance"))
161+
}
162+
163+
ownerDestinationTimelockVault, err := owner.ToTimelockVault(destinationVmConfig)
164+
if err != nil {
165+
log.WithError(err).Warn("failure getting owner destination timelock vault")
166+
return handleStartSwapError(streamer, err)
167+
}
168+
169+
_, err = s.data.GetTimelockByVault(ctx, ownerDestinationTimelockVault.PublicKey().ToBase58())
170+
if err == timelock.ErrTimelockNotFound {
171+
return handleStartSwapError(streamer, NewSwapValidationError("destination timelock vault account not opened"))
172+
} else if err != nil {
173+
log.WithError(err).Warn("failure getting destination timelock record")
174+
return handleStartSwapError(streamer, err)
175+
}
176+
131177
_, err = s.data.GetIntent(ctx, startCurrencyCreatorSwapReq.FundingId)
132178
if err == nil {
133179
return handleStartSwapError(streamer, NewSwapValidationError("funding intent already exists"))
@@ -475,11 +521,6 @@ func (s *transactionServer) Swap(streamer transactionpb.Transaction_SwapServer)
475521
log.WithError(err).Warn("failure getting owner source vm swap ata")
476522
return handleSwapError(streamer, err)
477523
}
478-
ownerDestinationTimelockVault, err := owner.ToTimelockVault(destinationVmConfig)
479-
if err != nil {
480-
log.WithError(err).Warn("failure getting owner destination timelock vault")
481-
return handleSwapError(streamer, err)
482-
}
483524

484525
//
485526
// Section: Validation
@@ -497,18 +538,6 @@ func (s *transactionServer) Swap(streamer transactionpb.Transaction_SwapServer)
497538
return handleSwapError(streamer, NewSwapValidationError("owner cannot be swap authority"))
498539
}
499540

500-
if bytes.Equal(fromMint.PublicKey().ToBytes(), toMint.PublicKey().ToBytes()) {
501-
return handleSwapError(streamer, NewSwapValidationError("must swap between two different mints"))
502-
}
503-
504-
_, err = s.data.GetTimelockByVault(ctx, ownerDestinationTimelockVault.PublicKey().ToBase58())
505-
if err == timelock.ErrTimelockNotFound {
506-
return handleSwapError(streamer, NewSwapValidationError("destination timelock vault account not opened"))
507-
} else if err != nil {
508-
log.WithError(err).Warn("failure getting destination timelock record")
509-
return handleSwapError(streamer, err)
510-
}
511-
512541
// todo: for any of these invalid funding cases, we should cancel the swap
513542
intentRecord, err := s.data.GetIntent(ctx, swapRecord.FundingId)
514543
if err != nil {

0 commit comments

Comments
 (0)