aboutsummaryrefslogblamecommitdiffstats
path: root/packages/contracts/src/1.0.0/Arbitrage/Arbitrage.sol
blob: 5054afc2f0ce7beabcf10197c74424dde3372a3c (plain) (tree)
1
2
3
4
5
6
7
8
9
                        
 
                                                                        
                                                          

                                                                  
 

                                                                                                                





                               
                                           






                                                                                                     



                                                                                                   
                                                                     






                                                     

                                                                                                                      


                          
             













                               
                                              
                                              
                          




                                                        
                                              


                                              



                                                    
                         






                                                     




                  



                                                     


                               
                                              


                                              




                                        

                                      





                                                  
          

                                                                                                   


                                                                                                      
pragma solidity ^0.4.19;

import { IExchange_v1 as Exchange } from "../Exchange/IExchange_v1.sol";
import { EtherDelta } from "../EtherDelta/EtherDelta.sol";
import { Ownable_v1 as Ownable } from "../Ownable/Ownable_v1.sol";
import { IToken_v1 as Token } from "../Token/IToken_v1.sol";

/// @title Arbitrage - Facilitates atomic arbitrage of ERC20 tokens between EtherDelta and 0x Exchange contract.
/// @author Leonid Logvinov - <leo@0xProject.com>
contract Arbitrage is Ownable {

    Exchange exchange;
    EtherDelta etherDelta;
    address proxyAddress;

    uint256 constant MAX_UINT = 2**256 - 1;

    function Arbitrage(address _exchangeAddress, address _etherDeltaAddress, address _proxyAddress) {
        exchange = Exchange(_exchangeAddress);
        etherDelta = EtherDelta(_etherDeltaAddress);
        proxyAddress = _proxyAddress;
    }

    /*
     * Makes token tradeable by setting an allowance for etherDelta and 0x proxy contract.
     * Also sets an allowance for the owner of the contracts therefore allowing to withdraw tokens.
     */
    function setAllowances(address tokenAddress) external onlyOwner {
        Token token = Token(tokenAddress);
        token.approve(address(etherDelta), MAX_UINT);
        token.approve(proxyAddress, MAX_UINT);
        token.approve(owner, MAX_UINT);
    }

    /*
     * Because of the limits on the number of local variables in Solidity we need to compress parameters while loosing
     * readability. Scheme of the parameter layout:
     *
     * addresses
     * 0..4 orderAddresses
     * 5 user
     *
     * values
     * 0..5 orderValues
     * 6 fillTakerTokenAmount
     * 7 amountGet
     * 8 amountGive
     * 9 expires
     * 10 nonce
     * 11 amount

     * signature
     * exchange then etherDelta
     */
    function makeAtomicTrade(
        address[6] addresses, uint[12] values,
        uint8[2] v, bytes32[2] r, bytes32[2] s
    ) external onlyOwner {
        makeExchangeTrade(addresses, values, v, r, s);
        makeEtherDeltaTrade(addresses, values, v, r, s);
    }

    function makeEtherDeltaTrade(
        address[6] addresses, uint[12] values,
        uint8[2] v, bytes32[2] r, bytes32[2] s
    ) internal {
        uint amount = values[11];
        etherDelta.depositToken(
            addresses[2], // tokenGet === makerToken
            values[7] // amountGet
        );
        etherDelta.trade(
            addresses[2], // tokenGet === makerToken
            values[7], // amountGet
            addresses[3], // tokenGive === takerToken
            values[8], // amountGive
            values[9], // expires
            values[10], // nonce
            addresses[5], // user
            v[1],
            r[1],
            s[1],
            amount
        );
        etherDelta.withdrawToken(
            addresses[3], // tokenGive === tokenToken
            values[8] // amountGive
        );
    }

    function makeExchangeTrade(
        address[6] addresses, uint[12] values,
        uint8[2] v, bytes32[2] r, bytes32[2] s
    ) internal {
        address[5] memory orderAddresses = [
            addresses[0], // maker
            addresses[1], // taker
            addresses[2], // makerToken
            addresses[3], // takerToken
            addresses[4] // feeRecepient
        ];
        uint[6] memory orderValues = [
            values[0], // makerTokenAmount
            values[1], // takerTokenAmount
            values[2], // makerFee
            values[3], // takerFee
            values[4], // expirationTimestampInSec
            values[5]  // salt
        ];
        uint fillTakerTokenAmount = values[6]; // fillTakerTokenAmount
        // Execute Exchange trade. It either succeeds in full or fails and reverts all the changes.
        exchange.fillOrKillOrder(orderAddresses, orderValues, fillTakerTokenAmount, v[0], r[0], s[0]);
    }
}