Skip to content

Commit

Permalink
Merge pull request #357 from rabbitholegg/mmackz/across
Browse files Browse the repository at this point in the history
feat(across): update for V3
  • Loading branch information
mmackz authored Apr 25, 2024
2 parents 2732c7c + 34ba4f9 commit 83be202
Show file tree
Hide file tree
Showing 12 changed files with 217 additions and 103 deletions.
5 changes: 5 additions & 0 deletions .changeset/odd-glasses-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rabbitholegg/questdk-plugin-across": minor
---

update for Across V3
4 changes: 2 additions & 2 deletions packages/across/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import babel from '@rollup/plugin-babel'
import resolve from '@rollup/plugin-node-resolve'
import terser from '@rollup/plugin-terser'
import commonjs from '@rollup/plugin-commonjs'
import json from '@rollup/plugin-json'
import resolve from '@rollup/plugin-node-resolve'
import terser from '@rollup/plugin-terser'
import polyfillNode from 'rollup-plugin-polyfill-node'

const extensions = ['.js', '.ts']
Expand Down
92 changes: 53 additions & 39 deletions packages/across/src/Across.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import { GreaterThanOrEqual, apply } from '@rabbitholegg/questdk'
import { describe, expect, test } from 'vitest'
import { bridge } from './Across'
import { bridge } from './Across.js'
import { ACROSS_BRIDGE_ABI } from './abi.js'
import { CHAIN_TO_SPOKEPOOL } from './contracts.js'
import {
DEPOSIT_ETH,
DEPOSIT_ERC20,
WITHDRAW_ETH,
DEPOSIT_ETH,
WITHDRAW_ERC20,
} from './test-transactions'
import {
ARBITRUM_CHAIN_ID,
ETH_CHAIN_ID,
POLYGON_CHAIN_ID,
OPTIMISM_CHAIN_ID,
} from './chain-ids'
import { ACROSS_BRIDGE_ABI } from './abi'
WITHDRAW_ETH,
failingTestCases,
passingTestCases,
} from './test-transactions.js'
import { Chains } from '@rabbitholegg/questdk-plugin-utils'
import { GreaterThanOrEqual, apply } from '@rabbitholegg/questdk/filter'
import { parseEther } from 'viem'
import { CHAIN_TO_CONTRACT } from './chain-to-contract'
import { describe, expect, test } from 'vitest'

export const WETH_ADRESS_MAINNET = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
export const WETH_ADDRESS_ARBITRUM =
Expand All @@ -24,27 +21,26 @@ export const USDT_ADDRESS_ARBITRUM =
'0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9'
export const USDT_ADDRESS_MAINNET = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

// Random ETHEREUM address
const TEST_USER = '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619'

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_CHAIN_ID,
destinationChainId: ETH_CHAIN_ID,
sourceChainId: Chains.ARBITRUM_ONE,
destinationChainId: Chains.ETHEREUM,
tokenAddress: USDT_ADDRESS_ARBITRUM,
amount: GreaterThanOrEqual(100000n),
recipient: TEST_USER,
})

expect(filter).to.deep.equal({
chainId: ARBITRUM_CHAIN_ID,
to: CHAIN_TO_CONTRACT[ARBITRUM_CHAIN_ID],
chainId: Chains.ARBITRUM_ONE,
to: CHAIN_TO_SPOKEPOOL[Chains.ARBITRUM_ONE],
input: {
$abi: ACROSS_BRIDGE_ABI,
recipient: TEST_USER,
destinationChainId: ETH_CHAIN_ID,
destinationChainId: Chains.ETHEREUM,
amount: {
$gte: '100000',
},
Expand All @@ -55,20 +51,20 @@ describe('Given the Across plugin', () => {

test('should return a valid bridge action filter for L1 token tx', async () => {
const filter = await bridge({
sourceChainId: ETH_CHAIN_ID,
destinationChainId: ARBITRUM_CHAIN_ID,
sourceChainId: Chains.ETHEREUM,
destinationChainId: Chains.ARBITRUM_ONE,
tokenAddress: USDT_ADDRESS_MAINNET,
amount: GreaterThanOrEqual(100000n),
recipient: TEST_USER,
})

expect(filter).to.deep.equal({
chainId: ETH_CHAIN_ID,
to: CHAIN_TO_CONTRACT[ETH_CHAIN_ID],
chainId: Chains.ETHEREUM,
to: CHAIN_TO_SPOKEPOOL[Chains.ETHEREUM],
input: {
$abi: ACROSS_BRIDGE_ABI,
recipient: TEST_USER,
destinationChainId: ARBITRUM_CHAIN_ID,
destinationChainId: Chains.ARBITRUM_ONE,
amount: {
$gte: '100000',
},
Expand All @@ -79,20 +75,20 @@ describe('Given the Across plugin', () => {

test('should return a valid bridge action filter for L1 ETH tx', async () => {
const filter = await bridge({
sourceChainId: ETH_CHAIN_ID,
destinationChainId: ARBITRUM_CHAIN_ID,
sourceChainId: Chains.ETHEREUM,
destinationChainId: Chains.ARBITRUM_ONE,
tokenAddress: WETH_ADRESS_MAINNET,
amount: GreaterThanOrEqual(100000n),
recipient: TEST_USER,
})

expect(filter).to.deep.equal({
chainId: ETH_CHAIN_ID,
to: CHAIN_TO_CONTRACT[ETH_CHAIN_ID],
chainId: Chains.ETHEREUM,
to: CHAIN_TO_SPOKEPOOL[Chains.ETHEREUM],
input: {
$abi: ACROSS_BRIDGE_ABI,
recipient: TEST_USER,
destinationChainId: ARBITRUM_CHAIN_ID,
destinationChainId: Chains.ARBITRUM_ONE,
amount: {
$gte: '100000',
},
Expand All @@ -105,8 +101,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_CHAIN_ID,
destinationChainId: OPTIMISM_CHAIN_ID,
sourceChainId: Chains.ETHEREUM,
destinationChainId: Chains.OPTIMISM,
tokenAddress: WETH_ADRESS_MAINNET,
amount: GreaterThanOrEqual(parseEther('.315')),
recipient: '0xE751378EC5E5c0b64c4D16A077E8f11FBcfC958A',
Expand All @@ -116,8 +112,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_CHAIN_ID,
destinationChainId: ETH_CHAIN_ID,
sourceChainId: Chains.ARBITRUM_ONE,
destinationChainId: Chains.ETHEREUM,
tokenAddress: WETH_ADDRESS_ARBITRUM,
amount: GreaterThanOrEqual(parseEther('.15')),
recipient: '0xbfe7A294ceD3Ce8C33c22c4dcAa6FD4522d6D32a',
Expand All @@ -127,8 +123,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_CHAIN_ID,
destinationChainId: POLYGON_CHAIN_ID,
sourceChainId: Chains.ETHEREUM,
destinationChainId: Chains.POLYGON_POS,
tokenAddress: USDT_ADDRESS_MAINNET,
amount: GreaterThanOrEqual('9900000'), // $250 USDC,
recipient: '0xb3b873a999cff617307A351e32a3dd7A94adD5B2',
Expand All @@ -138,8 +134,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_CHAIN_ID,
destinationChainId: POLYGON_CHAIN_ID,
sourceChainId: Chains.ARBITRUM_ONE,
destinationChainId: Chains.POLYGON_POS,
tokenAddress: USDT_ADDRESS_ARBITRUM,
amount: GreaterThanOrEqual('19000000'),
recipient: '0x49b887e3f64C7007E76f72C17cE29c7bcFb9Af55',
Expand All @@ -148,5 +144,23 @@ describe('Given the Across plugin', () => {
})
})

test('should not pass filter with invalid transactions', () => {})
describe('should pass filter with valid transactions', () => {
passingTestCases.forEach((testCase) => {
const { transaction, description, params } = testCase
test(description, async () => {
const filter = await bridge(params)
expect(apply(transaction, filter)).to.be.true
})
})
})

describe('should not pass filter with invalid transactions', () => {
failingTestCases.forEach((testCase) => {
const { transaction, description, params } = testCase
test(description, async () => {
const filter = await bridge(params)
expect(apply(transaction, filter)).to.be.false
})
})
})
})
40 changes: 25 additions & 15 deletions packages/across/src/Across.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
import { ACROSS_BRIDGE_ABI } from './abi.js'
import { CHAIN_ID_ARRAY } from './chain-ids.js'
import {
CHAIN_TO_SPOKEPOOL,
CHAIN_TO_SPOKE_VERIFIER,
CHAIN_TO_WETH,
} from './contracts.js'
import { type BridgeActionParams, compressJson } from '@rabbitholegg/questdk'
import { type Address } from 'viem'
import { CHAIN_ID_ARRAY } from './chain-ids'
import { ACROSS_BRIDGE_ABI } from './abi'
import { CHAIN_TO_CONTRACT } from './chain-to-contract'
import { CHAIN_TO_TOKENS } from '@rabbitholegg/questdk-plugin-utils'
import { type Address, zeroAddress } from 'viem'

export const bridge = async (bridge: BridgeActionParams) => {
// This is the information we'll use to compose the Transaction object
const { sourceChainId, destinationChainId, tokenAddress, amount, recipient } =
bridge

// We always want to return a compressed JSON object which we'll transform into a TransactionFilter
const isNative = tokenAddress === zeroAddress
const tokenIn = isNative ? CHAIN_TO_WETH[sourceChainId] : tokenAddress
const bridgeContract = isNative
? CHAIN_TO_SPOKE_VERIFIER[sourceChainId]
: CHAIN_TO_SPOKEPOOL[sourceChainId]

return compressJson({
chainId: sourceChainId, // The chainId of the source chain
to: CHAIN_TO_CONTRACT[sourceChainId], // The contract address of the bridge
chainId: sourceChainId,
to: bridgeContract,
input: {
$abi: ACROSS_BRIDGE_ABI, // The ABI of the bridge contract
recipient: recipient, // The recipient of the funds
destinationChainId: destinationChainId, // The chainId of the destination chain
amount: amount, // The amount of tokens to send
originToken: tokenAddress, // The token address of the token to send
}, // The input object is where we'll put the ABI and the parameters
$abi: ACROSS_BRIDGE_ABI,
recipient: recipient,
destinationChainId: destinationChainId,
amount: amount,
originToken: tokenIn,
},
})
}

export const getSupportedTokenAddresses = async (
_chainId: number,
): Promise<Address[]> => {
return []
return CHAIN_TO_TOKENS[_chainId] ?? []
}

export const getSupportedChainIds = async () => {
Expand Down
21 changes: 21 additions & 0 deletions packages/across/src/abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,25 @@ export const ACROSS_BRIDGE_ABI = [
stateMutability: 'payable',
type: 'function',
},
{
inputs: [
{
internalType: 'contract SpokePoolInterface',
name: 'spokePool',
type: 'address',
},
{ internalType: 'address', name: 'recipient', type: 'address' },
{ internalType: 'address', name: 'originToken', type: 'address' },
{ internalType: 'uint256', name: 'amount', type: 'uint256' },
{ internalType: 'uint256', name: 'destinationChainId', type: 'uint256' },
{ internalType: 'int64', name: 'relayerFeePct', type: 'int64' },
{ internalType: 'uint32', name: 'quoteTimestamp', type: 'uint32' },
{ internalType: 'bytes', name: 'message', type: 'bytes' },
{ internalType: 'uint256', name: 'maxCount', type: 'uint256' },
],
name: 'deposit',
outputs: [],
stateMutability: 'payable',
type: 'function',
},
]
21 changes: 9 additions & 12 deletions packages/across/src/chain-ids.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
export const ETH_CHAIN_ID = 1
export const OPTIMISM_CHAIN_ID = 10
export const ARBITRUM_CHAIN_ID = 42161
export const ZKSYNC_CHAIN_ID = 324
export const BASE_CHAIN_ID = 8453
export const POLYGON_CHAIN_ID = 137
import { Chains } from '@rabbitholegg/questdk-plugin-utils'

export const CHAIN_ID_ARRAY = [
ETH_CHAIN_ID,
POLYGON_CHAIN_ID,
OPTIMISM_CHAIN_ID,
ARBITRUM_CHAIN_ID,
ZKSYNC_CHAIN_ID,
BASE_CHAIN_ID,
Chains.ETHEREUM,
Chains.POLYGON_POS,
Chains.OPTIMISM,
Chains.ARBITRUM_ONE,
Chains.ZK_SYNC_ERA,
Chains.BASE,
Chains.LINEA,
]
24 changes: 0 additions & 24 deletions packages/across/src/chain-to-contract.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/across/src/contract-addresses.ts

This file was deleted.

30 changes: 30 additions & 0 deletions packages/across/src/contracts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Chains } from '@rabbitholegg/questdk-plugin-utils'
import { type Address } from 'viem'

export const CHAIN_TO_SPOKEPOOL: { [chainId: number]: Address } = {
[Chains.ETHEREUM]: '0x5c7bcd6e7de5423a257d81b442095a1a6ced35c5',
[Chains.POLYGON_POS]: '0x9295ee1d8c5b022be115a2ad3c30c72e34e7f096',
[Chains.OPTIMISM]: '0x6f26bf09b1c792e3228e5467807a900a503c0281',
[Chains.ARBITRUM_ONE]: '0xe35e9842fceaca96570b734083f4a58e8f7c5f2a',
[Chains.ZK_SYNC_ERA]: '0xe0b015e54d54fc84a6cb9b666099c46ade9335ff',
[Chains.BASE]: '0x09aea4b2242abc8bb4bb78d537a67a245a7bec64',
}

// Entry-point for Native tokens (ETH/MATIC)
export const CHAIN_TO_SPOKE_VERIFIER: { [chainId: number]: Address } = {
[Chains.ETHEREUM]: '0xb4a8d45647445ea9fc3e1058096142390683dbc2',
[Chains.POLYGON_POS]: '0xb4a8d45647445ea9fc3e1058096142390683dbc2',
[Chains.OPTIMISM]: '0xb4a8d45647445ea9fc3e1058096142390683dbc2',
[Chains.ARBITRUM_ONE]: '0xb4a8d45647445ea9fc3e1058096142390683dbc2',
[Chains.ZK_SYNC_ERA]: '0xe0b015e54d54fc84a6cb9b666099c46ade9335ff',
[Chains.BASE]: '0xb4a8d45647445ea9fc3e1058096142390683dbc2',
}

export const CHAIN_TO_WETH: { [chainId: number]: Address } = {
[Chains.ETHEREUM]: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
[Chains.POLYGON_POS]: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', // WMATIC
[Chains.OPTIMISM]: '0x4200000000000000000000000000000000000006',
[Chains.ARBITRUM_ONE]: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1',
[Chains.ZK_SYNC_ERA]: '0x5aea5775959fbc2557cc8789bc1bf90a239d9a91',
[Chains.BASE]: '0x4200000000000000000000000000000000000006',
}
11 changes: 6 additions & 5 deletions packages/across/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {
type IActionPlugin,
PluginActionNotImplementedError,
} from '@rabbitholegg/questdk'
import {
bridge,
getSupportedChainIds,
getSupportedTokenAddresses,
} from './Across'
} from './Across.js'
import {
type IActionPlugin,
PluginActionNotImplementedError,
} from '@rabbitholegg/questdk'

export const Across: IActionPlugin = {
pluginId: 'across',
getSupportedTokenAddresses,
Expand Down
Loading

0 comments on commit 83be202

Please sign in to comment.