* update abi-gen with new method interfaces * wip: get all packages to build * wip: get all packages to build * Fix two contract wrapper calls * Export necessary types part of the contract wrapper public interfaces * Revive and fix wrapper_unit_tests * Remove duplicate type * Fix lib_exchange_rich_error_decoder tests * Fix remaining test failures in contracts-* packages * Prettier fixes * remove transactionHelper * lint and update changelogs * Fix prettier * Revert changes to reference docs * Add back changelog already published and add revert changelog entry * Add missing CHANGELOG entries * Add missing comma * Update mesh-rpc-client dep * Update Mesh RPC logic in @0x/orderbook to v6.0.1-beta * Align package versions
		
			
				
	
	
		
			192 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import {
 | |
|     blockchainTests,
 | |
|     constants,
 | |
|     expect,
 | |
|     filterLogsToArguments,
 | |
|     getRandomInteger,
 | |
|     hexLeftPad,
 | |
|     hexRandom,
 | |
|     Numberish,
 | |
|     randomAddress,
 | |
| } from '@0x/contracts-test-utils';
 | |
| import { AssetProxyId } from '@0x/types';
 | |
| import { BigNumber, RawRevertError } from '@0x/utils';
 | |
| import { DecodedLogs } from 'ethereum-types';
 | |
| import * as _ from 'lodash';
 | |
| 
 | |
| import { artifacts } from './artifacts';
 | |
| 
 | |
| import {
 | |
|     TestEth2DaiBridgeContract,
 | |
|     TestEth2DaiBridgeEvents,
 | |
|     TestEth2DaiBridgeSellAllAmountEventArgs,
 | |
|     TestEth2DaiBridgeTokenApproveEventArgs,
 | |
|     TestEth2DaiBridgeTokenTransferEventArgs,
 | |
| } from './wrappers';
 | |
| 
 | |
| blockchainTests.resets('Eth2DaiBridge unit tests', env => {
 | |
|     let testContract: TestEth2DaiBridgeContract;
 | |
| 
 | |
|     before(async () => {
 | |
|         testContract = await TestEth2DaiBridgeContract.deployFrom0xArtifactAsync(
 | |
|             artifacts.TestEth2DaiBridge,
 | |
|             env.provider,
 | |
|             env.txDefaults,
 | |
|             artifacts,
 | |
|         );
 | |
|     });
 | |
| 
 | |
|     describe('isValidSignature()', () => {
 | |
|         it('returns success bytes', async () => {
 | |
|             const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
 | |
|             const result = await testContract.isValidSignature(hexRandom(), hexRandom(_.random(0, 32))).callAsync();
 | |
|             expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
 | |
|         });
 | |
|     });
 | |
| 
 | |
|     describe('bridgeTransferFrom()', () => {
 | |
|         interface WithdrawToOpts {
 | |
|             toTokenAddress?: string;
 | |
|             fromTokenAddress?: string;
 | |
|             toAddress: string;
 | |
|             amount: Numberish;
 | |
|             fromTokenBalance: Numberish;
 | |
|             revertReason: string;
 | |
|             fillAmount: Numberish;
 | |
|             toTokentransferRevertReason: string;
 | |
|             toTokenTransferReturnData: string;
 | |
|         }
 | |
| 
 | |
|         interface WithdrawToResult {
 | |
|             opts: WithdrawToOpts;
 | |
|             result: string;
 | |
|             logs: DecodedLogs;
 | |
|         }
 | |
| 
 | |
|         function createWithdrawToOpts(opts?: Partial<WithdrawToOpts>): WithdrawToOpts {
 | |
|             return {
 | |
|                 toAddress: randomAddress(),
 | |
|                 amount: getRandomInteger(1, 100e18),
 | |
|                 revertReason: '',
 | |
|                 fillAmount: getRandomInteger(1, 100e18),
 | |
|                 fromTokenBalance: getRandomInteger(1, 100e18),
 | |
|                 toTokentransferRevertReason: '',
 | |
|                 toTokenTransferReturnData: hexLeftPad(1),
 | |
|                 ...opts,
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         async function withdrawToAsync(opts?: Partial<WithdrawToOpts>): Promise<WithdrawToResult> {
 | |
|             const _opts = createWithdrawToOpts(opts);
 | |
|             // Set the fill behavior.
 | |
|             await testContract
 | |
|                 .setFillBehavior(_opts.revertReason, new BigNumber(_opts.fillAmount))
 | |
|                 .awaitTransactionSuccessAsync();
 | |
|             // Create tokens and balances.
 | |
|             if (_opts.fromTokenAddress === undefined) {
 | |
|                 const createTokenFn = testContract.createToken(new BigNumber(_opts.fromTokenBalance));
 | |
|                 _opts.fromTokenAddress = await createTokenFn.callAsync();
 | |
|                 await createTokenFn.awaitTransactionSuccessAsync();
 | |
|             }
 | |
|             if (_opts.toTokenAddress === undefined) {
 | |
|                 const createTokenFn = testContract.createToken(constants.ZERO_AMOUNT);
 | |
|                 _opts.toTokenAddress = await createTokenFn.callAsync();
 | |
|                 await createTokenFn.awaitTransactionSuccessAsync();
 | |
|             }
 | |
|             // Set the transfer behavior of `toTokenAddress`.
 | |
|             await testContract
 | |
|                 .setTransferBehavior(
 | |
|                     _opts.toTokenAddress,
 | |
|                     _opts.toTokentransferRevertReason,
 | |
|                     _opts.toTokenTransferReturnData,
 | |
|                 )
 | |
|                 .awaitTransactionSuccessAsync();
 | |
|             // Call bridgeTransferFrom().
 | |
|             const bridgeTransferFromFn = testContract.bridgeTransferFrom(
 | |
|                 // "to" token address
 | |
|                 _opts.toTokenAddress,
 | |
|                 // Random from address.
 | |
|                 randomAddress(),
 | |
|                 // To address.
 | |
|                 _opts.toAddress,
 | |
|                 new BigNumber(_opts.amount),
 | |
|                 // ABI-encode the "from" token address as the bridge data.
 | |
|                 hexLeftPad(_opts.fromTokenAddress as string),
 | |
|             );
 | |
|             const result = await bridgeTransferFromFn.callAsync();
 | |
|             const { logs } = await bridgeTransferFromFn.awaitTransactionSuccessAsync();
 | |
|             return {
 | |
|                 opts: _opts,
 | |
|                 result,
 | |
|                 logs: (logs as any) as DecodedLogs,
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         it('returns magic bytes on success', async () => {
 | |
|             const BRIDGE_SUCCESS_RETURN_DATA = AssetProxyId.ERC20Bridge;
 | |
|             const { result } = await withdrawToAsync();
 | |
|             expect(result).to.eq(BRIDGE_SUCCESS_RETURN_DATA);
 | |
|         });
 | |
| 
 | |
|         it('calls `Eth2Dai.sellAllAmount()`', async () => {
 | |
|             const { opts, logs } = await withdrawToAsync();
 | |
|             const transfers = filterLogsToArguments<TestEth2DaiBridgeSellAllAmountEventArgs>(
 | |
|                 logs,
 | |
|                 TestEth2DaiBridgeEvents.SellAllAmount,
 | |
|             );
 | |
|             expect(transfers.length).to.eq(1);
 | |
|             expect(transfers[0].sellToken).to.eq(opts.fromTokenAddress);
 | |
|             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('sets an unlimited allowance on the `fromTokenAddress` token', async () => {
 | |
|             const { opts, logs } = await withdrawToAsync();
 | |
|             const approvals = filterLogsToArguments<TestEth2DaiBridgeTokenApproveEventArgs>(
 | |
|                 logs,
 | |
|                 TestEth2DaiBridgeEvents.TokenApprove,
 | |
|             );
 | |
|             expect(approvals.length).to.eq(1);
 | |
|             expect(approvals[0].token).to.eq(opts.fromTokenAddress);
 | |
|             expect(approvals[0].spender).to.eq(testContract.address);
 | |
|             expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
 | |
|         });
 | |
| 
 | |
|         it('transfers filled amount to `to`', async () => {
 | |
|             const { opts, logs } = await withdrawToAsync();
 | |
|             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 = createWithdrawToOpts({ revertReason: 'FOOBAR' });
 | |
|             const tx = withdrawToAsync(opts);
 | |
|             return expect(tx).to.revertWith(opts.revertReason);
 | |
|         });
 | |
| 
 | |
|         it('fails if `toTokenAddress.transfer()` reverts', async () => {
 | |
|             const opts = createWithdrawToOpts({ toTokentransferRevertReason: 'FOOBAR' });
 | |
|             const tx = withdrawToAsync(opts);
 | |
|             return expect(tx).to.revertWith(opts.toTokentransferRevertReason);
 | |
|         });
 | |
| 
 | |
|         it('fails if `toTokenAddress.transfer()` returns false', async () => {
 | |
|             const opts = createWithdrawToOpts({ toTokenTransferReturnData: hexLeftPad(0) });
 | |
|             const tx = withdrawToAsync(opts);
 | |
|             return expect(tx).to.revertWith(new RawRevertError(hexLeftPad(0)));
 | |
|         });
 | |
| 
 | |
|         it('succeeds if `toTokenAddress.transfer()` returns true', async () => {
 | |
|             await withdrawToAsync({ toTokenTransferReturnData: hexLeftPad(1) });
 | |
|         });
 | |
|     });
 | |
| });
 |