Skip to content

Commit

Permalink
Smr 2090 flow rate info (#1313)
Browse files Browse the repository at this point in the history
Co-authored-by: Pano Skylakis <[email protected]>
Co-authored-by: Mikhala <[email protected]>
Co-authored-by: Zach Couchman <[email protected]>
Co-authored-by: Zach Couchman <[email protected]>
Co-authored-by: Mikhala <[email protected]>
Co-authored-by: Sharon Sheah <[email protected]>
Co-authored-by: Ermyas Abebe <[email protected]>
Co-authored-by: Charlie McKenzie <[email protected]>
  • Loading branch information
9 people authored Dec 22, 2023
1 parent a52a5ea commit 10a79bb
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 38 deletions.
9 changes: 7 additions & 2 deletions packages/internal/bridge/bridge-sample-app/.example.env
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ STATUS_TX_HASH=0x89d9a95ccdb7d4370f86fd9a6680d141367e5c24b2d111ec1fc6c87037ecfdd
# Chain ID of the source chain where the bridge tx to check originated from
STATUS_SOURCE_CHAIN_ID=13473

# FLOW RATE ----------------------------------------------------------------
# FLOW RATE TX ----------------------------------------------------------------

# FlowRate withdraw transaction to fetch
FLOW_RATE_INDEX=0
FLOW_RATE_INDEX=0

# FLOW RATE INFO --------------------------------------------------------------

# FlowRate token to fetch the info for
FLOW_RATE_INFO_TOKEN=0x40b87d235A5B010a20A241F15797C9debf1ecd01
1 change: 1 addition & 0 deletions packages/internal/bridge/bridge-sample-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"build": "",
"deposit": "node --loader ts-node/esm ./src/deposit.ts",
"fees": "node --loader ts-node/esm ./src/fees.ts",
"flowRateInfo": "node --loader ts-node/esm ./src/flowRateInfo.ts",
"lint": "eslint ./src --ext .ts --max-warnings=0",
"mapToken": "node --loader ts-node/esm ./src/mapToken.ts",
"pending": "node --loader ts-node/esm ./src/pending.ts",
Expand Down
61 changes: 61 additions & 0 deletions packages/internal/bridge/bridge-sample-app/src/flowRateInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* eslint-disable no-console */
import 'dotenv/config';
import util from 'util';

import { ImmutableConfiguration, Environment } from '@imtbl/config';

import {
TokenBridge,
BridgeConfiguration,
FlowRateInfoRequest,
FlowRateInfoResponse,
} from '@imtbl/bridge-sdk';

// @ts-ignore
import { setupForBridge } from './lib/utils.ts';

async function getFlowRateInfo() {

const params = await setupForBridge();

if (!process.env.FLOW_RATE_INFO_TOKEN) {
throw new Error('FLOW_RATE_INFO_TOKEN not set');
}

const bridgeConfig = new BridgeConfiguration({
baseConfig: new ImmutableConfiguration({
environment: Environment.SANDBOX,
}),
bridgeInstance: params.bridgeInstance,
rootProvider: params.rootProvider,
childProvider: params.childProvider,
});

const tokenBridge = new TokenBridge(bridgeConfig);

const flowRateInfoReq: FlowRateInfoRequest = {
tokens: ['NATIVE', process.env.FLOW_RATE_INFO_TOKEN],
}

console.log('flowRateInfoReq', flowRateInfoReq)

try {
const flowRateInfoRes: FlowRateInfoResponse = await tokenBridge.getFlowRateInfo(flowRateInfoReq);
console.log('flowRateInfoRes');
console.log(util.inspect(flowRateInfoRes, {showHidden: false, depth: null, colors: true}));

} catch(err) {
console.error('flowRateInfoErr', err);
throw(err);
}

}

(async () => {
try {
await getFlowRateInfo()
console.log('Exiting successfully');
} catch(err) {
console.error('Exiting with error', err)
}
})();
19 changes: 14 additions & 5 deletions packages/internal/bridge/sdk/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,26 @@ const CONTRACTS_FOR_BRIDGE = new Map<BridgeInstance, BridgeContracts>()
.set(ETH_SEPOLIA_TO_ZKEVM_DEVNET, {
rootERC20BridgeFlowRate: '0x0',
childERC20Bridge: '0x0',
wrappedIMX: '0x0',
rootChainIMX: '0x0',
rootChainWrappedETH: '0x0',
childChainWrappedETH: '0x0',
childChainWrappedIMX: '0x0',
})
.set(ETH_SEPOLIA_TO_ZKEVM_TESTNET, {
rootERC20BridgeFlowRate: '0x0D3C59c779Fd552C27b23F723E80246c840100F5',
childERC20Bridge: '0x0D3C59c779Fd552C27b23F723E80246c840100F5',
wrappedIMX: '0x1CcCa691501174B4A623CeDA58cC8f1a76dc3439',
rootChainIMX: '0xe2629e08f4125d14e446660028bD98ee60EE69F2',
rootChainWrappedETH: '0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9',
childChainWrappedETH: '0xe9E96d1aad82562b7588F03f49aD34186f996478',
childChainWrappedIMX: '0x1CcCa691501174B4A623CeDA58cC8f1a76dc3439',
})
.set(ETH_MAINNET_TO_ZKEVM_MAINNET, {
rootERC20BridgeFlowRate: '0x0',
childERC20Bridge: '0x0',
wrappedIMX: '0x0',
rootERC20BridgeFlowRate: '0xBa5E35E26Ae59c7aea6F029B68c6460De2d13eB6',
childERC20Bridge: '0xBa5E35E26Ae59c7aea6F029B68c6460De2d13eB6',
rootChainIMX: '0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF',
rootChainWrappedETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
childChainWrappedETH: '0x52a6c53869ce09a731cd772f245b97a4401d3348',
childChainWrappedIMX: '0x3a0c2ba54d6cbd3121f01b96dfd20e99d1696c9d',
});

/**
Expand Down
154 changes: 153 additions & 1 deletion packages/internal/bridge/sdk/src/tokenBridge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,7 @@ describe('Token Bridge', () => {
},
]),
getPendingWithdrawalsLength: jest.fn().mockImplementation(async () => ethers.BigNumber.from(1)),
withdrawalDelay: jest.fn().mockImplementation(async () => ethers.BigNumber.from(60 * 60 * 24)),
};

const voidRootProvider = new ethers.providers.JsonRpcProvider('x');
Expand Down Expand Up @@ -1118,6 +1119,7 @@ describe('Token Bridge', () => {
},
]),
getPendingWithdrawalsLength: jest.fn().mockImplementation(async () => ethers.BigNumber.from(0)),
withdrawalDelay: jest.fn().mockImplementation(async () => ethers.BigNumber.from(60 * 60 * 24)),
};

jest.spyOn(ethers, 'Contract').mockReturnValue(mockERC20ContractFlowRateNotFound as any);
Expand Down Expand Up @@ -1154,6 +1156,7 @@ describe('Token Bridge', () => {
timestamp,
},
]),
withdrawalDelay: jest.fn().mockImplementation(async () => ethers.BigNumber.from(60 * 60 * 24)),
};

jest.spyOn(ethers, 'Contract').mockReturnValue(mockERC20ContractFlowRateNotReady as any);
Expand Down Expand Up @@ -1194,6 +1197,7 @@ describe('Token Bridge', () => {
},
]),
getPendingWithdrawalsLength: jest.fn().mockImplementation(async () => ethers.BigNumber.from(1)),
withdrawalDelay: jest.fn().mockImplementation(async () => ethers.BigNumber.from(60 * 60 * 24)),
};

const voidRootProvider = new ethers.providers.JsonRpcProvider('x');
Expand Down Expand Up @@ -1271,6 +1275,7 @@ describe('Token Bridge', () => {
},
]),
getPendingWithdrawalsLength: jest.fn().mockImplementation(async () => ethers.BigNumber.from(3)),
withdrawalDelay: jest.fn().mockImplementation(async () => ethers.BigNumber.from(60 * 60 * 24)),

};

Expand Down Expand Up @@ -1320,7 +1325,7 @@ describe('Token Bridge', () => {
},
]),
getPendingWithdrawalsLength: jest.fn().mockImplementation(async () => ethers.BigNumber.from(0)),

withdrawalDelay: jest.fn().mockImplementation(async () => ethers.BigNumber.from(60 * 60 * 24)),
};

jest.spyOn(ethers, 'Contract').mockReturnValue(mockERC20ContractFlowRateNone as any);
Expand All @@ -1332,6 +1337,153 @@ describe('Token Bridge', () => {
});
});

describe('getFlowRateInfo', () => {
let tokenBridge: TokenBridge;

const token = '0x40b87d235A5B010a20A241F15797C9debf1ecd01';
const capacity = ethers.BigNumber.from(500000);
const depth = ethers.BigNumber.from(300000);
const refillTime = ethers.BigNumber.from(5000);
const refillRate = ethers.BigNumber.from(100000);
const withdrawalDelay = ethers.BigNumber.from(60 * 60 * 24);

const mockERC20ContractFlowRate = {
withdrawalQueueActivated: jest.fn().mockImplementation(async () => false),
withdrawalDelay: jest.fn().mockImplementation(async () => withdrawalDelay),
flowRateBuckets: jest.fn().mockImplementation(async () => ({
capacity,
depth,
refillTime,
refillRate,
})),
};

const voidRootProvider = new ethers.providers.JsonRpcProvider('x');
const voidChildProvider = new ethers.providers.JsonRpcProvider('x');

const bridgeConfig = new BridgeConfiguration({
baseConfig: new ImmutableConfiguration({
environment: Environment.SANDBOX,
}),
bridgeInstance: ETH_SEPOLIA_TO_ZKEVM_DEVNET,
rootProvider: voidRootProvider,
childProvider: voidChildProvider,
});

beforeEach(() => {
tokenBridge = new TokenBridge(bridgeConfig);
});

afterEach(() => {
jest.clearAllMocks();
});
it('returns the flow rate info for a specific token', async () => {
expect.assertions(7);
const req = {
tokens: [token],
};

jest.spyOn(ethers, 'Contract').mockReturnValue(mockERC20ContractFlowRate as any);

const result = await tokenBridge.getFlowRateInfo(req);

expect(result).toBeDefined();
expect(result.withdrawalQueueActivated).toBe(false);
expect(result.withdrawalDelay).toBe(withdrawalDelay.toNumber());
expect(result.tokens[token].capacity).toStrictEqual(capacity);
expect(result.tokens[token].depth).toStrictEqual(depth);
expect(result.tokens[token].refillTime).toBe(refillTime.toNumber());
expect(result.tokens[token].refillRate).toStrictEqual(refillRate);
});

it('returns the flow rate info for the NATIVE token', async () => {
expect.assertions(7);
const req = {
tokens: ['NATIVE'],
};

jest.spyOn(ethers, 'Contract').mockReturnValue(mockERC20ContractFlowRate as any);

const result = await tokenBridge.getFlowRateInfo(req);

expect(result).toBeDefined();
expect(result.withdrawalQueueActivated).toBe(false);
expect(result.withdrawalDelay).toBe(withdrawalDelay.toNumber());
expect(result.tokens['NATIVE'].capacity).toStrictEqual(capacity);
expect(result.tokens['NATIVE'].depth).toStrictEqual(depth);
expect(result.tokens['NATIVE'].refillTime).toBe(refillTime.toNumber());
expect(result.tokens['NATIVE'].refillRate).toStrictEqual(refillRate);
});

it('returns the flow rate info for the multiple tokens', async () => {
expect.assertions(15);
const otherToken = '0x12345';
const req = {
tokens: ['NATIVE', token, otherToken],
};

const mockERC20ContractFlowRateMultiToken = {
withdrawalQueueActivated: jest.fn().mockImplementation(async () => false),
withdrawalDelay: jest.fn().mockImplementation(async () => withdrawalDelay),
flowRateBuckets: jest.fn().mockImplementation(async () => ({
capacity,
depth,
refillTime,
refillRate,
})),
};

jest.spyOn(ethers, 'Contract').mockReturnValue(mockERC20ContractFlowRateMultiToken as any);

const result = await tokenBridge.getFlowRateInfo(req);

expect(result).toBeDefined();
expect(result.withdrawalQueueActivated).toBe(false);
expect(result.withdrawalDelay).toBe(withdrawalDelay.toNumber());
expect(result.tokens['NATIVE'].capacity).toStrictEqual(capacity);
expect(result.tokens['NATIVE'].depth).toStrictEqual(depth);
expect(result.tokens['NATIVE'].refillTime).toBe(refillTime.toNumber());
expect(result.tokens['NATIVE'].refillRate).toStrictEqual(refillRate);
expect(result.tokens[token].capacity).toStrictEqual(capacity);
expect(result.tokens[token].depth).toStrictEqual(depth);
expect(result.tokens[token].refillTime).toBe(refillTime.toNumber());
expect(result.tokens[token].refillRate).toStrictEqual(refillRate);
expect(result.tokens[otherToken].capacity).toStrictEqual(capacity);
expect(result.tokens[otherToken].depth).toStrictEqual(depth);
expect(result.tokens[otherToken].refillTime).toBe(refillTime.toNumber());
expect(result.tokens[otherToken].refillRate).toStrictEqual(refillRate);
});
it('returns the withdrawalQueueActivated as true ', async () => {
expect.assertions(7);
const req = {
tokens: ['NATIVE'],
};

const mockERC20ContractFlowRateMultiToken = {
withdrawalQueueActivated: jest.fn().mockImplementation(async () => true),
withdrawalDelay: jest.fn().mockImplementation(async () => withdrawalDelay),
flowRateBuckets: jest.fn().mockImplementation(async () => ({
capacity,
depth,
refillTime,
refillRate,
})),
};

jest.spyOn(ethers, 'Contract').mockReturnValue(mockERC20ContractFlowRateMultiToken as any);

const result = await tokenBridge.getFlowRateInfo(req);

expect(result).toBeDefined();
expect(result.withdrawalQueueActivated).toBe(true);
expect(result.withdrawalDelay).toBe(withdrawalDelay.toNumber());
expect(result.tokens['NATIVE'].capacity).toStrictEqual(capacity);
expect(result.tokens['NATIVE'].depth).toStrictEqual(depth);
expect(result.tokens['NATIVE'].refillTime).toBe(refillTime.toNumber());
expect(result.tokens['NATIVE'].refillRate).toStrictEqual(refillRate);
});
});

describe('calculateBridgeFee', () => {
let tokenBridge: TokenBridge;
beforeEach(() => {
Expand Down
Loading

0 comments on commit 10a79bb

Please sign in to comment.