aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/src/1.0.0/Arbitrage/Arbitrage.sol
diff options
context:
space:
mode:
Diffstat (limited to 'packages/contracts/src/1.0.0/Arbitrage/Arbitrage.sol')
-rw-r--r--packages/contracts/src/1.0.0/Arbitrage/Arbitrage.sol114
1 files changed, 114 insertions, 0 deletions
diff --git a/packages/contracts/src/1.0.0/Arbitrage/Arbitrage.sol b/packages/contracts/src/1.0.0/Arbitrage/Arbitrage.sol
new file mode 100644
index 000000000..5054afc2f
--- /dev/null
+++ b/packages/contracts/src/1.0.0/Arbitrage/Arbitrage.sol
@@ -0,0 +1,114 @@
+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]);
+ }
+}