aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/test
diff options
context:
space:
mode:
Diffstat (limited to 'packages/contracts/test')
-rw-r--r--packages/contracts/test/tutorials/arbitrage.ts207
1 files changed, 207 insertions, 0 deletions
diff --git a/packages/contracts/test/tutorials/arbitrage.ts b/packages/contracts/test/tutorials/arbitrage.ts
new file mode 100644
index 000000000..b2f1c338a
--- /dev/null
+++ b/packages/contracts/test/tutorials/arbitrage.ts
@@ -0,0 +1,207 @@
+import { ECSignature, ZeroEx } from '0x.js';
+import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
+import { BigNumber } from '@0xproject/utils';
+import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import * as chai from 'chai';
+import ethUtil = require('ethereumjs-util');
+import * as Web3 from 'web3';
+
+import { Balances } from '../../util/balances';
+import { constants } from '../../util/constants';
+import { crypto } from '../../util/crypto';
+import { ExchangeWrapper } from '../../util/exchange_wrapper';
+import { Order } from '../../util/order';
+import { OrderFactory } from '../../util/order_factory';
+import { BalancesByOwner, ContractName, ExchangeContractErrs } from '../../util/types';
+import { chaiSetup } from '../utils/chai_setup';
+import { deployer } from '../utils/deployer';
+
+chaiSetup.configure();
+const expect = chai.expect;
+const web3 = web3Factory.create();
+const web3Wrapper = new Web3Wrapper(web3.currentProvider);
+const blockchainLifecycle = new BlockchainLifecycle();
+
+describe.only('Arbitrage', () => {
+ let coinbase: string;
+ let maker: string;
+ let edMaker: string;
+ let edFrontRunner: string;
+ const feeRecipient = ZeroEx.NULL_ADDRESS;
+ const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
+ const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
+
+ let weth: Web3.ContractInstance;
+ let zrx: Web3.ContractInstance;
+ let arbitrage: Web3.ContractInstance;
+ let etherDelta: Web3.ContractInstance;
+
+ let order: Order;
+ let exWrapper: ExchangeWrapper;
+ let orderFactory: OrderFactory;
+
+ let zeroEx: ZeroEx;
+
+ before(async () => {
+ const accounts = await web3Wrapper.getAvailableAddressesAsync();
+ [coinbase, maker, edMaker, edFrontRunner] = accounts;
+ weth = await deployer.deployAsync(ContractName.DummyToken);
+ zrx = await deployer.deployAsync(ContractName.DummyToken);
+ const accountLevels = await deployer.deployAsync(ContractName.AccountLevels);
+ const edAdminAddress = accounts[0];
+ const edMakerFee = 0;
+ const edTakerFee = 0;
+ const edFeeRebate = 0;
+ etherDelta = await deployer.deployAsync(ContractName.EtherDelta, [
+ edAdminAddress,
+ feeRecipient,
+ accountLevels.address,
+ edMakerFee,
+ edTakerFee,
+ edFeeRebate,
+ ]);
+ const tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
+ const exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]);
+ await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
+ zeroEx = new ZeroEx(web3.currentProvider, {
+ exchangeContractAddress: exchange.address,
+ networkId: constants.TESTRPC_NETWORK_ID,
+ });
+ exWrapper = new ExchangeWrapper(exchange, zeroEx);
+
+ const defaultOrderParams = {
+ exchangeContractAddress: exchange.address,
+ maker,
+ feeRecipient,
+ makerToken: zrx.address,
+ takerToken: weth.address,
+ makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
+ takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
+ makerFee: new BigNumber(0),
+ takerFee: new BigNumber(0),
+ };
+ orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams);
+ arbitrage = await deployer.deployAsync(ContractName.Arbitrage, [
+ exchange.address,
+ etherDelta.address,
+ tokenTransferProxy.address,
+ ]);
+ // Enable arbitrage and withdrawals of tokens
+ await arbitrage.setAllowances(weth.address, { from: coinbase });
+ await arbitrage.setAllowances(zrx.address, { from: coinbase });
+
+ // Give some tokens to arbitrage contract
+ await weth.setBalance(arbitrage.address, ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), { from: coinbase });
+
+ // Fund the maker on exchange side
+ await zrx.setBalance(maker, ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), { from: coinbase });
+ // Set the allowance for the maker on Exchange side
+ await zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: maker });
+
+ const amountGive = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
+ // Fund the maker on EtherDelta side
+ await weth.setBalance(edMaker, ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), { from: coinbase });
+ // Set the allowance for the maker on EtherDelta side
+ await weth.approve(etherDelta.address, INITIAL_ALLOWANCE, { from: edMaker });
+ // Deposit maker funds into EtherDelta
+ await etherDelta.depositToken(weth.address, amountGive, { from: edMaker });
+
+ const amountGet = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
+ // Fund the front runner on EtherDelta side
+ await zrx.setBalance(edFrontRunner, amountGet, { from: coinbase });
+ // Set the allowance for the maker on EtherDelta side
+ await zrx.approve(etherDelta.address, INITIAL_ALLOWANCE, { from: edFrontRunner });
+ // Deposit front runner funds into EtherDelta
+ await etherDelta.depositToken(zrx.address, amountGet, { from: edFrontRunner });
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ describe('makeAtomicTrade', () => {
+ let addresses: string[];
+ let values: BigNumber[];
+ let v: number[];
+ let r: string[];
+ let s: string[];
+ let tokenGet: string;
+ let tokenGive: string;
+ let amountGet: BigNumber;
+ let amountGive: BigNumber;
+ let expires: BigNumber;
+ let nonce: BigNumber;
+ let edSignature: ECSignature;
+ before(async () => {
+ order = await orderFactory.newSignedOrderAsync();
+ const shouldAddPersonalMessagePrefix = false;
+ tokenGet = zrx.address;
+ amountGet = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
+ tokenGive = weth.address;
+ amountGive = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
+ const blockNumber = await web3Wrapper.getBlockNumberAsync();
+ expires = new BigNumber(blockNumber + 10);
+ nonce = new BigNumber(42);
+ const edOrderHash = `0x${crypto
+ .solSHA256([etherDelta.address, tokenGet, amountGet, tokenGive, amountGive, expires, nonce])
+ .toString('hex')}`;
+ edSignature = await zeroEx.signOrderHashAsync(edOrderHash, edMaker, shouldAddPersonalMessagePrefix);
+ addresses = [
+ order.params.maker,
+ order.params.taker,
+ order.params.makerToken,
+ order.params.takerToken,
+ order.params.feeRecipient,
+ tokenGet,
+ tokenGive,
+ edMaker,
+ ];
+ const fillTakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
+ const edFillAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
+ values = [
+ order.params.makerTokenAmount,
+ order.params.takerTokenAmount,
+ order.params.makerFee,
+ order.params.takerFee,
+ order.params.expirationTimestampInSec,
+ order.params.salt,
+ fillTakerTokenAmount,
+ amountGet,
+ amountGive,
+ expires,
+ nonce,
+ edFillAmount,
+ ];
+ v = [order.params.v as number, edSignature.v];
+ r = [order.params.r as string, edSignature.r];
+ s = [order.params.s as string, edSignature.s];
+ });
+ it('1', async () => {
+ const txHash = await arbitrage.makeAtomicTrade(addresses, values, v, r, s, { from: coinbase });
+ const res = await zeroEx.awaitTransactionMinedAsync(txHash);
+ const postBalance = await weth.balanceOf(arbitrage.address);
+ expect(postBalance).to.be.bignumber.equal(ZeroEx.toBaseUnitAmount(new BigNumber(2), 18));
+ });
+ it('2', async () => {
+ // Front-running transaction
+ await etherDelta.trade(
+ tokenGet,
+ amountGet,
+ tokenGive,
+ amountGive,
+ expires,
+ nonce,
+ edMaker,
+ edSignature.v,
+ edSignature.r,
+ edSignature.s,
+ ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
+ { from: edFrontRunner },
+ );
+ return expect(arbitrage.makeAtomicTrade(addresses, values, v, r, s, { from: coinbase })).to.be.rejectedWith(
+ constants.REVERT,
+ );
+ });
+ });
+});