Skip to content

Commit

Permalink
feat: ETH connector migration.
Browse files Browse the repository at this point in the history
  • Loading branch information
paouvrard committed Jul 11, 2024
1 parent 400168e commit cfd32b7
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 100 deletions.
12 changes: 12 additions & 0 deletions .yarn/versions/55773dcb.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
releases:
"@near-eth/aurora-erc20": minor
"@near-eth/aurora-ether": major
"@near-eth/aurora-nep141": patch
"@near-eth/near-ether": major
"@near-eth/nep141-erc20": patch
"@near-eth/rainbow": major
"@near-eth/utils": patch
rainbow-bridge-client-monorepo: major

declined:
- "@near-eth/client"
75 changes: 39 additions & 36 deletions packages/aurora-erc20/src/bridged-erc20/sendToEthereum/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ const steps = [
UNLOCK
]

class TransferError extends Error {}

export interface TransferDraft extends TransferStatus {
type: string
finalityBlockHeights: number[]
Expand Down Expand Up @@ -89,6 +87,8 @@ export interface TransferOptions {
ethClientAbi?: string
nep141Factory?: string
auroraEvmAccount?: string
etherNep141Factory?: string
etherNep141FactoryMigrationHeight?: number
}

const transferDraft: TransferDraft = {
Expand Down Expand Up @@ -261,6 +261,8 @@ export async function recover (
options?: TransferOptions & {
decimals?: number
symbol?: string
etherNep141Factory?: string
etherNep141FactoryMigrationHeight?: number
}
): Promise<Transfer> {
options = options ?? {}
Expand Down Expand Up @@ -297,9 +299,10 @@ export async function recover (
}

const bridgeParams = getBridgeParams()
const nep141Factory = options.nep141Factory ?? bridgeParams.nep141Factory
const auroraEvmAccount = options.auroraEvmAccount ?? bridgeParams.auroraEvmAccount
let nearBurnReceipt, amount, recipient, symbol, decimals
if (options.symbol !== 'ETH') {
const nep141Factory = options.nep141Factory ?? bridgeParams.nep141Factory
nearBurnReceipt = await parseNep141BurnReceipt(burnTx, nep141Factory, nearProvider)
amount = nearBurnReceipt.event.amount
recipient = nearBurnReceipt.event.recipient
Expand All @@ -308,8 +311,14 @@ export async function recover (
decimals = options.decimals ?? await getDecimals({ erc20Address, options })
} else {
// Withdraw ERC-20 ETH from a silo which doesn't use ETH as native currency.
const auroraEvmAccount = options.auroraEvmAccount ?? bridgeParams.auroraEvmAccount
nearBurnReceipt = await parseETHBurnReceipt(burnTx, auroraEvmAccount, nearProvider)
// @ts-expect-error
const txBlock = await nearProvider.block({ blockId: burnTx.transaction_outcome.block_hash })
const blockHeight = Number(txBlock.header.height)
const etherNep141FactoryMigrationHeight = options.etherNep141FactoryMigrationHeight ?? bridgeParams.etherNep141FactoryMigrationHeight
const etherNep141Factory = blockHeight >= etherNep141FactoryMigrationHeight
? (options.etherNep141Factory ?? bridgeParams.etherNep141Factory)
: auroraEvmAccount
nearBurnReceipt = await parseETHBurnReceipt(burnTx, etherNep141Factory, nearProvider)
amount = nearBurnReceipt.event.amount
recipient = nearBurnReceipt.event.recipient
symbol = options.symbol
Expand All @@ -321,15 +330,12 @@ export async function recover (
const sourceTokenName = 'a' + symbol
const destinationTokenName = symbol

// @ts-expect-error TODO
const txBlock = await nearProvider.block({ blockId: burnTx.transaction_outcome.block_hash })

// various attributes stored as arrays, to keep history of retries
const transfer = {
...transferDraft,

id: Math.random().toString().slice(2),
startTime: new Date(txBlock.header.timestamp / 10 ** 6).toISOString(),
startTime: new Date(nearBurnReceipt.blockTimestamp / 10 ** 6).toISOString(),
amount,
completedStep: BURN,
destinationTokenName,
Expand All @@ -339,7 +345,7 @@ export async function recover (
sourceToken,
symbol,
decimals,
auroraEvmAccount: options.auroraEvmAccount ?? bridgeParams.auroraEvmAccount,
auroraEvmAccount,
auroraChainId: options.auroraChainId ?? bridgeParams.auroraChainId,
burnHashes: [burnTxHash],
nearBurnHashes: [nearBurnTxHash],
Expand Down Expand Up @@ -502,6 +508,8 @@ export async function checkBurn (
nearAccount?: Account
nearProvider?: najProviders.Provider
nep141Factory?: string
etherNep141Factory?: string
etherNep141FactoryMigrationHeight?: number
}
): Promise<Transfer> {
options = options ?? {}
Expand Down Expand Up @@ -598,35 +606,26 @@ export async function checkBurn (
}

let nearBurnReceipt
const nep141Factory = options.nep141Factory ?? getBridgeParams().nep141Factory
try {
if (transfer.symbol !== 'ETH') {
nearBurnReceipt = await parseNep141BurnReceipt(nearBurnTx, nep141Factory, nearProvider)
} else {
// Withdraw ERC-20 ETH from a silo which doesn't use ETH as native currency.
nearBurnReceipt = await parseETHBurnReceipt(nearBurnTx, transfer.auroraEvmAccount ?? 'aurora', nearProvider)
}
} catch (e) {
if (e instanceof TransferError) {
return {
...transfer,
errors: [...transfer.errors, e.message],
status: status.FAILED
}
}
// Any other error like provider connection error should throw
// so that the transfer stays in progress and checkWithdraw will be called again.
throw e
if (transfer.symbol !== 'ETH') {
const nep141Factory = options.nep141Factory ?? bridgeParams.nep141Factory
nearBurnReceipt = await parseNep141BurnReceipt(nearBurnTx, nep141Factory, nearProvider)
} else {
// Withdraw ERC-20 ETH from a silo which doesn't use ETH as native currency.
// @ts-expect-error
const txBlock = await nearProvider.block({ blockId: nearBurnTx.transaction_outcome.block_hash })
const blockHeight = Number(txBlock.header.height)
const etherNep141FactoryMigrationHeight = options.etherNep141FactoryMigrationHeight ?? bridgeParams.etherNep141FactoryMigrationHeight
const etherNep141Factory = blockHeight >= etherNep141FactoryMigrationHeight
? (options.etherNep141Factory ?? bridgeParams.etherNep141Factory)
: bridgeParams.auroraEvmAccount
nearBurnReceipt = await parseETHBurnReceipt(nearBurnTx, etherNep141Factory, nearProvider)
}

// @ts-expect-error TODO
const txBlock = await nearProvider.block({ blockId: nearBurnTx.transaction_outcome.block_hash })

return {
...transfer,
status: status.IN_PROGRESS,
completedStep: BURN,
startTime: new Date(txBlock.header.timestamp / 10 ** 6).toISOString(),
startTime: new Date(nearBurnReceipt.blockTimestamp / 10 ** 6).toISOString(),
burnReceipts: [...transfer.burnReceipts, burnReceipt],
nearBurnHashes: [...transfer.nearBurnHashes, nearBurnHash],
nearBurnReceiptIds: [...transfer.nearBurnReceiptIds, nearBurnReceipt.id],
Expand Down Expand Up @@ -716,12 +715,15 @@ export async function checkSync (
options.nearAccount?.connection.provider ??
getNearProvider()
if (nearOnEthClientBlockHeight > burnBlockHeight) {
const etherNep141FactoryMigrationHeight = options.etherNep141FactoryMigrationHeight ?? bridgeParams.etherNep141FactoryMigrationHeight
const etherNep141Factory = burnBlockHeight >= etherNep141FactoryMigrationHeight
? (options.etherNep141Factory ?? bridgeParams.etherNep141Factory)
: bridgeParams.auroraEvmAccount
proof = await findNearProof(
last(transfer.nearBurnReceiptIds),
// NOTE: If ETH is being transfered with @near-eth/aurora-erc20,
// it means that ETH is not the silo's native currency
// NOTE: If ETH is being transfered with @near-eth/aurora-erc20, it means that ETH is not the silo's native currency
transfer.symbol === 'ETH'
? bridgeParams.auroraEvmAccount
? etherNep141Factory
: (options.nep141Factory ?? bridgeParams.nep141Factory),
nearOnEthClientBlockHeight,
nearProvider,
Expand Down Expand Up @@ -835,6 +837,7 @@ export async function unlock (
// in case there was a reorg.
const safeReorgHeight = await provider.getBlockNumber() - 20
const pendingUnlockTx = await ethTokenLocker.unlockToken(borshProof, transfer.nearOnEthClientBlockHeight)
// TODO: Handle etherCustodian.withdraw when ETH is not the native silo token.

return {
...transfer,
Expand Down
62 changes: 35 additions & 27 deletions packages/aurora-ether/src/bridged-ether/sendToEthereum/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ const steps = [
UNLOCK
]

class TransferError extends Error {}

export interface TransferDraft extends TransferStatus {
type: string
finalityBlockHeights: number[]
Expand Down Expand Up @@ -88,6 +86,8 @@ export interface TransferOptions {
auroraProvider?: ethers.providers.JsonRpcProvider
auroraEvmAccount?: string
symbol?: string
etherNep141Factory?: string
etherNep141FactoryMigrationHeight?: number
}

const transferDraft: TransferDraft = {
Expand Down Expand Up @@ -246,6 +246,8 @@ export async function recover (
sender: string = 'todo',
options?: TransferOptions & {
nep141Factory?: string
etherNep141Factory?: string
etherNep141FactoryMigrationHeight?: number
}
): Promise<Transfer> {
options = options ?? {}
Expand Down Expand Up @@ -286,12 +288,19 @@ export async function recover (
let recipient
if (options.symbol && options.symbol !== 'ETH') {
// Withdraw native currency from a silo which doesn't use ETH as native currency
const nep141Factory = options.nep141Factory ?? getBridgeParams().nep141Factory
const nep141Factory = options.nep141Factory ?? bridgeParams.nep141Factory
nearBurnReceipt = await parseNep141BurnReceipt(burnTx, nep141Factory, nearProvider)
amount = nearBurnReceipt.event.amount
recipient = nearBurnReceipt.event.recipient
} else {
nearBurnReceipt = await parseETHBurnReceipt(burnTx, auroraEvmAccount, nearProvider)
// @ts-expect-error
const txBlock = await nearProvider.block({ blockId: burnTx.transaction_outcome.block_hash })
const blockHeight = Number(txBlock.header.height)
const etherNep141FactoryMigrationHeight = options.etherNep141FactoryMigrationHeight ?? bridgeParams.etherNep141FactoryMigrationHeight
const etherNep141Factory = blockHeight >= etherNep141FactoryMigrationHeight
? (options.etherNep141Factory ?? bridgeParams.etherNep141Factory)
: auroraEvmAccount
nearBurnReceipt = await parseETHBurnReceipt(burnTx, etherNep141Factory, nearProvider)
amount = nearBurnReceipt.event.amount
recipient = nearBurnReceipt.event.recipient
}
Expand Down Expand Up @@ -485,6 +494,8 @@ export async function checkBurn (
nearAccount?: Account
nearProvider?: najProviders.Provider
nep141Factory?: string
etherNep141Factory?: string
etherNep141FactoryMigrationHeight?: number
}
): Promise<Transfer> {
options = options ?? {}
Expand Down Expand Up @@ -580,25 +591,19 @@ export async function checkBurn (
}

let nearBurnReceipt
try {
if (transfer.symbol !== 'ETH') {
// Withdraw native currency from a silo which doesn't use ETH as native currency
const nep141Factory = options.nep141Factory ?? getBridgeParams().nep141Factory
nearBurnReceipt = await parseNep141BurnReceipt(nearBurnTx, nep141Factory, nearProvider)
} else {
nearBurnReceipt = await parseETHBurnReceipt(nearBurnTx, transfer.auroraEvmAccount ?? 'aurora', nearProvider)
}
} catch (e) {
if (e instanceof TransferError) {
return {
...transfer,
errors: [...transfer.errors, e.message],
status: status.FAILED
}
}
// Any other error like provider connection error should throw
// so that the transfer stays in progress and checkWithdraw will be called again.
throw e
if (transfer.symbol !== 'ETH') {
// Withdraw native currency from a silo which doesn't use ETH as native currency
const nep141Factory = options.nep141Factory ?? bridgeParams.nep141Factory
nearBurnReceipt = await parseNep141BurnReceipt(nearBurnTx, nep141Factory, nearProvider)
} else {
// @ts-expect-error
const txBlock = await nearProvider.block({ blockId: nearBurnTx.transaction_outcome.block_hash })
const blockHeight = Number(txBlock.header.height)
const etherNep141FactoryMigrationHeight = options.etherNep141FactoryMigrationHeight ?? bridgeParams.etherNep141FactoryMigrationHeight
const etherNep141Factory = blockHeight >= etherNep141FactoryMigrationHeight
? (options.etherNep141Factory ?? bridgeParams.etherNep141Factory)
: bridgeParams.auroraEvmAccount
nearBurnReceipt = await parseETHBurnReceipt(nearBurnTx, etherNep141Factory, nearProvider)
}

return {
Expand Down Expand Up @@ -693,14 +698,16 @@ export async function checkSync (
options.nearAccount?.connection.provider ??
getNearProvider()
if (nearOnEthClientBlockHeight > burnBlockHeight) {
const etherNep141FactoryMigrationHeight = options.etherNep141FactoryMigrationHeight ?? bridgeParams.etherNep141FactoryMigrationHeight
const etherNep141Factory = burnBlockHeight >= etherNep141FactoryMigrationHeight
? (options.etherNep141Factory ?? bridgeParams.etherNep141Factory)
: bridgeParams.auroraEvmAccount
proof = await findNearProof(
last(transfer.nearBurnReceiptIds),
// NOTE: options.auroraEvmAccount cannot be used because checkSync can be called by recover using a different silo's auroraEvmAccount.
// NOTE: If another token than ETH is being transfered with @near-eth/aurora-ether,
// it means that ETH is not the silo's native currency
// NOTE: If another token than ETH is being transfered with @near-eth/aurora-ether it means that ETH is not the silo's native currency
transfer.symbol !== 'ETH'
? bridgeParams.nep141Factory
: bridgeParams.auroraEvmAccount,
: etherNep141Factory,
nearOnEthClientBlockHeight,
nearProvider,
provider,
Expand Down Expand Up @@ -813,6 +820,7 @@ export async function unlock (
// in case there was a reorg.
const safeReorgHeight = await provider.getBlockNumber() - 20
const pendingUnlockTx = await ethTokenLocker.withdraw(borshProof, transfer.nearOnEthClientBlockHeight)
// TODO: Handle erc20Locker.unlockToken when ETH is not the native silo token.

return {
...transfer,
Expand Down
19 changes: 15 additions & 4 deletions packages/aurora-ether/src/natural-ether/sendToAurora/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface TransferOptions {
nearClientAccount?: string
callIndexer?: (query: string) => Promise<ExplorerIndexerResult[] | string>
eventRelayerAccount?: string
etherNep141Factory?: string
}

const transferDraft: TransferDraft = {
Expand Down Expand Up @@ -529,15 +530,25 @@ export async function checkSync (
options.etherCustodianAbi ?? bridgeParams.etherCustodianAbi,
provider
)
const result = await nearProvider.query<CodeResult>({
let result = await nearProvider.query<CodeResult>({
request_type: 'call_function',
// NOTE: options.auroraEvmAccount cannot be used because checkSync can be called by recover using a different silo's auroraEvmAccount.
account_id: bridgeParams.auroraEvmAccount,
account_id: options.etherNep141Factory ?? bridgeParams.etherNep141Factory,
method_name: 'is_used_proof',
args_base64: Buffer.from(proof).toString('base64'),
finality: 'optimistic'
})
const proofAlreadyUsed = Boolean(result.result[0])
let proofAlreadyUsed = Boolean(result.result[0])
if (!proofAlreadyUsed) {
result = await nearProvider.query<CodeResult>({
request_type: 'call_function',
// NOTE: options.auroraEvmAccount cannot be used because checkSync can be called by recover using a different silo's auroraEvmAccount.
account_id: bridgeParams.auroraEvmAccount,
method_name: 'is_used_proof',
args_base64: Buffer.from(proof).toString('base64'),
finality: 'optimistic'
})
proofAlreadyUsed = Boolean(result.result[0])
}
if (proofAlreadyUsed) {
if (options.callIndexer) {
try {
Expand Down
8 changes: 7 additions & 1 deletion packages/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ import {
| ERC-20 | nep141Erc20/naturalErc20/sendToNear | auroraErc20/naturalErc20/sendToAurora |
| | nep141Erc20/bridgedErc20/sendToNear | auroraErc20/bridgedErc20/sendToAurora (TODO) |
| ETH | nearEther/naturalETH/sendToNear | auroraEther/naturalEther/sendToAurora |
| NEAR | nearEther.bridgedNEAR.sendToNear | (TODO) |
| NEAR | nearEther.bridgedNEAR.sendToNear | auroraErc20/eNEAR/sendToAurora |
| ERC-721 | (TODO) | (TODO) |

| from NEAR | to Ethereum | to Aurora |
Expand Down Expand Up @@ -522,6 +522,9 @@ setBridgeParams({
// https://github.com/Near-One/rainbow-token-connector/tree/master/erc20-bridge-token
erc20FactoryAddress: '0x252e87862A3A720287E7fd527cE6e8d0738427A2',
erc20FactoryAbi: process.env.erc20FactoryAbi,
// https://github.com/Near-One/aurora-eth-connector
etherNep141Factory: 'eth.bridge.near',
etherNep141FactoryMigrationHeight: 0, // TODO
})
```

Expand Down Expand Up @@ -574,5 +577,8 @@ setBridgeParams({
// https://github.com/Near-One/rainbow-token-connector/tree/master/erc20-bridge-token
erc20FactoryAddress: '0xa9108f7F83Fb661e611991116D526fCa1a9585ab',
erc20FactoryAbi: process.env.erc20FactoryAbi,
// https://github.com/Near-One/aurora-eth-connector
etherNep141Factory: 'eth.sepolia.testnet',
etherNep141FactoryMigrationHeight: 0, // TODO
})
```
Loading

0 comments on commit cfd32b7

Please sign in to comment.