Skip to content

Commit 3e4f887

Browse files
committed
Create Strings library, create PaymentMaxCost struct, rename some functions
1 parent b9a654f commit 3e4f887

File tree

2 files changed

+42
-24
lines changed

2 files changed

+42
-24
lines changed

src/builder/QuarkBuilder.sol

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity ^0.8.23;
44
import {IQuarkWallet} from "quark-core/src/interfaces/IQuarkWallet.sol";
55
import {TransferActions} from "../DeFiScripts.sol";
66
import "./BridgeRoutes.sol";
7+
import "./Strings.sol";
78

89
contract QuarkBuilder {
910
/* ===== Constants ===== */
@@ -63,12 +64,15 @@ contract QuarkBuilder {
6364
}
6465

6566
struct Payment {
66-
// TODO: rename?
6767
bool isToken;
68+
// Note: Payment `currency` should be the same across chains
6869
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;
7276
}
7377

7478
/* ===== Output Types ===== */
@@ -122,7 +126,6 @@ contract QuarkBuilder {
122126
uint256 destinationChainId;
123127
}
124128

125-
126129
/* ===== Internal/Intermediate Types ===== */
127130

128131
// Note: This is just the AssetPositions type with an extra `chainId` field
@@ -135,17 +138,12 @@ contract QuarkBuilder {
135138
AccountBalance[] accountBalances;
136139
}
137140

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) {
144142
uint numMatches = 0;
145143
// First loop to count the number of matching AssetPositions
146144
for (uint i = 0; i < chainAccountsList.length; ++i) {
147145
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)) {
149147
numMatches++;
150148
}
151149
}
@@ -156,7 +154,7 @@ contract QuarkBuilder {
156154
// Second loop to populate the matchingAssetPositions array
157155
for (uint i = 0; i < chainAccountsList.length; ++i) {
158156
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)) {
160158
AssetPositions memory assetPositions = chainAccountsList[i].assetPositionsList[j];
161159
matchingAssetPositions[index] = AssetPositionsWithChainId({
162160
chainId: chainAccountsList[i].chainId,
@@ -182,7 +180,7 @@ contract QuarkBuilder {
182180
continue
183181
}
184182
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)) {
186184
AssetPositions memory assetPositions = chainAccountsList[i].assetPositionsList[j];
187185
return AssetPositionsWithChainId({
188186
chainId: chainAccountsList[i].chainId,
@@ -217,14 +215,10 @@ contract QuarkBuilder {
217215
Payment calldata payment,
218216
ChainAccounts[] calldata chainAccountsList
219217
) 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);
225219
AssetPositionsWithChainId[] paymentAssetPositions;
226220
if (payment.isToken) {
227-
paymentAssetPositions = filterAssetPositionsForSymbol(payment.currency, chainAccountsList);
221+
paymentAssetPositions = filterAssetPositions(payment.currency, chainAccountsList);
228222
}
229223

230224
// INSUFFICIENT_FUNDS
@@ -245,11 +239,13 @@ contract QuarkBuilder {
245239
// (amount of payment token on chain id - transfer amount (IF IS SAME TOKEN AND SAME CHAIN ID)) < maxPaymentAmount on chain id
246240
// Note: This check assumes we will not be bridging payment tokens for the user
247241
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);
250245
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) {
253249
paymentAssetNeeded += transferAmount;
254250
}
255251
if (paymentAssetBalanceOnChain < paymentAssetNeeded) {

src/builder/Strings.sol

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
pragma solidity ^0.8.23;
3+
4+
library Strings {
5+
function stringEq(string memory a, string memory b) internal pure returns (bool) {
6+
return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
7+
}
8+
9+
function stringEqIgnoreCase(string memory a, string memory b) internal pure returns (bool) {
10+
return keccak256(abi.encodePacked(toLowerCase(a))) == keccak256(abi.encodePacked(toLowerCase(b)));
11+
}
12+
13+
function toLowerCase(string memory str) internal pure returns (string memory) {
14+
bytes memory strBytes = bytes(strBytes);
15+
for (uint i = 0; i < strBytes.length; i++) {
16+
if (strBytes[i] >= 0x41 && strBytes[i] <= 0x5A) {
17+
strBytes[i] = bytes1(uint8(strBytes[i]) + 32);
18+
}
19+
}
20+
return string(strBytes);
21+
}
22+
}

0 commit comments

Comments
 (0)