Skip to content

Commit

Permalink
feat: arbitrum claims unchained-client parsing (#7645)
Browse files Browse the repository at this point in the history
* feat: arbitrum claims unchained-client parsing

* feat: tackle review comment

* feat: add migration
  • Loading branch information
gomesalexandre authored Aug 29, 2024
1 parent 489b1ce commit 6c94009
Show file tree
Hide file tree
Showing 9 changed files with 389 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export const arbitrumBridgeErc20Claim = {
txid: '0x48bd40a3cac5d25b21d2ae31375f6c273a3fe37f78cfca385e05a948038a1c57',
blockHash: '0x224eec4d01a99b1cd011bc5e89fd6ddd468e5b9ad1c9658b6ca852e487ee4d2b',
blockHeight: 20627282,
timestamp: 1724850443,
from: '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986',
to: '0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840',
confirmations: 918,
value: '0',
fee: '572048472071840',
gasLimit: '173616',
gasUsed: '151804',
gasPrice: '3768335960',
status: 1,
inputData:
'0x08635a950000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000001ef8600000000000000000000000009e9222e96e7b4ae2a407b98d48e330053351eee000000000000000000000000a3a7b6f88361f48403514059f1f16c8e78d60eec000000000000000000000000000000000000000000000000000000000e9c126d000000000000000000000000000000000000000000000000000000000139f4fd0000000000000000000000000000000000000000000000000000000066c59637000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000011a3a9ec71cd70cd6c5c28735e0ca94e88d19213cb3712a10f16804af32736dadf660e391a6d2ba4ce42c78d935c534dd9d89b6f9fe2fa1c43fa53c323687166fe81e3451e2ca4f9332b9b8edb7b68c457335f8156ea6deb8364b0e002fa274d8ab4da46c68619f49085e0a967f05321bc008239b73683b4657e87531737d6c03b80901f3842d0fd9f30a7cddbadd0d3db161126bf30566e90473f162bd6d3ab4e438ba8b56f0a949d82b9346e9a8edb83ffdbc1b0ffa37a3b1fb94bb16c33565b3d71b69c4375863736e0b3a729d787970ba6321d0db6337f712cb06ea57d808ebe61d1dd28e667943a8226262c9753fca8d76ef25ab0b1c434ab108736068568746df6bc1ac131f54f691aedd4ff0d57210b93f743a659f47b39b7ba4fc4617c68a53327828e6730f403e0a9f69774f3ced6c9a8c1526cf3f8de358c814f51d57ca5d92ec4f4e5e82e866dc2cc660e229a0b2cdd438ef0b7f83ede4e7ade5dd70ee286d9a814d510998ddeccef77f09a39bdf3d58f7c87ab126d9e739f9484890000000000000000000000000000000000000000000000000000000000000000f2ba2a36f24697a4a158278feea7c61d80a7095422e10a4ef78b94c9ed096508e293e3dc5befe34c72d718dc7b2e5f5cfdeb11a8c3387f0811a76c1d8825903cc0425084107ea9f7a4118f5ed1e3566cda4e90b550363fc804df1e52ed5f2386b43a6b28077d49f37d58c87aec0b51f7bce13b648143f3295385f3b3d5ac3b9b00000000000000000000000000000000000000000000000000000000000001242e567b36000000000000000000000000c770eefad204b5180df6a14ee197d99d808ee52d0000000000000000000000005daf465a9ccf64deb146eeae9e7bd40d6761c9860000000000000000000000005daf465a9ccf64deb146eeae9e7bd40d6761c9860000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000005f2e0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
tokenTransfers: [
{
contract: '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d',
decimals: 18,
name: 'FOX',
symbol: 'FOX',
type: 'ERC20',
from: '0xa3A7B6F88361F48403514059F1F16C8E78d60EeC',
to: '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986',
value: '1000000000000000000',
},
],
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const arbitrumBridgeNativeClaim = {
txid: '0x88d984a81220fe9d45ec0cdc07c56ad22cb31439ac6d5abfe32c069990d86f56',
blockHash: '0x22ec673c7bc57087312a368b26abfd183ddb0c19fb225c7c86d15d7d2f3da047',
blockHeight: 20627308,
timestamp: 1724850755,
from: '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986',
to: '0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840',
confirmations: 892,
value: '0',
fee: '369113082579370',
gasLimit: '113784',
gasUsed: '95707',
gasPrice: '3856698910',
status: 1,
inputData:
'0x08635a950000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000001d29c0000000000000000000000005daf465a9ccf64deb146eeae9e7bd40d6761c9860000000000000000000000005daf465a9ccf64deb146eeae9e7bd40d6761c986000000000000000000000000000000000000000000000000000000000cca139900000000000000000000000000000000000000000000000000000000013043d1000000000000000000000000000000000000000000000000000000006650a28500000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000011bafffd8826a325f6dcf8db90a642f439cd39f329aea96c09a0073b447c0d84dfdd07e249c412a147d10d7bd3655e5932b94c7c49ac8524e1da20fb495605a4a4ba3ae4632ba61b4c2ff2243aae6ace7c25279f77ba3931df68d8e2421349103b59072b53dbdcd411841ebf9b6408a1fb165d5602d3e6c3ce9e2ec85b6bfbec03b7ac99f6de83af7f5a826998915f3b91bac955bd413085bacb1a4f0fe7e1345dc93d736e090830d442d11c9ea2c2d79e8fc987e1fba31d54daca4c4a2e71170569952c047831bfe5549f296f31ea13162aa14e640e74e696f5f9dc15379552bded5ab9ae42c96523909724b5d766a3cd03bf89770647ff59dcb0e165bd13e116fb84b7ccbf7731434213ef92095048795da4885d13bef2c31887b504a0e45f424f6ace293f8762a87ad640939ad4ff4df1cfc82260fa73efbabf5747713bd104061994733acbf859be63941c3770d9caa220d0ff30cf4681b966c9992d68dbd9f1593d92c2a207e2edd1a9bd661ccf373eda39750f310e547a79422a97f54c5c815ea3a0a2819747d8c6ab7870bad0a01b006d2333b876eadcf308bde637c9d269106634d68ee17e676555d1e82fa65fbfe607b63e7594de0da751593d7c5c6ae293e3dc5befe34c72d718dc7b2e5f5cfdeb11a8c3387f0811a76c1d8825903cc0425084107ea9f7a4118f5ed1e3566cda4e90b550363fc804df1e52ed5f2386b43a6b28077d49f37d58c87aec0b51f7bce13b648143f3295385f3b3d5ac3b9b0000000000000000000000000000000000000000000000000000000000000000',
internalTxs: [
{
from: '0x8315177aB297bA92A06054cE80a67Ed4DBd7ed3a',
to: '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986',
value: '1000000000000000',
},
],
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { beforeAll, describe, expect, it, vi } from 'vitest'
import type { Trade } from '../../../../types'
import { Dex, TradeType, TransferType, TxStatus } from '../../../../types'
import type { Api } from '../../..'
import { arbitrumBridgeErc20Claim } from '../../../arbitrum/parser/__tests__/mockData/arbitrumBridgeErc20Claim'
import { arbitrumBridgeErc20DepositTx } from '../../../arbitrum/parser/__tests__/mockData/arbitrumBridgeErc20DepositTx'
import { arbitrumBridgeNativeClaim } from '../../../arbitrum/parser/__tests__/mockData/arbitrumBridgeNativeClaim'
import { arbitrumBridgeNativeCreateRetryableTicketTx } from '../../../arbitrum/parser/__tests__/mockData/arbitrumBridgeNativeCreateRetryableTicketTx'
import { arbitrumBridgeNativeDepositTx } from '../../../arbitrum/parser/__tests__/mockData/arbitrumBridgeNativeDepositTx'
import type { ParsedTx } from '../../../parser'
Expand Down Expand Up @@ -3238,6 +3240,103 @@ describe('parseTx', () => {
const txParser = await makeTxParser()
const actual = await txParser.parse(tx, address)

expect(actual).toEqual(expected)
})
it('should be able to parse erc20 claim', async () => {
const tx = arbitrumBridgeErc20Claim
const address = '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986'

const expected = {
address: '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986',
blockHash: '0x224eec4d01a99b1cd011bc5e89fd6ddd468e5b9ad1c9658b6ca852e487ee4d2b',
blockHeight: 20627282,
blockTime: 1724850443,
chainId: 'eip155:1',
confirmations: 918,
data: {
assetId: 'eip155:1/erc20:0xc770eefad204b5180df6a14ee197d99d808ee52d',
method: 'executeTransaction',
parser: 'arbitrumBridge',
},
fee: {
assetId: 'eip155:1/slip44:60',
value: '572048472071840',
},
status: 'Confirmed',
trade: undefined,
transfers: [
{
assetId: 'eip155:1/erc20:0xc770eefad204b5180df6a14ee197d99d808ee52d',
components: [
{
value: '1000000000000000000',
},
],
from: '0xa3A7B6F88361F48403514059F1F16C8E78d60EeC',
id: undefined,
to: '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986',
token: {
contract: '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d',
decimals: 18,
name: 'FOX',
symbol: 'FOX',
},
totalValue: '1000000000000000000',
type: 'Receive',
},
],
txid: '0x48bd40a3cac5d25b21d2ae31375f6c273a3fe37f78cfca385e05a948038a1c57',
}

const txParser = await makeTxParser()
const actual = await txParser.parse(tx, address)

expect(actual).toEqual(expected)
})
it('should be able to parse ETH claim', async () => {
const tx = arbitrumBridgeNativeClaim
const address = '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986'

const expected = {
address: '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986',
blockHash: '0x22ec673c7bc57087312a368b26abfd183ddb0c19fb225c7c86d15d7d2f3da047',
blockHeight: 20627308,
blockTime: 1724850755,
chainId: 'eip155:1',
confirmations: 892,
data: {
assetId: undefined,
method: 'executeTransaction',
parser: 'arbitrumBridge',
},
fee: {
assetId: 'eip155:1/slip44:60',
value: '369113082579370',
},
status: 'Confirmed',
trade: undefined,
transfers: [
{
assetId: 'eip155:1/slip44:60',
components: [
{
value: '1000000000000000',
},
],
from: '0x8315177aB297bA92A06054cE80a67Ed4DBd7ed3a',
id: undefined,
to: '0x5daF465a9cCf64DEB146eEaE9E7Bd40d6761c986',
token: undefined,
totalValue: '1000000000000000',
type: 'Receive',
},
],
txid: '0x88d984a81220fe9d45ec0cdc07c56ad22cb31439ac6d5abfe32c069990d86f56',
}

const txParser = await makeTxParser()
const actual = await txParser.parse(tx, address)

expect(actual).toEqual(expected)
})
})
Expand Down
228 changes: 228 additions & 0 deletions packages/unchained-client/src/evm/parser/abi/ArbOutbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import type { InterfaceAbi } from 'ethers'

// https://etherscan.io/address/0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840
export const ARB_OUTBOX_ABI: InterfaceAbi = [
{ inputs: [], name: 'AlreadyInit', type: 'error' },
{
inputs: [{ internalType: 'uint256', name: 'index', type: 'uint256' }],
name: 'AlreadySpent',
type: 'error',
},
{ inputs: [], name: 'BridgeCallFailed', type: 'error' },
{ inputs: [], name: 'HadZeroInit', type: 'error' },
{
inputs: [
{ internalType: 'uint256', name: 'actualLength', type: 'uint256' },
{ internalType: 'uint256', name: 'maxProofLength', type: 'uint256' },
],
name: 'MerkleProofTooLong',
type: 'error',
},
{
inputs: [
{ internalType: 'address', name: 'sender', type: 'address' },
{ internalType: 'address', name: 'rollup', type: 'address' },
],
name: 'NotRollup',
type: 'error',
},
{
inputs: [
{ internalType: 'uint256', name: 'index', type: 'uint256' },
{ internalType: 'uint256', name: 'maxIndex', type: 'uint256' },
],
name: 'PathNotMinimal',
type: 'error',
},
{
inputs: [{ internalType: 'uint256', name: 'proofLength', type: 'uint256' }],
name: 'ProofTooLong',
type: 'error',
},
{ inputs: [], name: 'SimulationOnlyEntrypoint', type: 'error' },
{
inputs: [{ internalType: 'bytes32', name: 'root', type: 'bytes32' }],
name: 'UnknownRoot',
type: 'error',
},
{
anonymous: false,
inputs: [
{ indexed: true, internalType: 'address', name: 'to', type: 'address' },
{ indexed: true, internalType: 'address', name: 'l2Sender', type: 'address' },
{ indexed: true, internalType: 'uint256', name: 'zero', type: 'uint256' },
{ indexed: false, internalType: 'uint256', name: 'transactionIndex', type: 'uint256' },
],
name: 'OutBoxTransactionExecuted',
type: 'event',
},
{
anonymous: false,
inputs: [
{ indexed: true, internalType: 'bytes32', name: 'blockHash', type: 'bytes32' },
{ indexed: true, internalType: 'bytes32', name: 'outputRoot', type: 'bytes32' },
],
name: 'SendRootUpdated',
type: 'event',
},
{
inputs: [],
name: 'OUTBOX_VERSION',
outputs: [{ internalType: 'uint128', name: '', type: 'uint128' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'bridge',
outputs: [{ internalType: 'contract IBridge', name: '', type: 'address' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{ internalType: 'address', name: 'l2Sender', type: 'address' },
{ internalType: 'address', name: 'to', type: 'address' },
{ internalType: 'uint256', name: 'l2Block', type: 'uint256' },
{ internalType: 'uint256', name: 'l1Block', type: 'uint256' },
{ internalType: 'uint256', name: 'l2Timestamp', type: 'uint256' },
{ internalType: 'uint256', name: 'value', type: 'uint256' },
{ internalType: 'bytes', name: 'data', type: 'bytes' },
],
name: 'calculateItemHash',
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
stateMutability: 'pure',
type: 'function',
},
{
inputs: [
{ internalType: 'bytes32[]', name: 'proof', type: 'bytes32[]' },
{ internalType: 'uint256', name: 'path', type: 'uint256' },
{ internalType: 'bytes32', name: 'item', type: 'bytes32' },
],
name: 'calculateMerkleRoot',
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
stateMutability: 'pure',
type: 'function',
},
{
inputs: [
{ internalType: 'bytes32[]', name: 'proof', type: 'bytes32[]' },
{ internalType: 'uint256', name: 'index', type: 'uint256' },
{ internalType: 'address', name: 'l2Sender', type: 'address' },
{ internalType: 'address', name: 'to', type: 'address' },
{ internalType: 'uint256', name: 'l2Block', type: 'uint256' },
{ internalType: 'uint256', name: 'l1Block', type: 'uint256' },
{ internalType: 'uint256', name: 'l2Timestamp', type: 'uint256' },
{ internalType: 'uint256', name: 'value', type: 'uint256' },
{ internalType: 'bytes', name: 'data', type: 'bytes' },
],
name: 'executeTransaction',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{ internalType: 'uint256', name: 'index', type: 'uint256' },
{ internalType: 'address', name: 'l2Sender', type: 'address' },
{ internalType: 'address', name: 'to', type: 'address' },
{ internalType: 'uint256', name: 'l2Block', type: 'uint256' },
{ internalType: 'uint256', name: 'l1Block', type: 'uint256' },
{ internalType: 'uint256', name: 'l2Timestamp', type: 'uint256' },
{ internalType: 'uint256', name: 'value', type: 'uint256' },
{ internalType: 'bytes', name: 'data', type: 'bytes' },
],
name: 'executeTransactionSimulation',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [{ internalType: 'contract IBridge', name: '_bridge', type: 'address' }],
name: 'initialize',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [{ internalType: 'uint256', name: 'index', type: 'uint256' }],
name: 'isSpent',
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'l2ToL1BatchNum',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'pure',
type: 'function',
},
{
inputs: [],
name: 'l2ToL1Block',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'l2ToL1EthBlock',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'l2ToL1OutputId',
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'l2ToL1Sender',
outputs: [{ internalType: 'address', name: '', type: 'address' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'l2ToL1Timestamp',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'rollup',
outputs: [{ internalType: 'address', name: '', type: 'address' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
name: 'roots',
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
name: 'spent',
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{ internalType: 'bytes32', name: 'root', type: 'bytes32' },
{ internalType: 'bytes32', name: 'l2BlockHash', type: 'bytes32' },
],
name: 'updateSendRoot',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
]
Loading

0 comments on commit 6c94009

Please sign in to comment.