Skip to content

Commit

Permalink
swap and stake router e2e (#55)
Browse files Browse the repository at this point in the history
* swap and route e2e

* fix

* bump test version
  • Loading branch information
shunjizhan authored Jun 13, 2024
1 parent db72afa commit 3190596
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 6 deletions.
6 changes: 3 additions & 3 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const TEST_ACCOUNTS = {
path: 'm/44\'/60\'/0\'/0',
};

const PROD_ACCOUNTS = process.env.KEY ? [process.env.KEY] : [];
const PROD_ACCOUNTS = process.env.KEY ? process.env.KEY.split(',') : [];

const config: HardhatUserConfig = {
solidity: '0.8.18',
Expand All @@ -26,8 +26,8 @@ const config: HardhatUserConfig = {
chainId: 596,
},
acalaFork: {
url: 'http://127.0.0.1:8545',
accounts: TEST_ACCOUNTS,
url: 'https://crosschain-dev.polkawallet.io/forkAcala/',
accounts: PROD_ACCOUNTS,
chainId: 787,
},
karura: {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@acala-network/asset-router",
"version": "1.0.17",
"version": "1.0.18-1",
"main": "dist/index.js",
"repository": "[email protected]:AcalaNetwork/asset-router.git",
"author": "Acala Developers <[email protected]>",
Expand Down
14 changes: 13 additions & 1 deletion scripts/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const enum CHAIN {
BSC = 'BSC',
ARB = 'ARB',
POLYGON = 'POLYGON',
SOLANA = 'SOLANA',
}

export const enum TOKEN {
Expand All @@ -35,6 +36,7 @@ export const enum TOKEN {
TDOT = 'tdot',
LCDOT = 'lcdot',
KSM = 'ksm',
JITOSOL = 'jitosol',
}

export type CHAIN_NAME = keyof typeof CHAIN;
Expand All @@ -51,11 +53,12 @@ export const ADDRESSES = {
[CHAIN.ACALA_TESTNET]: {
tokenBridgeAddr: CONTRACTS.TESTNET.acala.token_bridge,
factoryAddr: '',
feeAddr: '0xfFAD744806522F9F9f3bef1F09Ec5421Bfc0874e', // acala fork
feeAddr: '0x346a989D3B55a82b3CD8a5ed804E3776Af90925a', // acala fork
usdcAddr: '0x7E0CCD4209Ef7039901512fF9f6a01d0de0691e2',
homaFactoryAddr: '0x2ed9aa0e30D52958E21Db37FfBDC3F0B0fD4b973', // acala fork
accountHelperAddr: '0x0252340cC347718f9169d329CEFf8B15A92badf8', // acala fork
euphratesFactoryAddr: '0x2AeFc65B6E1660d2bA2796f8698120A2acB95634', // acala fork
swapAndStakeFactoryAddr: '0x97B15411D65e83F0bDA8D1db628CCC5D003B754d', // acala fork
},
[CHAIN.KARURA]: {
tokenBridgeAddr: CONTRACTS.MAINNET.karura.token_bridge,
Expand All @@ -73,6 +76,7 @@ export const ADDRESSES = {
homaFactoryAddr: '0x2ed9aa0e30D52958E21Db37FfBDC3F0B0fD4b973',
accountHelperAddr: '0x0252340cC347718f9169d329CEFf8B15A92badf8',
euphratesFactoryAddr: '0x2AeFc65B6E1660d2bA2796f8698120A2acB95634',
swapAndStakeFactoryAddr: '',
},
} as const;

Expand Down Expand Up @@ -261,6 +265,14 @@ export const ROUTER_TOKEN_INFO = {
decimals: 12,
fee: 0.001,
},
[TOKEN.JITOSOL]: {
originChain: CHAIN.SOLANA,
originAddr: '',
karuraAddr: '',
acalaAddr: '0xa7fb00459f5896c3bd4df97870b44e868ae663d7',
decimals: 9,
fee: 0.0003,
},
} as const;

export const CHAIN_NAME_TO_WORMHOLE_CHAIN_ID = {
Expand Down
2 changes: 1 addition & 1 deletion scripts/deploy-fee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FeeStruct } from '../typechain-types/src/FeeRegistry';
import { ROUTER_TOKEN_INFO } from './consts';

async function main() {
const isAcala = network.name === 'acala';
const isAcala = network.name.toLowerCase().includes('acala');
const feeConfig = Object.entries(ROUTER_TOKEN_INFO)
.filter(([, info]) => isAcala ? !!info.acalaAddr : !!info.karuraAddr)
.map(([, info]) => ({
Expand Down
154 changes: 154 additions & 0 deletions test/swapAndStakeRouter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { ACA } from '@acala-network/contracts/utils/AcalaTokens';
import { BigNumber, constants } from 'ethers';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { ethers } from 'hardhat';
import { expect } from 'chai';
import { formatUnits, parseEther, parseUnits } from 'ethers/lib/utils';

import { ADDRESSES } from '../scripts/consts';
import { FeeRegistry, MockToken, SwapAndStakeEuphratesFactory } from '../typechain-types';
import { ONE_ACA, almostEq, toHuman } from '../scripts/utils';

const { swapAndStakeFactoryAddr, feeAddr } = ADDRESSES.ACALA_TESTNET;

describe('Stake and Swap Router', () => {
// fixed
let jitosol: MockToken;
let aca: MockToken;
let fee: FeeRegistry;
let factory: SwapAndStakeEuphratesFactory;
let decimals: number;
let routingFee: BigNumber;
let stakeAndSupplyAmount: BigNumber;
let user: SignerWithAddress;
let relayer: SignerWithAddress;

// dynamic
let routerAddr: string;
let bal0: Awaited<ReturnType<typeof fetchTokenBalances>>;
let bal1: Awaited<ReturnType<typeof fetchTokenBalances>>;

const fetchTokenBalances = async () => {
const [
userBal,
relayerBal,
userBalJitoSol,
relayerBalJitoSol,
routerBalJitoSol,
] = await Promise.all([
user.getBalance(),
relayer.getBalance(),
jitosol.balanceOf(user.address),
jitosol.balanceOf(relayer.address),
jitosol.balanceOf(routerAddr),
]);

console.log({
userBal: toHuman(userBal, 18),
relayerBal: toHuman(relayerBal, 18),
userBalJitoSol: toHuman(userBalJitoSol, decimals),
relayerBalJitoSol: toHuman(relayerBalJitoSol, decimals),
routerBalJitoSol: toHuman(routerBalJitoSol, decimals),
});

return {
userBal,
relayerBal,
userBalJitoSol,
relayerBalJitoSol,
routerBalJitoSol,
};
};

before('setup', async () => {
([user, relayer] = await ethers.getSigners());

const Token = await ethers.getContractFactory('MockToken');
const Fee = await ethers.getContractFactory('FeeRegistry');
const Factory = await ethers.getContractFactory('SwapAndStakeEuphratesFactory');

jitosol = Token.attach('0xa7fb00459f5896c3bd4df97870b44e868ae663d7');
aca = Token.attach(ACA);
fee = Fee.attach(feeAddr);
factory = Factory.attach(swapAndStakeFactoryAddr).connect(relayer);
decimals = await jitosol.decimals();
routingFee = await fee.getFee(jitosol.address);
stakeAndSupplyAmount = parseUnits('1', decimals);

console.log(`jitosol address: ${jitosol.address}`);
console.log(`feeRegistry address: ${fee.address}`);
console.log(`factory address: ${factory.address}`);
console.log(`user address: ${user.address}`);
console.log(`relayer address: ${relayer.address}`);
console.log(`token decimals: ${decimals}`);
console.log(`router fee: ${Number(formatUnits(routingFee, decimals))}`);
});

describe('swap and route', async () => {
it('works', async () => {
const supplyAmount = parseUnits('0.1', decimals);
const targetAmount = parseUnits('2', 12);
const targetAmountNative = parseEther('2');
const insts = {
recipient: user.address,
supplyAmount,
maker: relayer.address,
targetToken: ACA,
poolId: 7,
euphrates: '0x7Fe92EC600F15cD25253b421bc151c51b0276b7D',
};

// console.log('approving ...');
// const approveTx = await aca.connect(relayer).approve(swapAndStakeFactoryAddr, constants.MaxUint256);
// await approveTx.wait();
// console.log('approved');

routerAddr = await factory.callStatic.deploySwapAndStakeEuphratesRouter(fee.address, insts, targetAmount);

console.log({ predictedRouterAddr: routerAddr });

console.log('\n-------------------- init state --------------------');
bal0 = await fetchTokenBalances();
expect(bal0.userBalJitoSol).to.gte(stakeAndSupplyAmount);

// router shouldn't exist
let routerCode = await relayer.provider!.getCode(routerAddr);
expect(routerCode).to.eq('0x');

await (await jitosol.connect(user).transfer(
routerAddr,
stakeAndSupplyAmount,
)).wait();

console.log('\n-------------------- after user deposited to router --------------------');
await fetchTokenBalances();


const deployAndRoute = await factory.deploySwapAndStakeEuphratesRouterAndRoute(
fee.address,
insts,
jitosol.address,
targetAmount,
);
await deployAndRoute.wait();

console.log('\n-------------------- after router routed and staked --------------------');
bal1 = await fetchTokenBalances();

// router should have no remaining balance
expect(bal1.routerBalJitoSol).to.eq(0);

// user should receive LDOT and swapped target token
expect(bal0.userBalJitoSol.sub(bal1.userBalJitoSol)).to.eq(stakeAndSupplyAmount);
almostEq(bal1.userBal.sub(bal0.userBal), targetAmountNative);

// relayer should receive fee
expect(bal1.relayerBalJitoSol.sub(bal0.relayerBalJitoSol)).to.eq(routingFee.add(supplyAmount));

// router should be destroyed
routerCode = await relayer.provider!.getCode(routerAddr);
expect(routerCode).to.eq('0x');
});
});

});

0 comments on commit 3190596

Please sign in to comment.