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

Fix(stargate): supply layer one chain ids #32

Merged
merged 14 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
49 changes: 24 additions & 25 deletions packages/stargate/src/Stargate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ import {
} from './test-transactions.js'
import {
ARBITRUM_LAYER_ZERO_CHAIN_ID,
POLYGON_LAYER_ZERO_CHAIN_ID,
ETH_LAYER_ZERO_CHAIN_ID,
OPTIMISM_LAYER_ZERO_CHAIN_ID,
LAYER_ZERO_TO_LAYER_ONE_CHAIN_ID,
ETH_CHAIN_ID,
ARBITRUM_CHAIN_ID,
OPTIMISM_CHAIN_ID,
POLYGON_CHAIN_ID,
} from './chain-ids.js'
import { STARGATE_BRIDGE_ABI } from './abi.js'
import { parseEther } from 'viem'
import {
CHAIN_AND_POOL_TO_TOKEN_ADDRESS,
CHAIN_ONE_AND_POOL_TO_TOKEN_ADDRESS,
CHAIN_ID_TO_ROUTER_ADDRESS,
CHAIN_ID_TO_ETH_ROUTER_ADDRESS,
} from './contract-addresses.js'
Expand All @@ -35,19 +36,19 @@ describe('Given the Across plugin', () => {
describe('When generating the filter', () => {
test('should return a valid bridge action filter for L2 token tx', async () => {
const filter = await bridge({
sourceChainId: ARBITRUM_LAYER_ZERO_CHAIN_ID,
destinationChainId: ETH_LAYER_ZERO_CHAIN_ID,
sourceChainId: ARBITRUM_CHAIN_ID,
destinationChainId: ETH_CHAIN_ID,
tokenAddress: ARBITRUM_USDC_ADDRESS,
amount: GreaterThanOrEqual(100000n),
recipient: TEST_USER,
})
const sourcePool =
CHAIN_AND_POOL_TO_TOKEN_ADDRESS[ARBITRUM_LAYER_ZERO_CHAIN_ID][
CHAIN_ONE_AND_POOL_TO_TOKEN_ADDRESS[ARBITRUM_CHAIN_ID][
ARBITRUM_USDC_ADDRESS
]

expect(filter).to.deep.equal({
chainId: LAYER_ZERO_TO_LAYER_ONE_CHAIN_ID[ARBITRUM_LAYER_ZERO_CHAIN_ID],
chainId: ARBITRUM_CHAIN_ID,
to: CHAIN_ID_TO_ROUTER_ADDRESS[ARBITRUM_LAYER_ZERO_CHAIN_ID],
input: {
$abi: STARGATE_BRIDGE_ABI,
Expand All @@ -63,19 +64,17 @@ describe('Given the Across plugin', () => {

test('should return a valid bridge action filter for L1 token tx', async () => {
const filter = await bridge({
sourceChainId: ETH_LAYER_ZERO_CHAIN_ID,
destinationChainId: ARBITRUM_LAYER_ZERO_CHAIN_ID,
sourceChainId: ETH_CHAIN_ID,
destinationChainId: ARBITRUM_CHAIN_ID,
tokenAddress: ETHEREUM_USDC_ADDRESS,
amount: GreaterThanOrEqual(100000n),
recipient: TEST_USER,
})
const sourcePool =
CHAIN_AND_POOL_TO_TOKEN_ADDRESS[ETH_LAYER_ZERO_CHAIN_ID][
ETHEREUM_USDC_ADDRESS
]
CHAIN_ONE_AND_POOL_TO_TOKEN_ADDRESS[ETH_CHAIN_ID][ETHEREUM_USDC_ADDRESS]

expect(filter).to.deep.equal({
chainId: LAYER_ZERO_TO_LAYER_ONE_CHAIN_ID[ETH_LAYER_ZERO_CHAIN_ID],
chainId: ETH_CHAIN_ID,
to: CHAIN_ID_TO_ROUTER_ADDRESS[ETH_LAYER_ZERO_CHAIN_ID],
input: {
$abi: STARGATE_BRIDGE_ABI,
Expand All @@ -91,14 +90,14 @@ describe('Given the Across plugin', () => {

test('should return a valid bridge action filter for L1 ETH tx', async () => {
const filter = await bridge({
sourceChainId: ETH_LAYER_ZERO_CHAIN_ID,
destinationChainId: ARBITRUM_LAYER_ZERO_CHAIN_ID,
sourceChainId: ETH_CHAIN_ID,
destinationChainId: ARBITRUM_CHAIN_ID,
tokenAddress: ETHEREUM_SGETH_ADDRESS,
amount: GreaterThanOrEqual(100000n),
recipient: TEST_USER,
})
expect(filter).to.deep.equal({
chainId: LAYER_ZERO_TO_LAYER_ONE_CHAIN_ID[ETH_LAYER_ZERO_CHAIN_ID],
chainId: ETH_CHAIN_ID,
to: CHAIN_ID_TO_ETH_ROUTER_ADDRESS[ETH_LAYER_ZERO_CHAIN_ID],
input: {
$abi: STARGATE_BRIDGE_ABI,
Expand All @@ -115,8 +114,8 @@ describe('Given the Across plugin', () => {
test('should pass filter with valid L1 ETH tx', async () => {
const transaction = DEPOSIT_ETH
const filter = await bridge({
sourceChainId: ETH_LAYER_ZERO_CHAIN_ID,
destinationChainId: ARBITRUM_LAYER_ZERO_CHAIN_ID,
sourceChainId: ETH_CHAIN_ID,
destinationChainId: ARBITRUM_CHAIN_ID,
tokenAddress: ETHEREUM_SGETH_ADDRESS,
amount: GreaterThanOrEqual(parseEther('.04')),
recipient: '0x7c3bd1a09d7d86920451def20ae503322c8d0412',
Expand All @@ -126,8 +125,8 @@ describe('Given the Across plugin', () => {
test('should pass filter with valid L2 ETH tx', async () => {
const transaction = WITHDRAW_ETH
const filter = await bridge({
sourceChainId: ARBITRUM_LAYER_ZERO_CHAIN_ID,
destinationChainId: OPTIMISM_LAYER_ZERO_CHAIN_ID,
sourceChainId: ARBITRUM_CHAIN_ID,
destinationChainId: OPTIMISM_CHAIN_ID,
tokenAddress: ARBITRUM_SGETH_ADDRESS,
amount: GreaterThanOrEqual(parseEther('.6')),
recipient: '0x08bfa4ef61a457792c45240829529b43b019d941',
Expand All @@ -137,8 +136,8 @@ describe('Given the Across plugin', () => {
test('should pass filter with valid L1 Token tx', async () => {
const transaction = DEPOSIT_ERC20
const filter = await bridge({
sourceChainId: ETH_LAYER_ZERO_CHAIN_ID,
destinationChainId: ARBITRUM_LAYER_ZERO_CHAIN_ID,
sourceChainId: ETH_CHAIN_ID,
destinationChainId: ARBITRUM_CHAIN_ID,
tokenAddress: ETHEREUM_USDC_ADDRESS,
amount: GreaterThanOrEqual('48500000'), // $250 USDC,
recipient: '0x0318ccfbfae5e2c06b2f533a35acecea13b9909f',
Expand All @@ -148,8 +147,8 @@ describe('Given the Across plugin', () => {
test('should pass filter with valid L2 token tx', async () => {
const transaction = WITHDRAW_ERC20
const filter = await bridge({
sourceChainId: ARBITRUM_LAYER_ZERO_CHAIN_ID,
destinationChainId: POLYGON_LAYER_ZERO_CHAIN_ID,
sourceChainId: ARBITRUM_CHAIN_ID,
destinationChainId: POLYGON_CHAIN_ID,
tokenAddress: ARBITRUM_USDT_ADDRESS,
amount: GreaterThanOrEqual('1200000000'),
recipient: '0x5ee8496532d3dcb8bc726d66d8cb4c45d979e71d',
Expand Down
36 changes: 25 additions & 11 deletions packages/stargate/src/Stargate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import { type BridgeActionParams, compressJson } from '@rabbitholegg/questdk'
import { type Address } from 'viem'
import { STARGATE_BRIDGE_ABI } from './abi.js'
import {
ARBITRUM_CHAIN_ID,
CHAIN_ID_ARRAY,
LAYER_ZERO_TO_LAYER_ONE_CHAIN_ID,
ETH_CHAIN_ID,
LAYER_ONE_TO_LAYER_ZERO_CHAIN_ID,
POLYGON_CHAIN_ID,
} from './chain-ids.js'
import {
CHAIN_AND_POOL_TO_TOKEN_ADDRESS,
CHAIN_ID_TO_ROUTER_ADDRESS,
CHAIN_ONE_AND_POOL_TO_TOKEN_ADDRESS,
CHAIN_ID_TO_ETH_ROUTER_ADDRESS,
CHAIN_ID_TO_ROUTER_ADDRESS,
} from './contract-addresses.js'

export const bridge = async (bridge: BridgeActionParams) => {
Expand All @@ -21,36 +24,41 @@ export const bridge = async (bridge: BridgeActionParams) => {
amount,
recipient,
} = bridge
const layerOneChainId = LAYER_ZERO_TO_LAYER_ONE_CHAIN_ID[sourceChainId]
const layerZeroDestination =
LAYER_ONE_TO_LAYER_ZERO_CHAIN_ID[destinationChainId]
const sourcePool = tokenAddress
? CHAIN_AND_POOL_TO_TOKEN_ADDRESS[sourceChainId][tokenAddress]
? CHAIN_ONE_AND_POOL_TO_TOKEN_ADDRESS[sourceChainId][tokenAddress]
: 0

if (sourcePool === 13) {
const targetContractAddress = CHAIN_ID_TO_ETH_ROUTER_ADDRESS[sourceChainId]
const targetContractAddress =
CHAIN_ID_TO_ETH_ROUTER_ADDRESS[
LAYER_ONE_TO_LAYER_ZERO_CHAIN_ID[sourceChainId]
]
return compressJson({
chainId: layerOneChainId, // The chainId of the source chain
chainId: sourceChainId, // The chainId of the source chain
to: contractAddress || targetContractAddress, // The contract address of the bridge
input: {
$abi: STARGATE_BRIDGE_ABI, // The ABI of the bridge contract
_amountLD: amount, // The amount of tokens to send
_toAddress: recipient, // The recipient of the tokens
_dstChainId: destinationChainId, // The chainId of the destination chain
_dstChainId: layerZeroDestination, // The chainId of the destination chain
}, // The input object is where we'll put the ABI and the parameters
})
}
const targetContractAddress = CHAIN_ID_TO_ROUTER_ADDRESS[sourceChainId]
const targetContractAddress =
CHAIN_ID_TO_ROUTER_ADDRESS[LAYER_ONE_TO_LAYER_ZERO_CHAIN_ID[sourceChainId]]

// We always want to return a compressed JSON object which we'll transform into a TransactionFilter
return compressJson({
chainId: layerOneChainId, // The chainId of the source chain
chainId: sourceChainId, // The chainId of the source chain
to: contractAddress || targetContractAddress, // The contract address of the bridge
input: {
$abi: STARGATE_BRIDGE_ABI, // The ABI of the bridge contract
_srcPoolId: sourcePool, // The source poolId
_amountLD: amount, // The amount of tokens to send
_to: recipient, // The recipient of the tokens
_dstChainId: destinationChainId, // The chainId of the destination chain
_dstChainId: layerZeroDestination, // The chainId of the destination chain
}, // The input object is where we'll put the ABI and the parameters
})
}
Expand All @@ -59,6 +67,12 @@ export const getSupportedTokenAddresses = async (
_chainId: number,
): Promise<Address[]> => {
// Given a specific chain we would expect this function to return a list of supported token addresses
if (_chainId === POLYGON_CHAIN_ID)
return ['0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174']
if (_chainId === ARBITRUM_CHAIN_ID)
return ['0xaf88d065e77c8cC2239327C5EDb3A432268e5831']
if (_chainId === ETH_CHAIN_ID)
return ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48']
return []
}

Expand Down
14 changes: 14 additions & 0 deletions packages/stargate/src/chain-ids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ export const LAYER_ZERO_TO_LAYER_ONE_CHAIN_ID: Record<number, number> = {
[BASE_LAYER_ZERO_CHAIN_ID]: BASE_CHAIN_ID,
} as const

export const LAYER_ONE_TO_LAYER_ZERO_CHAIN_ID: Record<number, number> = {
[ETH_CHAIN_ID]: ETH_LAYER_ZERO_CHAIN_ID,
[BNB_CHAIN_ID]: BNB_LAYER_ZERO_CHAIN_ID,
[AVALANCHE_CHAIN_ID]: AVALANCHE_LAYER_ZERO_CHAIN_ID,
[POLYGON_CHAIN_ID]: POLYGON_LAYER_ZERO_CHAIN_ID,
[ARBITRUM_CHAIN_ID]: ARBITRUM_LAYER_ZERO_CHAIN_ID,
[OPTIMISM_CHAIN_ID]: OPTIMISM_LAYER_ZERO_CHAIN_ID,
[FANTOM_CHAIN_ID]: FANTOM_LAYER_ZERO_CHAIN_ID,
[METIS_CHAIN_ID]: METIS_LAYER_ZERO_CHAIN_ID,
[KAVA_CHAIN_ID]: KAVA_LAYER_ZERO_CHAIN_ID,
[LINEA_CHAIN_ID]: LINEA_LAYER_ZERO_CHAIN_ID,
[BASE_CHAIN_ID]: BASE_LAYER_ZERO_CHAIN_ID,
} as const

export const CHAIN_ID_ARRAY = [
ETH_LAYER_ZERO_CHAIN_ID,
BNB_LAYER_ZERO_CHAIN_ID,
Expand Down
51 changes: 50 additions & 1 deletion packages/stargate/src/contract-addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ import {
KAVA_LAYER_ZERO_CHAIN_ID,
LINEA_LAYER_ZERO_CHAIN_ID,
BASE_LAYER_ZERO_CHAIN_ID,
ETH_CHAIN_ID,
BNB_CHAIN_ID,
AVALANCHE_CHAIN_ID,
POLYGON_CHAIN_ID,
ARBITRUM_CHAIN_ID,
OPTIMISM_CHAIN_ID,
KAVA_CHAIN_ID,
LINEA_CHAIN_ID,
BASE_CHAIN_ID,
} from './chain-ids.js'

export const ETHEREUM_ETH_ROUTER = '0x150f94B44927F078737562f0fcF3C95c01Cc2376'
Expand Down Expand Up @@ -137,7 +146,7 @@ export const CHAIN_AND_POOL_TO_TOKEN_ADDRESS_UNUSED: {
}
*/

export const CHAIN_AND_POOL_TO_TOKEN_ADDRESS: {
export const CHAIN_ZERO_AND_POOL_TO_TOKEN_ADDRESS: {
[chainId: number]: { [address: string]: number }
} = {
[ETH_LAYER_ZERO_CHAIN_ID]: {
Expand Down Expand Up @@ -176,3 +185,43 @@ export const CHAIN_AND_POOL_TO_TOKEN_ADDRESS: {
'0x224d8fd7ab6ad4c6eb4611ce56ef35dec2277f03': ETH_POOL_ID,
},
}

export const CHAIN_ONE_AND_POOL_TO_TOKEN_ADDRESS: {
Copy link
Contributor

Choose a reason for hiding this comment

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

[very-nit] Not sure if CHAIN_ONE is best description for these. Wondering if we should use something like NATIVE_CHAIN_AND_POOL_TO_TOKEN_ADDRESS?

[chainId: number]: { [address: string]: number }
} = {
[ETH_CHAIN_ID]: {
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': USDC_POOL_ID,
'0xdAC17F958D2ee523a2206206994597C13D831ec7': USDT_POOL_ID,
'0x72E2F4830b9E45d52F80aC08CB2bEC0FeF72eD9c': ETH_POOL_ID,
},
[BNB_CHAIN_ID]: {
'0x55d398326f99059fF775485246999027B3197955': USDT_POOL_ID,
},
[AVALANCHE_CHAIN_ID]: {
'0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e': USDC_POOL_ID,
'0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7': USDT_POOL_ID,
},
[POLYGON_CHAIN_ID]: {
'0x2791bca1f2de4661ed88a30c99a7a9449aa84174': USDC_POOL_ID,
'0xc2132d05d31c914a87c6611c10748aeb04b58e8f': USDT_POOL_ID,
},
[ARBITRUM_CHAIN_ID]: {
'0xff970a61a04b1ca14834a43f5de4533ebddb5cc8': USDC_POOL_ID,
'0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9': USDT_POOL_ID,
'0x82cbecf39bee528b5476fe6d1550af59a9db6fc0': ETH_POOL_ID,
},
[OPTIMISM_CHAIN_ID]: {
'0x7f5c764cbc14f9669b88837ca1490cca17c31607': USDC_POOL_ID,
'0xb69c8cbcd90a39d8d3d3ccf0a3e968511c3856a0': ETH_POOL_ID,
},
[KAVA_CHAIN_ID]: {
'0x919c1c267bc06a7039e03fcc2ef738525769109c': USDT_POOL_ID,
},
[LINEA_CHAIN_ID]: {
'0x224d8fd7ab6ad4c6eb4611ce56ef35dec2277f03': ETH_POOL_ID,
},
[BASE_CHAIN_ID]: {
'0xd9aaec86b65d86f6a7b5b1b0c42ffa531710b6ca': USDC_POOL_ID,
'0x224d8fd7ab6ad4c6eb4611ce56ef35dec2277f03': ETH_POOL_ID,
},
}
22 changes: 11 additions & 11 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.