@@ -4,6 +4,7 @@ pragma solidity ^0.8.23;
4
4
import {IQuarkWallet} from "quark-core/src/interfaces/IQuarkWallet.sol " ;
5
5
import {TransferActions} from "../DeFiScripts.sol " ;
6
6
import "./BridgeRoutes.sol " ;
7
+ import "./Strings.sol " ;
7
8
8
9
contract QuarkBuilder {
9
10
/* ===== Constants ===== */
@@ -63,12 +64,15 @@ contract QuarkBuilder {
63
64
}
64
65
65
66
struct Payment {
66
- // TODO: rename?
67
67
bool isToken;
68
+ // Note: Payment `currency` should be the same across chains
68
69
string currency;
69
- // TODO: make into struct?
70
- uint256 [] chainIds;
71
- uint256 [] maxCosts;
70
+ PaymentMaxCost[] maxCosts;
71
+ }
72
+
73
+ struct PaymentMaxCost {
74
+ uint256 chainId;
75
+ uint256 amount;
72
76
}
73
77
74
78
/* ===== Output Types ===== */
@@ -122,7 +126,6 @@ contract QuarkBuilder {
122
126
uint256 destinationChainId;
123
127
}
124
128
125
-
126
129
/* ===== Internal/Intermediate Types ===== */
127
130
128
131
// Note: This is just the AssetPositions type with an extra `chainId` field
@@ -135,17 +138,12 @@ contract QuarkBuilder {
135
138
AccountBalance[] accountBalances;
136
139
}
137
140
138
- // TODO: convert strings to lower case before comparing. maybe rename to `compareSymbols`
139
- function compareStrings (string memory a , string memory b ) internal pure returns (bool ) {
140
- return keccak256 (abi.encodePacked ((a))) == keccak256 (abi.encodePacked ((b)));
141
- }
142
-
143
- function filterAssetPositionsForSymbol (string memory assetSymbol , ChainAccount[] memory chainAccountsList ) internal pure returns (AssetPositionsWithChainId[] memory ) {
141
+ function filterAssetPositions (string memory assetSymbol , ChainAccount[] memory chainAccountsList ) internal pure returns (AssetPositionsWithChainId[] memory ) {
144
142
uint numMatches = 0 ;
145
143
// First loop to count the number of matching AssetPositions
146
144
for (uint i = 0 ; i < chainAccountsList.length ; ++ i) {
147
145
for (uint j = 0 ; j < chainAccountsList[i].assetPositionsList.length ; ++ j) {
148
- if (compareStrings (chainAccountsList[i].assetPositionsList[j].symbol, assetSymbol)) {
146
+ if (Strings. stringEqIgnoreCase (chainAccountsList[i].assetPositionsList[j].symbol, assetSymbol)) {
149
147
numMatches++ ;
150
148
}
151
149
}
@@ -156,7 +154,7 @@ contract QuarkBuilder {
156
154
// Second loop to populate the matchingAssetPositions array
157
155
for (uint i = 0 ; i < chainAccountsList.length ; ++ i) {
158
156
for (uint j = 0 ; j < chainAccountsList[i].assetPositionsList.length ; ++ j) {
159
- if (compareStrings (chainAccountsList[i].assetPositionsList[j].symbol, assetSymbol)) {
157
+ if (Strings. stringEqIgnoreCase (chainAccountsList[i].assetPositionsList[j].symbol, assetSymbol)) {
160
158
AssetPositions memory assetPositions = chainAccountsList[i].assetPositionsList[j];
161
159
matchingAssetPositions[index] = AssetPositionsWithChainId ({
162
160
chainId: chainAccountsList[i].chainId,
@@ -182,7 +180,7 @@ contract QuarkBuilder {
182
180
continue
183
181
}
184
182
for (uint j = 0 ; j < chainAccountsList[i].assetPositionsList.length ; ++ j) {
185
- if (compareStrings (chainAccountsList[i].assetPositionsList[j].symbol, assetSymbol)) {
183
+ if (Strings. stringEqIgnoreCase (chainAccountsList[i].assetPositionsList[j].symbol, assetSymbol)) {
186
184
AssetPositions memory assetPositions = chainAccountsList[i].assetPositionsList[j];
187
185
return AssetPositionsWithChainId ({
188
186
chainId: chainAccountsList[i].chainId,
@@ -217,14 +215,10 @@ contract QuarkBuilder {
217
215
Payment calldata payment ,
218
216
ChainAccounts[] calldata chainAccountsList
219
217
) external pure returns (BuilderResult memory ) {
220
- if (payment.chainIds.length != payment.maxCosts.length ) {
221
- revert InvalidInput ();
222
- }
223
-
224
- AssetPositionsWithChainId[] transferAssetPositions = filterAssetPositionsForSymbol (assetSymbol, chainAccountsList);
218
+ AssetPositionsWithChainId[] transferAssetPositions = filterAssetPositions (assetSymbol, chainAccountsList);
225
219
AssetPositionsWithChainId[] paymentAssetPositions;
226
220
if (payment.isToken) {
227
- paymentAssetPositions = filterAssetPositionsForSymbol (payment.currency, chainAccountsList);
221
+ paymentAssetPositions = filterAssetPositions (payment.currency, chainAccountsList);
228
222
}
229
223
230
224
// INSUFFICIENT_FUNDS
@@ -245,11 +239,13 @@ contract QuarkBuilder {
245
239
// (amount of payment token on chain id - transfer amount (IF IS SAME TOKEN AND SAME CHAIN ID)) < maxPaymentAmount on chain id
246
240
// Note: This check assumes we will not be bridging payment tokens for the user
247
241
if (payment.isToken) {
248
- for (uint i = 0 ; i < payment.chainIds.length ; ++ i) {
249
- AssetPositionsWithChainId memory paymentAssetPosition = getAssetPositionForSymbolAndChain (payment.currency, payment.chainIds[i], chainAccountsList);
242
+ for (uint i = 0 ; i < payment.maxCosts.length ; ++ i) {
243
+ PaymentMaxCost memory maxCost = payment.maxCosts[i];
244
+ AssetPositionsWithChainId memory paymentAssetPosition = getAssetPositionForSymbolAndChain (payment.currency, maxCost.chainId, chainAccountsList);
250
245
uint256 paymentAssetBalanceOnChain = sumUpBalances (paymentAssetPosition);
251
- uint256 paymentAssetNeeded = payment.maxCosts[i];
252
- if (payment.currency == assetSymbol && chainId == payment.chainIds[i]) {
246
+ uint256 paymentAssetNeeded = maxCost.amount;
247
+ // If the payment token is the transfer token and this is the target chain, we need to account for the transfer amount when checking token balances
248
+ if (Strings.stringEqIgnoreCase (payment.currency, assetSymbol) && chainId == maxCost.chainId) {
253
249
paymentAssetNeeded += transferAmount;
254
250
}
255
251
if (paymentAssetBalanceOnChain < paymentAssetNeeded) {
0 commit comments