fix(amm): prevent swaps with identical tokens

This commit is contained in:
Ricardo Guilherme Schmidt 2026-07-17 20:45:42 -03:00
parent 0e6a38742d
commit 69c9783955
No known key found for this signature in database
GPG Key ID: 1396EA17DE132FFE
2 changed files with 53 additions and 3 deletions

View File

@ -24,9 +24,26 @@ Rectangle {
signal requestTokenSelect(string side)
signal previewRequested(var snapshot)
function isSameToken(left, right) {
if (!left || !right)
return false
if (left.address && right.address)
return String(left.address) === String(right.address)
return left === right
}
function setToken(side, token) {
if (side === "sell") root.sellToken = token
else root.buyToken = token
if (side === "sell") {
const previousSellToken = root.sellToken
if (root.isSameToken(token, root.buyToken))
root.buyToken = previousSellToken
root.sellToken = token
} else {
const previousBuyToken = root.buyToken
if (root.isSameToken(token, root.sellToken))
root.sellToken = previousBuyToken
root.buyToken = token
}
}
readonly property real sellReserve: sellToken ? (sellToken.reserve || 0) : 0
@ -65,11 +82,13 @@ Rectangle {
readonly property bool hasAmount: editingSide === "sell" ? parsedSellInput > 0 : parsedBuyInput > 0
readonly property bool tokensSelected: sellToken !== null && buyToken !== null
readonly property bool sameTokenSelected: isSameToken(sellToken, buyToken)
readonly property bool insufficientBalance: hasAmount && sellToken !== null && parsedSellAmount > (sellToken.balance || 0)
readonly property bool insufficientLiquidity: hasAmount && buyToken !== null && parsedBuyAmount > (buyToken.reserve || 0)
readonly property bool canSubmit: tokensSelected && hasAmount && parsedSellAmount > 0 && parsedBuyAmount > 0 && !insufficientBalance && !insufficientLiquidity
readonly property bool canSubmit: tokensSelected && !sameTokenSelected && hasAmount && parsedSellAmount > 0 && parsedBuyAmount > 0 && !insufficientBalance && !insufficientLiquidity
readonly property string submitButtonText: {
if (sameTokenSelected) return qsTr("Select different tokens")
if (!hasAmount || !tokensSelected) return qsTr("Enter an amount")
if (insufficientBalance) return qsTr("Insufficient balance")
if (insufficientLiquidity) return qsTr("Insufficient liquidity")

View File

@ -107,5 +107,36 @@ Item {
verify(snapshot.minReceived.length > 0)
verify(Number(snapshot.minReceived) < Number(snapshot.buyAmount))
}
function test_reselectingOppositeTokenSwapsPair() {
const page = createTemporaryObject(pageComponent, root)
verify(page)
const card = findChild(page, "swapCard")
verify(card)
card.setToken("sell", page.tokens[0])
card.setToken("buy", page.tokens[1])
card.setToken("buy", page.tokens[0])
compare(card.sellToken.address, page.tokens[1].address)
compare(card.buyToken.address, page.tokens[0].address)
verify(!card.sameTokenSelected)
}
function test_sameTokenPairCannotBePreviewed() {
const page = createTemporaryObject(pageComponent, root)
verify(page)
const card = findChild(page, "swapCard")
verify(card)
card.sellToken = page.tokens[0]
card.buyToken = page.tokens[0]
card.sellInput = "1"
card.editingSide = "sell"
verify(card.sameTokenSelected)
verify(!card.canSubmit)
compare(card.submitButtonText, "Select different tokens")
}
}
}