Skip to content

Commit

Permalink
Merge branch 'main' into feat/qualify-by-cfe-version
Browse files Browse the repository at this point in the history
  • Loading branch information
dandanlen authored Sep 14, 2023
2 parents 90b7399 + c00a008 commit cfb2385
Show file tree
Hide file tree
Showing 42 changed files with 766 additions and 381 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions api/bin/chainflip-cli/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ mod tests {
.unwrap();

assert_eq!(settings.state_chain.ws_endpoint, "ws://localhost:9944");
assert_eq!(settings.eth.nodes.primary.ws_node_endpoint, "ws://localhost:8545");
assert_eq!(settings.eth.nodes.primary.ws_node_endpoint.as_ref(), "ws://localhost:8545");
}

#[test]
Expand Down Expand Up @@ -294,21 +294,21 @@ mod tests {
);
assert_eq!(
opts.eth_opts.eth_ws_node_endpoint.unwrap(),
settings.eth.nodes.primary.ws_node_endpoint
settings.eth.nodes.primary.ws_node_endpoint.as_ref()
);
assert_eq!(
opts.eth_opts.eth_http_node_endpoint.unwrap(),
settings.eth.nodes.primary.http_node_endpoint
settings.eth.nodes.primary.http_node_endpoint.as_ref()
);

let eth_backup_node = settings.eth.nodes.backup.unwrap();
assert_eq!(
opts.eth_opts.eth_backup_ws_node_endpoint.unwrap(),
eth_backup_node.ws_node_endpoint
eth_backup_node.ws_node_endpoint.as_ref()
);
assert_eq!(
opts.eth_opts.eth_backup_http_node_endpoint.unwrap(),
eth_backup_node.http_node_endpoint
eth_backup_node.http_node_endpoint.as_ref()
);

assert_eq!(opts.eth_opts.eth_private_key_file.unwrap(), settings.eth.private_key_file);
Expand Down
4 changes: 1 addition & 3 deletions bouncer/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,4 @@ if [[ $LOCALNET == false ]]; then
else
echo "🚀 Running tests that require localnet"
./tests/swap_after_temp_disconnecting_chains.ts
fi

./tests/multiple_members_governance.ts
fi
8 changes: 4 additions & 4 deletions bouncer/shared/fund_flip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { observeEvent, getChainflipApi, amountToFineAmount } from '../shared/utils';
import { approveErc20 } from './approve_erc20';

export async function fundFlip(address: string, flipAmount: string) {
export async function fundFlip(scAddress: string, flipAmount: string) {
const chainflip = await getChainflipApi();
await cryptoWaitReady();

Expand Down Expand Up @@ -44,10 +44,10 @@ export async function fundFlip(address: string, flipAmount: string) {
nonce: BigInt(await getNextEthNonce()),
} as const;

console.log('Funding ' + flipAmount + ' FLIP to ' + address);
let pubkey = address;
console.log('Funding ' + flipAmount + ' FLIP to ' + scAddress);
let pubkey = scAddress;
try {
pubkey = decodeFlipAddressForContract(address);
pubkey = decodeFlipAddressForContract(scAddress);
} catch {
// ignore error
}
Expand Down
29 changes: 29 additions & 0 deletions bouncer/shared/fund_redeem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { HexString } from '@polkadot/util/types';
import { newAddress, observeBalanceIncrease } from '../shared/utils';
import { getBalance } from '../shared/get_balance';
import { fundFlip } from '../shared/fund_flip';
import { redeemFlip } from '../shared/redeem_flip';
import { newStatechainAddress } from '../shared/new_statechain_address';

// Uses the seed to generate a new SC address and ETH address.
// It then funds the SC address with FLIP, and redeems the FLIP to the ETH address
// checking that the balance has increased.
export async function testFundRedeem(seed: string) {
const redeemSCAddress = await newStatechainAddress(seed);
const redeemEthAddress = await newAddress('ETH', seed);
console.log(`FLIP Redeem address: ${redeemSCAddress}`);
console.log(`ETH Redeem address: ${redeemEthAddress}`);
const initBalance = await getBalance('FLIP', redeemEthAddress);
console.log(`Initial ERC20-FLIP balance: ${initBalance.toString()}`);
const amount = 1000;
// We fund to a specific SC address.
await fundFlip(redeemSCAddress, amount.toString());

// The ERC20 FLIP is sent back to an ETH address, and the registered claim can only be executed by that address.
await redeemFlip(seed, redeemEthAddress as HexString, (amount / 2).toString());
console.log('Observed RedemptionSettled event');
const newBalance = await observeBalanceIncrease('FLIP', redeemEthAddress, initBalance);
console.log(`Redemption success! New balance: ${newBalance.toString()}`);
console.log('=== Fund/Redeem Test Success ===');
process.exit(0);
}
72 changes: 72 additions & 0 deletions bouncer/shared/multiple_members_governance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Keyring from '@polkadot/keyring';
import { cryptoWaitReady } from '@polkadot/util-crypto';
import { assert } from '@polkadot/util';
import { getChainflipApi, observeEvent } from '../shared/utils';
import { snowWhite, submitGovernanceExtrinsic } from '../shared/cf_governance';

async function getGovernanceMembers(): Promise<string[]> {
const chainflip = await getChainflipApi();

const res = (await chainflip.query.governance.members()).toJSON();
return res as string[];
}

async function setGovernanceMembers(members: string[]) {
const chainflip = await getChainflipApi();

await submitGovernanceExtrinsic(chainflip.tx.governance.newMembershipSet(members));
}

await cryptoWaitReady();
const keyring = new Keyring({ type: 'sr25519' });
keyring.setSS58Format(2112);

const alice = keyring.createFromUri('//Alice');

async function addAliceToGovernance() {
const initMembers = await getGovernanceMembers();
assert(initMembers.length === 1, 'Governance should only have 1 member');

const newMembers = [...initMembers, alice.address];

await setGovernanceMembers(newMembers);

const chainflip = await getChainflipApi();
await observeEvent('governance:Executed', chainflip);

assert((await getGovernanceMembers()).length === 2, 'Governance should now have 2 members');

console.log('Added Alice to governance!');
}

async function submitWithMultipleGovernanceMembers() {
const chainflip = await getChainflipApi();

// Killing 2 birds with 1 stone: testing governance execution with multiple
// members *and* restoring governance to its original state
await submitGovernanceExtrinsic(chainflip.tx.governance.newMembershipSet([snowWhite.address]));

const proposalId = Number((await observeEvent('governance:Proposed', chainflip)).data);

// Note that with two members, we need to approve with the other account:
await chainflip.tx.governance.approve(proposalId).signAndSend(alice, { nonce: -1 });

const executedProposalId = Number((await observeEvent('governance:Executed', chainflip)).data);
assert(proposalId === executedProposalId, 'Proposal Ids should match');

assert(
(await getGovernanceMembers()).length === 1,
'Governance should have been restored to 1 member',
);

console.log('Removed Alice from governance!');
}

export async function testMultipleMembersGovernance() {
console.log('=== Testing multiple members governance ===');
await addAliceToGovernance();
await submitWithMultipleGovernanceMembers();

console.log('=== Multiple members governance test complete ===');
process.exit(0);
}
30 changes: 12 additions & 18 deletions bouncer/shared/provide_liquidity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { send } from '../shared/send';
export async function provideLiquidity(ccy: Asset, amount: number) {
const chainflip = await getChainflipApi();
await cryptoWaitReady();
const chain = assetToChain(ccy);

const keyring = new Keyring({ type: 'sr25519' });
const lpUri = process.env.LP_URI || '//LP_1';
Expand All @@ -29,39 +30,31 @@ export async function provideLiquidity(ccy: Asset, amount: number) {
)
).toJSON() === null
) {
let refundAddress = await newAddress(assetToChain(ccy).toUpperCase() as Asset, 'LP_1');
let refundAddress = await newAddress(chain.toUpperCase() as Asset, 'LP_1');
refundAddress = ccy === 'DOT' ? decodeDotAddressForContract(refundAddress) : refundAddress;

console.log('Registering Liquidity Refund Address for ' + ccy + ': ' + refundAddress);
await lpMutex.runExclusive(async () => {
await chainflip.tx.liquidityProvider
.registerLiquidityRefundAddress({ [assetToChain(ccy)]: refundAddress })
.registerLiquidityRefundAddress({ [chain]: refundAddress })
.signAndSend(lp, { nonce: -1 }, handleSubstrateError(chainflip));
});
}

let eventHandle = observeEvent(
'liquidityProvider:LiquidityDepositAddressReady',
chainflip,
(event) => event.data.asset.toUpperCase() === ccy,
);

console.log('Requesting ' + ccy + ' deposit address');
let eventHandle =
assetToChain(ccy) === 'Eth'
? observeEvent(
'ethereumIngressEgress:StartWitnessing',
chainflip,
(event) => event.data.sourceAsset.toUpperCase() === ccy,
)
: observeEvent(
'liquidityProvider:LiquidityDepositAddressReady',
chainflip,
(event) => event.data.depositAddress[assetToChain(ccy)] !== undefined,
);
await lpMutex.runExclusive(async () => {
await chainflip.tx.liquidityProvider
.requestLiquidityDepositAddress(ccy.toLowerCase())
.signAndSend(lp, { nonce: -1 }, handleSubstrateError(chainflip));
});
const ingressAddress =
assetToChain(ccy) === 'Eth'
? (await eventHandle).data.depositAddress
: (await eventHandle).data.depositAddress[assetToChain(ccy)];

const ingressAddress = (await eventHandle).data.depositAddress[chain];

console.log('Received ' + ccy + ' address: ' + ingressAddress);
console.log('Sending ' + amount + ' ' + ccy + ' to ' + ingressAddress);
Expand All @@ -71,5 +64,6 @@ export async function provideLiquidity(ccy: Asset, amount: number) {
(event) => event.data.asset.toUpperCase() === ccy,
);
send(ccy, ingressAddress, String(amount));

await eventHandle;
}
3 changes: 2 additions & 1 deletion bouncer/shared/redeem_flip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export async function redeemFlip(flipSeed: string, ethAddress: HexString, flipAm
(event) => event.data.accountId === flipWallet.address,
);
await chainflip.tx.funding
.redeem({ Exact: flipperinoAmount }, ethAddress)
.redeem({ Exact: flipperinoAmount }, ethAddress, null)
.signAndSend(flipWallet, { nonce: -1 }, handleSubstrateError(chainflip));
await redemptionRequestHandle;

Expand All @@ -52,6 +52,7 @@ export async function redeemFlip(flipSeed: string, ethAddress: HexString, flipAm
ethAddress,
'*',
'*',
'*',
]);

const delay = await getRedemptionDelay(networkOptions);
Expand Down
10 changes: 9 additions & 1 deletion bouncer/tests/all_concurrent_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ import { testLpDepositExpiry } from '../shared/lp_deposit_expiry';
import { testAllSwaps } from '../shared/swapping';
import { testEthereumDeposits } from '../shared/ethereum_deposits';
import { runWithTimeout, observeBadEvents } from '../shared/utils';
import { testFundRedeem } from '../shared/fund_redeem';
import { testMultipleMembersGovernance } from '../shared/multiple_members_governance';

async function runAllConcurrentTests() {
let stopObserving = false;
const observingBadEvents = observeBadEvents(':BroadcastAborted', () => stopObserving);

await Promise.all([testAllSwaps(), testLpDepositExpiry(), testEthereumDeposits()]);
await Promise.all([
testAllSwaps(),
testLpDepositExpiry(),
testEthereumDeposits(),
testFundRedeem('redeem'),
testMultipleMembersGovernance(),
]);

// Gracefully exit the broadcast abort observer
stopObserving = true;
Expand Down
27 changes: 3 additions & 24 deletions bouncer/tests/fund_redeem.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,8 @@
#!/usr/bin/env -S pnpm tsx
import { HexString } from '@polkadot/util/types';
import { newAddress, observeBalanceIncrease, runWithTimeout } from '../shared/utils';
import { getBalance } from '../shared/get_balance';
import { fundFlip } from '../shared/fund_flip';
import { redeemFlip } from '../shared/redeem_flip';
import { newStatechainAddress } from '../shared/new_statechain_address';
import { testFundRedeem } from '../shared/fund_redeem';
import { runWithTimeout } from '../shared/utils';

export async function fundRedeemTest() {
const seed = 'redeem';
const redeemFlipAddress = await newStatechainAddress(seed);
const redeemEthAddress = await newAddress('ETH', seed);
console.log(`FLIP Redeem address: ${redeemFlipAddress}`);
console.log(`ETH Redeem address: ${redeemEthAddress}`);
const initBalance = await getBalance('FLIP', redeemEthAddress);
console.log(`Initial ERC20-FLIP balance: ${initBalance.toString()}`);
const amount = 1000;
await fundFlip(redeemFlipAddress, amount.toString());
await redeemFlip(seed, redeemEthAddress as HexString, (amount / 2).toString());
console.log('Observed RedemptionSettled event');
const newBalance = await observeBalanceIncrease('FLIP', redeemEthAddress, initBalance);
console.log(`Redemption success! New balance: ${newBalance.toString()}`);
process.exit(0);
}

runWithTimeout(fundRedeemTest(), 600000).catch((error) => {
runWithTimeout(testFundRedeem('redeem'), 600000).catch((error) => {
console.error(error);
process.exit(-1);
});
Loading

0 comments on commit cfb2385

Please sign in to comment.