181 lines
7.1 KiB
TypeScript
181 lines
7.1 KiB
TypeScript
import {
|
|
blockchainTests,
|
|
constants,
|
|
expect,
|
|
filterLogsToArguments,
|
|
getRandomInteger,
|
|
hexRandom,
|
|
Numberish,
|
|
randomAddress,
|
|
TransactionHelper,
|
|
} from '@0x/contracts-test-utils';
|
|
import { BigNumber } from '@0x/utils';
|
|
import { DecodedLogs } from 'ethereum-types';
|
|
import * as _ from 'lodash';
|
|
|
|
import {
|
|
artifacts,
|
|
TestEth2DaiBridgeContract,
|
|
TestEth2DaiBridgeEvents,
|
|
TestEth2DaiBridgeSellAllAmountEventArgs,
|
|
TestEth2DaiBridgeTokenTransferEventArgs,
|
|
} from '../src';
|
|
|
|
blockchainTests.resets.only('Eth2DaiBridge unit tests', env => {
|
|
const txHelper = new TransactionHelper(env.web3Wrapper, artifacts);
|
|
let testContract: TestEth2DaiBridgeContract;
|
|
let daiTokenAddress: string;
|
|
let wethTokenAddress: string;
|
|
|
|
before(async () => {
|
|
testContract = await TestEth2DaiBridgeContract.deployFrom0xArtifactAsync(
|
|
artifacts.TestEth2DaiBridge,
|
|
env.provider,
|
|
env.txDefaults,
|
|
artifacts,
|
|
);
|
|
[daiTokenAddress, wethTokenAddress] = await Promise.all([
|
|
testContract.daiToken.callAsync(),
|
|
testContract.wethToken.callAsync(),
|
|
]);
|
|
});
|
|
|
|
describe('deployment', () => {
|
|
it('sets Eth2Dai allowances to maximum', async () => {
|
|
const [wethAllowance, daiAllowance] = await testContract.getEth2DaiTokenAllowances.callAsync();
|
|
expect(wethAllowance).to.bignumber.eq(constants.MAX_UINT256);
|
|
expect(daiAllowance).to.bignumber.eq(constants.MAX_UINT256);
|
|
});
|
|
});
|
|
|
|
describe('isValidSignature()', () => {
|
|
it('returns success bytes', async () => {
|
|
const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
|
|
const result = await testContract.isValidSignature.callAsync(hexRandom(), hexRandom(_.random(0, 32)));
|
|
expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
|
|
});
|
|
});
|
|
|
|
describe('transfer()', () => {
|
|
interface TransferOpts {
|
|
toTokenAddress: string;
|
|
toAddress: string;
|
|
amount: Numberish;
|
|
fromTokenBalance: Numberish;
|
|
revertReason: string;
|
|
fillAmount: Numberish;
|
|
}
|
|
|
|
function createTransferOpts(opts?: Partial<TransferOpts>): TransferOpts {
|
|
return {
|
|
toTokenAddress: _.sampleSize([wethTokenAddress, daiTokenAddress], 1)[0],
|
|
toAddress: randomAddress(),
|
|
amount: getRandomInteger(1, 100e18),
|
|
revertReason: '',
|
|
fillAmount: getRandomInteger(1, 100e18),
|
|
fromTokenBalance: getRandomInteger(1, 100e18),
|
|
...opts,
|
|
};
|
|
}
|
|
|
|
async function transferAsync(opts?: Partial<TransferOpts>): Promise<[string, DecodedLogs]> {
|
|
const _opts = createTransferOpts(opts);
|
|
// Set the fill behavior.
|
|
await testContract.setFillBehavior.awaitTransactionSuccessAsync(
|
|
_opts.revertReason,
|
|
new BigNumber(_opts.fillAmount),
|
|
);
|
|
// Set the token balance for the token we're converting from.
|
|
await testContract.setTokenBalances.awaitTransactionSuccessAsync(
|
|
_opts.toTokenAddress === daiTokenAddress
|
|
? new BigNumber(_opts.fromTokenBalance)
|
|
: constants.ZERO_AMOUNT,
|
|
_opts.toTokenAddress === wethTokenAddress
|
|
? new BigNumber(_opts.fromTokenBalance)
|
|
: constants.ZERO_AMOUNT,
|
|
);
|
|
// Call transfer().
|
|
const [result, { logs }] = await txHelper.getResultAndReceiptAsync(
|
|
testContract.transfer,
|
|
'0x',
|
|
_opts.toTokenAddress,
|
|
randomAddress(),
|
|
_opts.toAddress,
|
|
new BigNumber(_opts.amount),
|
|
);
|
|
return [result, (logs as any) as DecodedLogs];
|
|
}
|
|
|
|
function getOppositeToken(tokenAddress: string): string {
|
|
if (tokenAddress === daiTokenAddress) {
|
|
return wethTokenAddress;
|
|
}
|
|
return daiTokenAddress;
|
|
}
|
|
|
|
it('returns magic bytes on success', async () => {
|
|
const BRIDGE_SUCCESS_RETURN_DATA = '0xb5d40d78';
|
|
const [result] = await transferAsync();
|
|
expect(result).to.eq(BRIDGE_SUCCESS_RETURN_DATA);
|
|
});
|
|
|
|
it('calls `Eth2Dai.sellAllAmount()`', async () => {
|
|
const opts = createTransferOpts();
|
|
const [, logs] = await transferAsync(opts);
|
|
const transfers = filterLogsToArguments<TestEth2DaiBridgeSellAllAmountEventArgs>(
|
|
logs,
|
|
TestEth2DaiBridgeEvents.SellAllAmount,
|
|
);
|
|
expect(transfers.length).to.eq(1);
|
|
expect(transfers[0].sellToken).to.eq(getOppositeToken(opts.toTokenAddress));
|
|
expect(transfers[0].buyToken).to.eq(opts.toTokenAddress);
|
|
expect(transfers[0].sellTokenAmount).to.bignumber.eq(opts.fromTokenBalance);
|
|
expect(transfers[0].minimumFillAmount).to.bignumber.eq(opts.amount);
|
|
});
|
|
|
|
it('can swap DAI for WETH', async () => {
|
|
const opts = createTransferOpts({ toTokenAddress: wethTokenAddress });
|
|
const [, logs] = await transferAsync(opts);
|
|
const transfers = filterLogsToArguments<TestEth2DaiBridgeSellAllAmountEventArgs>(
|
|
logs,
|
|
TestEth2DaiBridgeEvents.SellAllAmount,
|
|
);
|
|
expect(transfers.length).to.eq(1);
|
|
expect(transfers[0].sellToken).to.eq(daiTokenAddress);
|
|
expect(transfers[0].buyToken).to.eq(wethTokenAddress);
|
|
});
|
|
|
|
it('can swap WETH for DAI', async () => {
|
|
const opts = createTransferOpts({ toTokenAddress: daiTokenAddress });
|
|
const [, logs] = await transferAsync(opts);
|
|
const transfers = filterLogsToArguments<TestEth2DaiBridgeSellAllAmountEventArgs>(
|
|
logs,
|
|
TestEth2DaiBridgeEvents.SellAllAmount,
|
|
);
|
|
expect(transfers.length).to.eq(1);
|
|
expect(transfers[0].sellToken).to.eq(wethTokenAddress);
|
|
expect(transfers[0].buyToken).to.eq(daiTokenAddress);
|
|
});
|
|
|
|
it('transfers filled amount to `to`', async () => {
|
|
const opts = createTransferOpts();
|
|
const [, logs] = await transferAsync(opts);
|
|
const transfers = filterLogsToArguments<TestEth2DaiBridgeTokenTransferEventArgs>(
|
|
logs,
|
|
TestEth2DaiBridgeEvents.TokenTransfer,
|
|
);
|
|
expect(transfers.length).to.eq(1);
|
|
expect(transfers[0].token).to.eq(opts.toTokenAddress);
|
|
expect(transfers[0].from).to.eq(testContract.address);
|
|
expect(transfers[0].to).to.eq(opts.toAddress);
|
|
expect(transfers[0].amount).to.bignumber.eq(opts.fillAmount);
|
|
});
|
|
|
|
it('fails if `Eth2Dai.sellAllAmount()` reverts', async () => {
|
|
const opts = createTransferOpts({ revertReason: 'FOOBAR' });
|
|
const tx = transferAsync(opts);
|
|
return expect(tx).to.revertWith(opts.revertReason);
|
|
});
|
|
});
|
|
});
|