-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
4a0c7c2
commit dbb0c3f
Showing
4 changed files
with
136 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { ethers } from 'ethers'; | ||
import { getWithdrawRootToken } from './axelarUtils'; | ||
|
||
const rootToken = '0x1f9090aaE28b8a3dCeaDf281B0F12828e676c326'; | ||
describe('Axelar', () => { | ||
const mockERC20Contract = { | ||
allowance: jest.fn(), | ||
interface: { | ||
encodeFunctionData: jest.fn(), | ||
}, | ||
rootToken: jest.fn().mockImplementation(async () => rootToken), | ||
}; | ||
describe('getWithdrawRootToken', () => { | ||
beforeEach(() => { | ||
jest.spyOn(ethers, 'Contract').mockReturnValue(mockERC20Contract as any); | ||
}); | ||
|
||
it('should return the root token for a child token', async () => { | ||
const childToken = '0x388c818ca8b9251b393131c08a736a67ccb19297'; | ||
const destinationChainId = '1'; | ||
const mockChildProvider = new ethers.providers.JsonRpcProvider('x'); | ||
const receivedRootToken = await getWithdrawRootToken( | ||
childToken, | ||
destinationChainId, | ||
mockChildProvider, | ||
); | ||
expect(receivedRootToken).toEqual(rootToken); | ||
}); | ||
|
||
it('should return the root IMX token withdrawing NATIVE', async () => { | ||
const childToken = 'NATIVE'; | ||
const destinationChainId = '1'; | ||
const mockChildProvider = new ethers.providers.JsonRpcProvider('x'); | ||
const receivedRootToken = await getWithdrawRootToken( | ||
childToken, | ||
destinationChainId, | ||
mockChildProvider, | ||
); | ||
|
||
const rootIMX = '0xf57e7e7c23978c3caec3c3548e3d615c346e79ff'; | ||
expect(receivedRootToken).toEqual(rootIMX); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { Provider } from '@ethersproject/providers'; | ||
import { Address } from 'types'; | ||
import { WITHDRAW_SIG, NATIVE } from 'constants/bridges'; | ||
import { CHILD_ERC20 } from 'contracts/ABIs/ChildERC20'; | ||
import { withBridgeError, BridgeErrorType } from 'errors'; | ||
import { ethers } from 'ethers'; | ||
import { keccak256, defaultAbiCoder } from 'ethers/lib/utils'; | ||
import { isWrappedIMX, getRootIMX } from './utils'; | ||
|
||
/** | ||
* We need the Axelar command ID to be unique, otherwise the simulation could fail. | ||
* We don't necessarily care if the command is what would actually be used by the | ||
* Axelar network. | ||
* @param payload The Axelar GMP payload. | ||
* @returns hash of payload and current time. | ||
*/ | ||
export function genUniqueAxelarCommandId(payload: string) { | ||
return keccak256( | ||
defaultAbiCoder.encode(['bytes', 'uint256'], [payload, new Date().getTime()]), | ||
); | ||
} | ||
|
||
/** | ||
* Generates an Axelar GMP payload for a withdrawal. | ||
* Note that this is not the payload *hash*. It can be any length of bytes. | ||
*/ | ||
export function genAxelarWithdrawPayload( | ||
rootToken: string, | ||
sender: string, | ||
recipient: string, | ||
amount: string, | ||
) { | ||
return defaultAbiCoder.encode( | ||
['bytes32', 'address', 'address', 'address', 'uint256'], | ||
[WITHDRAW_SIG, rootToken, sender, recipient, amount], | ||
); | ||
} | ||
|
||
export async function createChildErc20Contract( | ||
token: string, | ||
childProvider: Provider, | ||
): Promise<ethers.Contract> { | ||
return withBridgeError<ethers.Contract>( | ||
async () => new ethers.Contract(token, CHILD_ERC20, childProvider), | ||
BridgeErrorType.PROVIDER_ERROR, | ||
); | ||
} | ||
|
||
/** | ||
* Given a child chain token address (or NATIVE), returns its corresponding root token address. | ||
* This is done by calling the `rootToken` function on the child token contract. | ||
*/ | ||
export async function getWithdrawRootToken( | ||
childToken: string, | ||
destinationChainId: string, | ||
childProvider: ethers.providers.Provider, | ||
): Promise<string> { | ||
if (childToken.toUpperCase() === NATIVE | ||
|| isWrappedIMX(childToken, destinationChainId)) { | ||
return getRootIMX(destinationChainId); | ||
} | ||
// Find root token | ||
const erc20Contract: ethers.Contract = await createChildErc20Contract(childToken, childProvider); | ||
|
||
return withBridgeError<Address>(() => erc20Contract.rootToken(), BridgeErrorType.PROVIDER_ERROR); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters