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

2024-09-26 FE Release #3155

Merged
merged 74 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
89907ce
update bl
aureliusbtc Sep 18, 2024
b07d94e
remove global solidity extension settings
ChiTimesChi Sep 18, 2024
6e41b29
use monorepo support in global workspace only
ChiTimesChi Sep 18, 2024
9049299
- use Solidity extension for formatting *.sol files
ChiTimesChi Sep 18, 2024
7a118c9
REST API Improvements [SLT-179] (#3133)
Defi-Moses Sep 18, 2024
0b64779
Publish
Defi-Moses Sep 18, 2024
d4d1c5a
fix harmony proxy (#3149)
trajan0x Sep 19, 2024
bf22448
merging rfq indexer into monorepo [SLT-164] [SLT-176] (#3136)
Defi-Moses Sep 19, 2024
5052439
Publish
Defi-Moses Sep 19, 2024
a03677e
Adds /destinationTokens route [SLT-204] (#3151)
abtestingalpha Sep 19, 2024
4ed82b0
Publish
abtestingalpha Sep 19, 2024
1b821a0
boba pause (#3150)
Defi-Moses Sep 19, 2024
965736b
Publish
Defi-Moses Sep 19, 2024
fd1540d
fix(synapse-interface): Reorders validation to check existence first …
abtestingalpha Sep 19, 2024
8e12c27
Publish
abtestingalpha Sep 19, 2024
4f4c201
Fix boba pause (#3158)
abtestingalpha Sep 19, 2024
b1eca8a
Publish
abtestingalpha Sep 19, 2024
86415c0
update bl
trajan0x Sep 20, 2024
49cf94d
Merge branch 'master' of https://github.com/synapsecns/sanguine
trajan0x Sep 20, 2024
01ec2d4
feat(rest-api): Adds Swagger for api docs [SLT-205] (#3159)
abtestingalpha Sep 20, 2024
8127a4c
Publish
abtestingalpha Sep 20, 2024
d7599c3
Pulls version from package json (#3160)
abtestingalpha Sep 20, 2024
c262b01
Publish
abtestingalpha Sep 20, 2024
c32b70b
Require vs import due to file location (#3161)
abtestingalpha Sep 20, 2024
ce1defe
Publish
abtestingalpha Sep 20, 2024
304ecda
Prevent caching of api docs (#3162)
abtestingalpha Sep 20, 2024
fd0aecb
Publish
abtestingalpha Sep 20, 2024
23f6c4c
feat(contracts-rfq): relay/prove/claim with different address [SLT-13…
parodime Sep 20, 2024
dd67210
Publish
parodime Sep 20, 2024
4a0f2e7
fix(promexporter): make spans better (#3164)
golangisfun123 Sep 21, 2024
1eb52a0
changing native token address standard [SLT-210] (#3157)
Defi-Moses Sep 21, 2024
3b507bd
Publish
Defi-Moses Sep 21, 2024
f4101f2
Refactoring rfq-indexer API and adding swagger docs [SLT-228] (#3167)
Defi-Moses Sep 22, 2024
4cb5d73
Publish
Defi-Moses Sep 22, 2024
1891fed
fix read mes (#3168)
Defi-Moses Sep 22, 2024
4680ddc
Merge pull request #3145 from synapsecns/chore/solidity-vscode-settings
ChiTimesChi Sep 23, 2024
faf9387
Publish
ChiTimesChi Sep 23, 2024
8c702c7
fix(opbot): use submitter get tx status [SLT-158] (#3134)
golangisfun123 Sep 23, 2024
9418b40
fix(synapse-interface): Additional checks on screen [SLT-166] (#3152)
abtestingalpha Sep 23, 2024
1eb6fa0
Publish
abtestingalpha Sep 23, 2024
6f21b1a
feat(synapse-interface): confirm new price [SLT-150] (#3084)
bigboydiamonds Sep 23, 2024
1de17e0
Publish
bigboydiamonds Sep 23, 2024
b6651b1
fix: formatted bridge fee amount (#3165)
bigboydiamonds Sep 23, 2024
0daec70
Publish
bigboydiamonds Sep 23, 2024
74b620e
fix(contracts-rfq): CI workflows [SLT-245] (#3178)
ChiTimesChi Sep 24, 2024
038605d
Publish
ChiTimesChi Sep 24, 2024
98362bb
feat(api): bridge limits [SLT-165] (#3179)
bigboydiamonds Sep 24, 2024
67a04cd
Publish
bigboydiamonds Sep 24, 2024
c15ec86
fix(contracts-rfq): limit the amount of solhint warnings [SLT-245] (#…
ChiTimesChi Sep 25, 2024
11ac650
Publish
ChiTimesChi Sep 25, 2024
8113d0b
ci: Solidity gas diff [SLT-259] (#3181)
ChiTimesChi Sep 25, 2024
e89b363
Publish
ChiTimesChi Sep 25, 2024
7594100
fix(contracts-core): set very high gas limit for intensive tests [SLT…
ChiTimesChi Sep 25, 2024
6ec996d
Publish
ChiTimesChi Sep 25, 2024
ceff8bc
feat(rest-api): Adds validateRouteExists validation [SLT-260] (#3180)
abtestingalpha Sep 25, 2024
3af3438
Publish
abtestingalpha Sep 25, 2024
3e75b0d
add duplicate command warning (#3174)
trajan0x Sep 26, 2024
2e808e6
reduce solhint warnings on FbV2 (#3189)
parodime Sep 26, 2024
1bdfee6
Publish
parodime Sep 26, 2024
2709e85
ci: solidity gas diff options [SLT-267] (#3193)
ChiTimesChi Sep 26, 2024
9742f8f
prove w/ tx id [SLT-181] (#3169)
parodime Sep 26, 2024
abeea4d
Publish
parodime Sep 26, 2024
fc6ddae
fix(sdk-router): disable ARB airdrop tests (#3195)
ChiTimesChi Sep 26, 2024
90ac800
Publish
ChiTimesChi Sep 26, 2024
fe71628
Fixing issue for wallet integration [SLT-270] (#3194)
Defi-Moses Sep 26, 2024
5c8a069
Publish
Defi-Moses Sep 26, 2024
65ee496
store relayer on relay [SLT-182] (#3170)
parodime Sep 26, 2024
1c5e21d
Publish
parodime Sep 26, 2024
4a45bcf
Adjust text to trigger build (#3199)
abtestingalpha Sep 26, 2024
d8338fe
Publish
abtestingalpha Sep 26, 2024
f0b13bc
feat(synapse-interface): refund RFQ transaction [SLT-272] (#3197)
bigboydiamonds Sep 26, 2024
96bf50f
Publish
abtestingalpha Sep 26, 2024
e897b18
no empty sender recip [SLT-184] (#3171)
parodime Sep 26, 2024
ebf102c
Publish
parodime Sep 26, 2024
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
1 change: 1 addition & 0 deletions lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"useWorkspaces": true,
"packages": [
"packages/*",
"packages/rfq-indexer/*",
"docs/*"
],
"version": "independent"
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"workspaces": {
"packages": [
"packages/*",
"packages/rfq-indexer/*",
"docs/*"
],
"nohoist": [
Expand Down Expand Up @@ -73,7 +74,8 @@
"ts-mocha": "^10.0.0",
"typedoc": "^0.23.24",
"typedoc-plugin-markdown": "^3.14.0",
"typescript": "^5.0.4"
"typescript": "^5.0.4",
"wagmi": "^2.12.12"
},
"dependencies": {
"@changesets/cli": "2.22.0",
Expand Down
6 changes: 6 additions & 0 deletions packages/rest-api/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@ module.exports = {
'prettier/prettier': 'off',
},
},
{
files: ['**/*.ts'],
rules: {
'guard-for-in': 'off',
},
},
],
}
16 changes: 16 additions & 0 deletions packages/rest-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [1.0.76](https://github.com/synapsecns/sanguine/compare/@synapsecns/[email protected]...@synapsecns/[email protected]) (2024-09-19)

**Note:** Version bump only for package @synapsecns/rest-api





## [1.0.75](https://github.com/synapsecns/sanguine/compare/@synapsecns/[email protected]...@synapsecns/[email protected]) (2024-09-18)

**Note:** Version bump only for package @synapsecns/rest-api





## [1.0.74](https://github.com/synapsecns/sanguine/compare/@synapsecns/[email protected]...@synapsecns/[email protected]) (2024-09-16)

**Note:** Version bump only for package @synapsecns/rest-api
Expand Down
2 changes: 1 addition & 1 deletion packages/rest-api/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ module.exports = {
'^.+\\.(ts|tsx)$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleDirectories: ['node_modules', 'src'],
moduleDirectories: ['node_modules', '<rootDir>'],
}
5 changes: 3 additions & 2 deletions packages/rest-api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@synapsecns/rest-api",
"version": "1.0.74",
"version": "1.0.76",
"private": "true",
"engines": {
"node": ">=18.17.0"
Expand All @@ -15,7 +15,7 @@
"lint:check": "eslint . --max-warnings=0",
"ci:lint": "npm run lint:check",
"test": "jest",
"test:coverage": "echo 'No tests defined.'"
"test:coverage": "jest --collect-coverage"
},
"dependencies": {
"@ethersproject/bignumber": "^5.7.0",
Expand All @@ -26,6 +26,7 @@
"ethers": "5.7.2",
"express": "^4.18.2",
"express-validator": "^7.2.0",
"jest": "^29.7.0",
"lodash": "^4.17.21",
"supertest": "^6.3.3",
"typescript": "^4.8.3"
Expand Down
3 changes: 1 addition & 2 deletions packages/rest-api/src/constants/bridgeable.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { BridgeableToken } from '../types'
import { CHAINS } from './chains'

const ZeroAddress = '0x0000000000000000000000000000000000000000'
import { ZeroAddress } from '.'

export const GOHM: BridgeableToken = {
addresses: {
Expand Down
3 changes: 3 additions & 0 deletions packages/rest-api/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ export const VALID_BRIDGE_MODULES = [
'SynapseCCTP',
'SynapseRFQ',
]

export const ZeroAddress = '0x0000000000000000000000000000000000000000'
export const NativeGasAddress = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
12 changes: 7 additions & 5 deletions packages/rest-api/src/controllers/bridgeController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,26 @@ import { parseUnits } from '@ethersproject/units'

import { formatBNToString } from '../utils/formatBNToString'
import { Synapse } from '../services/synapseService'
import { tokenAddressToToken } from '../utils/tokenAddressToToken'

export const bridgeController = async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() })
}
try {
const { fromChain, toChain, amount } = req.query
const fromTokenInfo = res.locals.tokenInfo.fromToken
const toTokenInfo = res.locals.tokenInfo.toToken
const { fromChain, toChain, amount, fromToken, toToken } = req.query

const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken)
const toTokenInfo = tokenAddressToToken(toChain.toString(), toToken)

const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals)

const resp = await Synapse.allBridgeQuotes(
Number(fromChain),
Number(toChain),
fromTokenInfo.address,
toTokenInfo.address,
fromToken,
toToken,
amountInWei
)
const payload = resp.map((quote) => ({
Expand Down
14 changes: 8 additions & 6 deletions packages/rest-api/src/controllers/bridgeTxInfoController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { validationResult } from 'express-validator'
import { parseUnits } from '@ethersproject/units'

import { Synapse } from '../services/synapseService'
import { tokenAddressToToken } from '../utils/tokenAddressToToken'

export const bridgeTxInfoController = async (req, res) => {
const errors = validationResult(req)
Expand All @@ -10,17 +11,18 @@ export const bridgeTxInfoController = async (req, res) => {
}

try {
const { fromChain, toChain, amount, destAddress } = req.query
const fromTokenInfo = res.locals.tokenInfo.fromToken
const toTokenInfo = res.locals.tokenInfo.toToken
const { fromChain, toChain, amount, destAddress, fromToken, toToken } =
req.query

const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken)

const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals)

const quotes = await Synapse.allBridgeQuotes(
Number(fromChain),
Number(toChain),
fromTokenInfo.address,
toTokenInfo.address,
fromToken,
toToken,
amountInWei
)

Expand All @@ -31,7 +33,7 @@ export const bridgeTxInfoController = async (req, res) => {
quote.routerAddress,
Number(fromChain),
Number(toChain),
fromTokenInfo.address,
fromToken,
amountInWei,
quote.originQuery,
quote.destQuery
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { validationResult } from 'express-validator'

import { tokenAddressToToken } from '../utils/tokenAddressToToken'
import { BRIDGE_ROUTE_MAPPING } from '../utils/bridgeRouteMapping'

export const destinationTokensController = async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() })
}

try {
const { fromChain, fromToken } = req.query

const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken)

const constructedKey = `${fromTokenInfo.symbol}-${fromChain}`

const options = BRIDGE_ROUTE_MAPPING[constructedKey]

res.json(options)
} catch (err) {
res.status(500).json({
error:
'An unexpected error occurred in /destinationTokens. Please try again later.',
details: err.message,
})
}
}
21 changes: 15 additions & 6 deletions packages/rest-api/src/controllers/swapController.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
import { validationResult } from 'express-validator'
import { formatUnits, parseUnits } from '@ethersproject/units'
import { BigNumber } from '@ethersproject/bignumber'

import { Synapse } from '../services/synapseService'
import { tokenAddressToToken } from '../utils/tokenAddressToToken'

export const swapController = async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() })
}
try {
const { chain, amount } = req.query
const fromTokenInfo = res.locals.tokenInfo.fromToken
const toTokenInfo = res.locals.tokenInfo.toToken
const { chain, amount, fromToken, toToken } = req.query

const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken)
const toTokenInfo = tokenAddressToToken(chain.toString(), toToken)
Comment on lines +16 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle cases where tokenAddressToToken may return undefined

The functions fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken) and toTokenInfo = tokenAddressToToken(chain.toString(), toToken) might return undefined if the token address is invalid or not recognized. Using properties like fromTokenInfo.decimals without validation could lead to runtime errors. It's important to check that these objects are valid before proceeding.

Possible action: Add checks to verify that fromTokenInfo and toTokenInfo are not undefined and handle the error gracefully if they are.

 try {
   const { chain, amount, fromToken, toToken } = req.query

   const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken)
   const toTokenInfo = tokenAddressToToken(chain.toString(), toToken)

+  if (!fromTokenInfo || !toTokenInfo) {
+    return res.status(400).json({ error: 'Invalid token address provided.' })
+  }

   const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals)
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken)
const toTokenInfo = tokenAddressToToken(chain.toString(), toToken)
const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken)
const toTokenInfo = tokenAddressToToken(chain.toString(), toToken)
if (!fromTokenInfo || !toTokenInfo) {
return res.status(400).json({ error: 'Invalid token address provided.' })
}


const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals)
const quote = await Synapse.swapQuote(
Number(chain),
fromTokenInfo.address,
toTokenInfo.address,
fromToken,
toToken,
Comment on lines +22 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

Implement token address validation before using in swapQuote

The review of swapController.ts confirms that there's no explicit validation of fromToken and toToken addresses before they're used in the Synapse.swapQuote function. While there's a tokenAddressToToken function being used, it's unclear if it performs address validation.

To ensure the integrity of the swap operation and prevent potential errors or unexpected behavior, please implement the following:

  1. Add a utility function to validate Ethereum addresses:
const isValidEthereumAddress = (address) => /^0x[a-fA-F0-9]{40}$/.test(address);
  1. Use this function to validate fromToken and toToken before proceeding with the swap:
if (!isValidEthereumAddress(fromToken) || !isValidEthereumAddress(toToken)) {
  return res.status(400).json({ error: 'Invalid token address format.' });
}
  1. Place this validation immediately after extracting the values from req.query and before calling tokenAddressToToken or Synapse.swapQuote.

This addition will help prevent potential issues caused by invalid token addresses and improve the overall robustness of the swap controller.

Analysis chain

Validate token addresses before calling swapQuote

Passing invalid fromToken and toToken addresses to Synapse.swapQuote could result in errors or unexpected behavior. Ensure that the token addresses are validated for correct formatting and authenticity before making the external service call.

Possible action: Implement validation logic for fromToken and toToken to confirm they are valid Ethereum addresses.

+const isValidAddress = (address) => /^0x[a-fA-F0-9]{40}$/.test(address);

+if (!isValidAddress(fromToken) || !isValidAddress(toToken)) {
+  return res.status(400).json({ error: 'Invalid token address format.' })
+}

 const quote = await Synapse.swapQuote(
   Number(chain),
   fromToken,
   toToken,
   amountInWei
 )

Verification script:

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all token addresses conform to Ethereum address format.

# Test: Check if fromToken and toToken are valid hex addresses. Expect: Addresses match the regex pattern.
rg --type javascript --pattern '\bfromToken\b|\btoToken\b' -A 2

Length of output: 477


Script:

#!/bin/bash
# Search for fromToken and toToken usage
rg '\b(fromToken|toToken)\b' -t js -A 2 -B 2

# Search for potential address validation functions
rg '(isValidAddress|validateAddress|checkAddress)' -t js

# Search for Ethereum address regex patterns
rg '0x[a-fA-F0-9]{40}' -t js

Length of output: 1234


Script:

#!/bin/bash
# Check if the swapController.ts file exists
fd swapController.ts

# If the file exists, display its content
fd swapController.ts -x cat {}

# Search for fromToken and toToken usage in swapController.ts
fd swapController.ts -x rg '\b(fromToken|toToken)\b' {}

Length of output: 1664

amountInWei
)

const formattedMaxAmountOut = formatUnits(
BigNumber.from(quote.maxAmountOut),
toTokenInfo.decimals
)

Comment on lines +27 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure quote.maxAmountOut is defined before formatting

If quote.maxAmountOut is undefined or not a valid number, calling BigNumber.from(quote.maxAmountOut) will throw an error. It's important to check that quote.maxAmountOut is present and valid before attempting to format it.

Possible action: Add a validation step to confirm quote.maxAmountOut is defined and handle cases where it isn't.

 const formattedMaxAmountOut = formatUnits(
-  BigNumber.from(quote.maxAmountOut),
+  BigNumber.from(quote.maxAmountOut || '0'),
   toTokenInfo.decimals
 )

Or handle the case explicitly:

+if (!quote.maxAmountOut) {
+  return res.status(500).json({ error: 'Failed to retrieve maxAmountOut from quote.' })
+}

 const formattedMaxAmountOut = formatUnits(
   BigNumber.from(quote.maxAmountOut),
   toTokenInfo.decimals
 )

Committable suggestion was skipped due to low confidence.

res.json({
maxAmountOut: formatUnits(quote.maxAmountOut, toTokenInfo.decimals),
...quote,
maxAmountOut: formattedMaxAmountOut,
})
} catch (err) {
res.status(500).json({
Expand Down
15 changes: 8 additions & 7 deletions packages/rest-api/src/controllers/swapTxInfoController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { validationResult } from 'express-validator'
import { parseUnits } from '@ethersproject/units'

import { Synapse } from '../services/synapseService'
import { tokenAddressToToken } from '../utils/tokenAddressToToken'

export const swapTxInfoController = async (req, res) => {
const errors = validationResult(req)
Expand All @@ -10,23 +11,23 @@ export const swapTxInfoController = async (req, res) => {
}

try {
const { chain, amount } = req.query
const fromTokenInfo = res.locals.tokenInfo.fromToken
const toTokenInfo = res.locals.tokenInfo.toToken
const { chain, amount, address, fromToken, toToken } = req.query

const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle Potential Undefined 'fromTokenInfo'

The tokenAddressToToken function may return undefined if the token is not recognized. To prevent runtime errors, add a check to ensure fromTokenInfo is defined before using it.

Apply this diff to handle the undefined case:

 const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken)

+if (!fromTokenInfo) {
+  return res.status(400).json({ error: 'Invalid fromToken address' })
+}

 const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals)

Committable suggestion was skipped due to low confidence.


const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals)

const quote = await Synapse.swapQuote(
Number(chain),
fromTokenInfo.address,
toTokenInfo.address,
fromToken,
toToken,
amountInWei
)

const txInfo = await Synapse.swap(
Number(chain),
fromTokenInfo.address,
toTokenInfo.address,
address,
fromToken,
amountInWei,
quote.query
)
Expand Down
14 changes: 14 additions & 0 deletions packages/rest-api/src/middleware/checksumAddresses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Request, Response, NextFunction } from 'express'
import { getAddress, isAddress } from 'ethers/lib/utils'

export const checksumAddresses = (addressFields: string[]) => {
return (req: Request, _res: Response, next: NextFunction) => {
for (const field of addressFields) {
const address = req.query[field]
if (typeof address === 'string' && isAddress(address)) {
req.query[field] = getAddress(address)
}
}
next()
}
}
27 changes: 23 additions & 4 deletions packages/rest-api/src/routes/bridgeRoute.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import express from 'express'
import { check } from 'express-validator'

import { isTokenAddress } from '../utils/isTokenAddress'
import { CHAINS_ARRAY } from '../constants/chains'
import { validateTokens } from '../validations/validateTokens'
import { showFirstValidationError } from '../middleware/showFirstValidationError'
import { bridgeController } from '../controllers/bridgeController'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'
import { checksumAddresses } from '../middleware/checksumAddresses'

const router = express.Router()

router.get(
'/',
checksumAddresses(['fromToken', 'toToken']),
[
check('fromChain')
.isNumeric()
Expand All @@ -23,9 +26,25 @@ router.get(
.withMessage('Unsupported toChain')
.exists()
.withMessage('toChain is required'),
validateTokens('fromChain', 'fromToken', 'fromToken'),
validateTokens('toChain', 'toToken', 'toToken'),
check('amount').isNumeric(),
check('fromToken')
.exists()
.withMessage('fromToken is required')
.custom((value) => isTokenAddress(value))
.withMessage('Invalid fromToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.fromChain as string)
)
.withMessage('Token not supported on specified chain'),
check('toToken')
.exists()
.withMessage('toToken is required')
.custom((value) => isTokenAddress(value))
.withMessage('Invalid toToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.toChain as string)
)
.withMessage('Token not supported on specified chain'),
check('amount').isNumeric().exists().withMessage('amount is required'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swap the order of validators for the amount parameter

In the validation for the amount parameter, .isNumeric() is called before .exists(). If amount is missing, applying .isNumeric() may not behave as expected since it would be operating on undefined. It's recommended to check for the existence of the parameter before applying other validators to ensure accurate error handling.

Apply this diff to correct the validator order:

     check('amount')
+      .exists()
+      .withMessage('amount is required')
       .isNumeric()
-      .exists()
-      .withMessage('amount is required'),
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
check('amount').isNumeric().exists().withMessage('amount is required'),
check('amount')
.exists()
.withMessage('amount is required')
.isNumeric(),

],
showFirstValidationError,
bridgeController
Expand Down
Loading
Loading