diff --git a/.solcover.js b/.solcover.js
index 669e290..a183d57 100644
--- a/.solcover.js
+++ b/.solcover.js
@@ -2,5 +2,8 @@ module.exports = {
port: 9545,
testrpcOptions:
'-p 9545 -m "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat"',
- copyNodeModules: false
+ testCommand: 'truffle test --network coverage',
+ norpc: true,
+ copyPackages: ['openzeppelin-solidity'],
+ skipFiles: ['Bin/DEX.sol', 'Bin/Kyber.sol', 'Bin/Uniswap.sol', 'Bin/FreeProxy.sol', 'Reference/Auth.sol','Migrations.sol']
}
diff --git a/compiler.json b/compiler.json
new file mode 100644
index 0000000..0650451
--- /dev/null
+++ b/compiler.json
@@ -0,0 +1,13 @@
+{
+ "contractsDir": "contracts",
+ "artifactsDir": "docs",
+ "contracts": "*",
+ "compilerSettings": {
+ "optimizer": { "enabled": false },
+ "outputSelection": {
+ "*": {
+ "*": ["abi","devdoc"]
+ }
+ }
+ }
+}
diff --git a/contracts/Bin/FreeProxy.sol b/contracts/Bin/FreeProxy.sol
index 71b6cfd..91adc5a 100644
--- a/contracts/Bin/FreeProxy.sol
+++ b/contracts/Bin/FreeProxy.sol
@@ -1,4 +1,4 @@
-pragma solidity ^0.5.0;
+pragma solidity ^0.5.2;
interface TubInterface {
diff --git a/contracts/Bin/Kyber.sol b/contracts/Bin/Kyber.sol
index 0b4a32c..62b7fb9 100644
--- a/contracts/Bin/Kyber.sol
+++ b/contracts/Bin/Kyber.sol
@@ -1,26 +1,7 @@
-pragma solidity ^0.5.0;
+pragma solidity ^0.5.2;
-
-library SafeMath {
-
- function mul(uint256 a, uint256 b) internal pure returns (uint256) {
- if (a == 0) {
- return 0;
- }
- uint256 c = a * b;
- require(c / a == b, "Assertion Failed");
- return c;
- }
-
-}
-
-interface IERC20 {
- function balanceOf(address who) external view returns (uint256);
- function allowance(address _owner, address _spender) external view returns (uint256);
- function transfer(address to, uint256 value) external returns (bool);
- function approve(address spender, uint256 value) external returns (bool);
- function transferFrom(address from, address to, uint256 value) external returns (bool);
-}
+import "openzeppelin-solidity/contracts/math/SafeMath.sol";
+import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
interface AddressRegistry {
function getAddr(string calldata name) external view returns (address);
@@ -28,12 +9,19 @@ interface AddressRegistry {
interface Kyber {
// Kyber's trade function
- function trade(address src, uint srcAmount, address dest, address destAddress, uint maxDestAmount, uint minConversionRate, address walletId) external payable returns (uint);
+ function trade(
+ address src,
+ uint srcAmount,
+ address dest,
+ address destAddress,
+ uint maxDestAmount,
+ uint minConversionRate,
+ address walletId
+ ) external payable returns (uint);
// Kyber's Get expected Rate function
function getExpectedRate(address src, address dest, uint srcQty) external view returns (uint, uint);
}
-
contract Registry {
address public addressRegistry;
modifier onlyAdmin() {
@@ -47,16 +35,7 @@ contract Registry {
}
contract helper is Registry {
-
- function _getToken(
- address trader,
- address src,
- uint srcAmt,
- address eth
- )
- internal
- returns (uint ethQty)
- {
+ function _getToken(address trader, address src, uint srcAmt, address eth) internal returns (uint ethQty) {
if (src == eth) {
require(msg.value == srcAmt, "Invalid Operation");
ethQty = srcAmt;
@@ -71,7 +50,7 @@ contract helper is Registry {
function _approveKyber(address token) internal returns (bool) {
address kyberProxy = _getAddress("kyber");
IERC20 tokenFunctions = IERC20(token);
- return tokenFunctions.approve(kyberProxy, uint(0-1));
+ return tokenFunctions.approve(kyberProxy, uint(0 - 1));
}
// Check Allowance to Kyber Proxy contract
@@ -92,9 +71,7 @@ contract helper is Registry {
}
}
-
contract Trade is helper {
-
using SafeMath for uint;
event KyberTrade(address src, uint srcAmt, address dest, uint destAmt, address beneficiary, uint minConversionRate, address affiliate);
@@ -104,9 +81,8 @@ contract Trade is helper {
return kyberFunctions.getExpectedRate(src, dest, srcAmt);
}
-
/**
- * @title Kyber's trade when token to sell Amount fixed
+ * @dev Kyber's trade when token to sell Amount fixed
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param srcAmt - amount of token for sell
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
@@ -119,12 +95,7 @@ contract Trade is helper {
uint minDestAmt // minimum slippage rate
) public payable returns (uint tokensBought) {
address eth = _getAddress("eth");
- uint ethQty = _getToken(
- msg.sender,
- src,
- srcAmt,
- eth
- );
+ uint ethQty = _getToken(msg.sender, src, srcAmt, eth);
if (src != eth) {
_allowanceApproveKyber(src);
@@ -132,23 +103,14 @@ contract Trade is helper {
// Interacting with Kyber Proxy Contract
Kyber kyberFunctions = Kyber(_getAddress("kyber"));
- tokensBought = kyberFunctions.trade.value(ethQty)(
- src,
- srcAmt,
- dest,
- msg.sender,
- uint(0-1),
- minDestAmt,
- _getAddress("admin")
- );
+ tokensBought = kyberFunctions.trade.value(ethQty)(src, srcAmt, dest, msg.sender, uint(0 - 1), minDestAmt, _getAddress("admin"));
emit KyberTrade(src, srcAmt, dest, tokensBought, msg.sender, minDestAmt, _getAddress("admin"));
}
-
/**
- * @title Kyber's trade when token to sell Amount fixed
+ * @dev Kyber's trade when token to sell Amount fixed
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param maxSrcAmt - max amount of token for sell (slippage)
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
@@ -160,14 +122,8 @@ contract Trade is helper {
address dest, // token to buy
uint destAmt // minimum slippage rate
) public payable returns (uint tokensBought) {
-
address eth = _getAddress("eth");
- uint ethQty = _getToken(
- msg.sender,
- src,
- maxSrcAmt,
- eth
- );
+ uint ethQty = _getToken(msg.sender, src, maxSrcAmt, eth);
if (src != eth) {
_allowanceApproveKyber(src);
@@ -175,15 +131,7 @@ contract Trade is helper {
// Interacting with Kyber Proxy Contract
Kyber kyberFunctions = Kyber(_getAddress("kyber"));
- tokensBought = kyberFunctions.trade.value(ethQty)(
- src,
- maxSrcAmt,
- dest,
- msg.sender,
- destAmt,
- destAmt - 1,
- _getAddress("admin")
- );
+ tokensBought = kyberFunctions.trade.value(ethQty)(src, maxSrcAmt, dest, msg.sender, destAmt, destAmt - 1, _getAddress("admin"));
// maxDestAmt usecase implementated
if (src == eth && address(this).balance > 0) {
@@ -205,11 +153,9 @@ contract Trade is helper {
contract InstaKyber is Trade {
-
constructor(address rAddr) public {
addressRegistry = rAddr;
}
function() external payable {}
-
}
diff --git a/contracts/Bin/MakerContract.sol b/contracts/Bin/MakerContract.sol
deleted file mode 100644
index 73e013f..0000000
--- a/contracts/Bin/MakerContract.sol
+++ /dev/null
@@ -1,288 +0,0 @@
-pragma solidity ^0.4.23;
-
-/// math.sol -- mixin for inline numerical wizardry
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-pragma solidity ^0.4.13;
-
-contract DSMath {
- function add(uint x, uint y) internal pure returns (uint z) {
- require((z = x + y) >= x);
- }
- function sub(uint x, uint y) internal pure returns (uint z) {
- require((z = x - y) <= x);
- }
- function mul(uint x, uint y) internal pure returns (uint z) {
- require(y == 0 || (z = x * y) / y == x);
- }
-
- function min(uint x, uint y) internal pure returns (uint z) {
- return x <= y ? x : y;
- }
- function max(uint x, uint y) internal pure returns (uint z) {
- return x >= y ? x : y;
- }
- function imin(int x, int y) internal pure returns (int z) {
- return x <= y ? x : y;
- }
- function imax(int x, int y) internal pure returns (int z) {
- return x >= y ? x : y;
- }
-
- uint constant WAD = 10 ** 18;
- uint constant RAY = 10 ** 27;
-
- function wmul(uint x, uint y) internal pure returns (uint z) {
- z = add(mul(x, y), WAD / 2) / WAD;
- }
- function rmul(uint x, uint y) internal pure returns (uint z) {
- z = add(mul(x, y), RAY / 2) / RAY;
- }
- function wdiv(uint x, uint y) internal pure returns (uint z) {
- z = add(mul(x, WAD), y / 2) / y;
- }
- function rdiv(uint x, uint y) internal pure returns (uint z) {
- z = add(mul(x, RAY), y / 2) / y;
- }
-
- // This famous algorithm is called "exponentiation by squaring"
- // and calculates x^n with x as fixed-point and n as regular unsigned.
- //
- // It's O(log n), instead of O(n) for naive repeated multiplication.
- //
- // These facts are why it works:
- //
- // If n is even, then x^n = (x^2)^(n/2).
- // If n is odd, then x^n = x * x^(n-1),
- // and applying the equation for even x gives
- // x^n = x * (x^2)^((n-1) / 2).
- //
- // Also, EVM division is flooring and
- // floor[(n-1) / 2] = floor[n / 2].
- //
- function rpow(uint x, uint n) internal pure returns (uint z) {
- z = n % 2 != 0 ? x : RAY;
-
- for (n /= 2; n != 0; n /= 2) {
- x = rmul(x, x);
-
- if (n % 2 != 0) {
- z = rmul(z, x);
- }
- }
- }
-}
-
-contract TubInterface {
- function open() public returns (bytes32);
- function join(uint) public;
- function exit(uint) public;
- function lock(bytes32, uint) public;
- function free(bytes32, uint) public;
- function draw(bytes32, uint) public;
- function wipe(bytes32, uint) public;
- function give(bytes32, address) public;
- function shut(bytes32) public;
- function cups(bytes32) public view returns (address, uint, uint, uint);
- function gem() public view returns (TokenInterface);
- function gov() public view returns (TokenInterface);
- function skr() public view returns (TokenInterface);
- function sai() public view returns (TokenInterface);
- function mat() public view returns (uint);
- function ink(bytes32) public view returns (uint);
- function tab(bytes32) public view returns (uint);
- function rap(bytes32) public view returns (uint);
- function per() public view returns (uint);
- function pep() public view returns (PepInterface);
-}
-
-contract TokenInterface {
- function allowance(address, address) public view returns (uint);
- function balanceOf(address) public view returns (uint);
- function approve(address, uint) public;
- function transfer(address, uint) public returns (bool);
- function transferFrom(address, address, uint) public returns (bool);
- function deposit() public payable;
- function withdraw(uint) public;
-}
-
-contract PepInterface {
- function peek() public returns (bytes32, bool);
-}
-
-contract OtcInterface {
- function getPayAmount(address, address, uint) public view returns (uint);
- function buyAllAmount(address, uint, address pay_gem, uint) public returns (uint);
-}
-
-contract SaiProxy is DSMath {
- function open(address tub_) public returns (bytes32) {
- return TubInterface(tub_).open();
- }
-
- function give(address tub_, bytes32 cup, address lad) public {
- TubInterface(tub_).give(cup, lad);
- }
-
- function lock(address tub_, bytes32 cup) public payable {
- if (msg.value > 0) {
- TubInterface tub = TubInterface(tub_);
-
- (address lad,,,) = tub.cups(cup);
- require(lad == address(this), "cup-not-owned");
-
- tub.gem().deposit.value(msg.value)();
-
- uint ink = rdiv(msg.value, tub.per());
- ink = rmul(ink, tub.per()) <= msg.value ? ink : ink - 1;
-
- if (tub.gem().allowance(this, tub) != uint(-1)) {
- tub.gem().approve(tub, uint(-1));
- }
- tub.join(ink);
-
- if (tub.skr().allowance(this, tub) != uint(-1)) {
- tub.skr().approve(tub, uint(-1));
- }
- tub.lock(cup, ink);
- }
- }
-
- function draw(address tub_, bytes32 cup, uint wad) public {
- if (wad > 0) {
- TubInterface tub = TubInterface(tub_);
- tub.draw(cup, wad);
- tub.sai().transfer(msg.sender, wad);
- }
- }
-
- function handleGovFee(TubInterface tub, uint saiDebtFee, address otc_) internal {
- bytes32 val;
- bool ok;
- (val, ok) = tub.pep().peek();
- if (ok && val != 0) {
- uint govAmt = wdiv(saiDebtFee, uint(val));
- if (otc_ != address(0)) {
- uint saiGovAmt = OtcInterface(otc_).getPayAmount(tub.sai(), tub.gov(), govAmt);
- if (tub.sai().allowance(this, otc_) != uint(-1)) {
- tub.sai().approve(otc_, uint(-1));
- }
- tub.sai().transferFrom(msg.sender, this, saiGovAmt);
- OtcInterface(otc_).buyAllAmount(tub.gov(), govAmt, tub.sai(), saiGovAmt);
- } else {
- tub.gov().transferFrom(msg.sender, this, govAmt);
- }
- }
- }
-
- function wipe(address tub_, bytes32 cup, uint wad, address otc_) public {
- if (wad > 0) {
- TubInterface tub = TubInterface(tub_);
-
- tub.sai().transferFrom(msg.sender, this, wad);
- handleGovFee(tub, rmul(wad, rdiv(tub.rap(cup), tub.tab(cup))), otc_);
-
- if (tub.sai().allowance(this, tub) != uint(-1)) {
- tub.sai().approve(tub, uint(-1));
- }
- if (tub.gov().allowance(this, tub) != uint(-1)) {
- tub.gov().approve(tub, uint(-1));
- }
- tub.wipe(cup, wad);
- }
- }
-
- function wipe(address tub_, bytes32 cup, uint wad) public {
- wipe(tub_, cup, wad, address(0));
- }
-
- function free(address tub_, bytes32 cup, uint jam) public {
- if (jam > 0) {
- TubInterface tub = TubInterface(tub_);
- uint ink = rdiv(jam, tub.per());
- ink = rmul(ink, tub.per()) <= jam ? ink : ink - 1;
- tub.free(cup, ink);
- if (tub.skr().allowance(this, tub) != uint(-1)) {
- tub.skr().approve(tub, uint(-1));
- }
- tub.exit(ink);
- uint freeJam = tub.gem().balanceOf(this); // Withdraw possible previous stuck WETH as well
- tub.gem().withdraw(freeJam);
- address(msg.sender).transfer(freeJam);
- }
- }
-
- function lockAndDraw(address tub_, bytes32 cup, uint wad) public payable {
- lock(tub_, cup);
- draw(tub_, cup, wad);
- }
-
- function lockAndDraw(address tub_, uint wad) public payable returns (bytes32 cup) {
- cup = open(tub_);
- lockAndDraw(tub_, cup, wad);
- }
-
- function wipeAndFree(address tub_, bytes32 cup, uint jam, uint wad) public payable {
- wipe(tub_, cup, wad);
- free(tub_, cup, jam);
- }
-
- function wipeAndFree(address tub_, bytes32 cup, uint jam, uint wad, address otc_) public payable {
- wipe(tub_, cup, wad, otc_);
- free(tub_, cup, jam);
- }
-
- function shut(address tub_, bytes32 cup) public {
- TubInterface tub = TubInterface(tub_);
- wipeAndFree(tub_, cup, rmul(tub.ink(cup), tub.per()), tub.tab(cup));
- tub.shut(cup);
- }
-
- function shut(address tub_, bytes32 cup, address otc_) public {
- TubInterface tub = TubInterface(tub_);
- wipeAndFree(tub_, cup, rmul(tub.ink(cup), tub.per()), tub.tab(cup), otc_);
- tub.shut(cup);
- }
-}
-
-contract ProxyRegistryInterface {
- function build(address) public returns (address);
-}
-
-contract SaiProxyCreateAndExecute is SaiProxy {
-
- // Create a DSProxy instance and open a cup
- function createAndOpen(address registry_, address tub_) public returns (address proxy, bytes32 cup) {
- proxy = ProxyRegistryInterface(registry_).build(msg.sender);
- cup = open(tub_);
- TubInterface(tub_).give(cup, proxy);
- }
-
- // Create a DSProxy instance, open a cup, and lock collateral
- function createOpenAndLock(address registry_, address tub_) public payable returns (address proxy, bytes32 cup) {
- proxy = ProxyRegistryInterface(registry_).build(msg.sender);
- cup = open(tub_);
- lock(tub_, cup);
- TubInterface(tub_).give(cup, proxy);
- }
-
- // Create a DSProxy instance, open a cup, lock collateral, and draw DAI
- function createOpenLockAndDraw(address registry_, address tub_, uint wad) public payable returns (address proxy, bytes32 cup) {
- proxy = ProxyRegistryInterface(registry_).build(msg.sender);
- cup = open(tub_);
- lockAndDraw(tub_, cup, wad);
- TubInterface(tub_).give(cup, proxy);
- }
-}
\ No newline at end of file
diff --git a/contracts/Bin/DEX.sol b/contracts/Bin/Trade.sol
similarity index 76%
rename from contracts/Bin/DEX.sol
rename to contracts/Bin/Trade.sol
index 4653031..03d4475 100644
--- a/contracts/Bin/DEX.sol
+++ b/contracts/Bin/Trade.sol
@@ -1,15 +1,7 @@
-pragma solidity 0.5.0;
+pragma solidity ^0.5.2;
-
-import "./safemath.sol";
-
-interface IERC20 {
- function balanceOf(address who) external view returns (uint256);
- function allowance(address _owner, address _spender) external view returns (uint256);
- function transfer(address to, uint256 value) external returns (bool);
- function approve(address spender, uint256 value) external returns (bool);
- function transferFrom(address from, address to, uint256 value) external returns (bool);
-}
+import "openzeppelin-solidity/contracts/math/SafeMath.sol";
+import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
interface AddressRegistry {
function getAddr(string calldata name) external view returns (address);
@@ -18,7 +10,15 @@ interface AddressRegistry {
// Kyber's contract Interface
interface KyberExchange {
// Kyber's trade function
- function trade(address src, uint srcAmount, address dest, address destAddress, uint maxDestAmount, uint minConversionRate, address walletId) external payable returns (uint);
+ function trade(
+ address src,
+ uint srcAmount,
+ address dest,
+ address destAddress,
+ uint maxDestAmount,
+ uint minConversionRate,
+ address walletId
+ ) external payable returns (uint);
// Kyber's Get expected Rate function
function getExpectedRate(address src, address dest, uint srcQty) external view returns (uint, uint);
}
@@ -37,17 +37,40 @@ interface UniswapExchange {
function getTokenToEthInputPrice(uint256 tokens_sold) external view returns (uint256 eth_bought);
function getTokenToEthOutputPrice(uint256 eth_bought) external view returns (uint256 tokens_sold);
// Trade ETH to ERC20
- function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient) external payable returns (uint256 tokens_bought);
- function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient) external payable returns (uint256 eth_sold);
+ function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient)
+ external
+ payable
+ returns (uint256 tokens_bought);
+ function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient)
+ external
+ payable
+ returns (uint256 eth_sold);
// Trade ERC20 to ETH
- function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline, address recipient) external returns (uint256 eth_bought);
- function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient) external returns (uint256 tokens_sold);
+ function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline, address recipient)
+ external
+ returns (uint256 eth_bought);
+ function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient)
+ external
+ returns (uint256 tokens_sold);
// Trade ERC20 to ERC20
- function tokenToTokenTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_bought);
- function tokenToTokenTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_sold);
+ function tokenToTokenTransferInput(
+ uint256 tokens_sold,
+ uint256 min_tokens_bought,
+ uint256 min_eth_bought,
+ uint256 deadline,
+ address recipient,
+ address token_addr
+ ) external returns (uint256 tokens_bought);
+ function tokenToTokenTransferOutput(
+ uint256 tokens_bought,
+ uint256 max_tokens_sold,
+ uint256 max_eth_sold,
+ uint256 deadline,
+ address recipient,
+ address token_addr
+ ) external returns (uint256 tokens_sold);
}
-
contract Registry {
address public addressRegistry;
modifier onlyAdmin() {
@@ -62,16 +85,10 @@ contract Registry {
// common stuffs in Kyber and Uniswap's trade
contract CommonStuffs {
-
using SafeMath for uint;
- // Check required ETH Quantity to execute code
- function _getToken(
- address trader,
- address src,
- uint srcAmt,
- address eth
- ) internal returns (uint ethQty) {
+ // Check required ETH Quantity to execute code
+ function _getToken(address trader, address src, uint srcAmt, address eth) internal returns (uint ethQty) {
if (src == eth) {
require(msg.value == srcAmt, "Invalid Operation");
ethQty = srcAmt;
@@ -84,24 +101,22 @@ contract CommonStuffs {
function _approveDexes(address token, address dexToApprove) internal returns (bool) {
IERC20 tokenFunctions = IERC20(token);
- return tokenFunctions.approve(dexToApprove, uint(0-1));
+ return tokenFunctions.approve(dexToApprove, uint(0 - 1));
}
function _allowance(address token, address spender) internal view returns (uint) {
IERC20 tokenFunctions = IERC20(token);
return tokenFunctions.allowance(address(this), spender);
}
-
-}
+}
// Kyber's dex functions
contract Kyber is Registry, CommonStuffs {
-
function getExpectedRateKyber(address src, address dest, uint srcAmt) internal view returns (uint) {
KyberExchange kyberFunctions = KyberExchange(_getAddress("kyber"));
uint expectedRate;
- (expectedRate,) = kyberFunctions.getExpectedRate(src, dest, srcAmt);
+ (expectedRate, ) = kyberFunctions.getExpectedRate(src, dest, srcAmt);
uint kyberRate = expectedRate.mul(srcAmt);
return kyberRate;
}
@@ -128,7 +143,7 @@ contract Kyber is Registry, CommonStuffs {
}
/**
- * @title Kyber's trade when token to sell Amount fixed
+ * @dev Kyber's trade when token to sell Amount fixed
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param srcAmt - amount of token for sell
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
@@ -141,24 +156,11 @@ contract Kyber is Registry, CommonStuffs {
uint minDestAmt // minimum slippage rate
) public payable returns (uint tokensBought) {
address eth = _getAddress("eth");
- uint ethQty = _getToken(
- msg.sender,
- src,
- srcAmt,
- eth
- );
+ uint ethQty = _getToken(msg.sender, src, srcAmt, eth);
// Interacting with Kyber Proxy Contract
KyberExchange kyberFunctions = KyberExchange(_getAddress("kyber"));
- tokensBought = kyberFunctions.trade.value(ethQty)(
- src,
- srcAmt,
- dest,
- msg.sender,
- uint(0-1),
- minDestAmt,
- _getAddress("admin")
- );
+ tokensBought = kyberFunctions.trade.value(ethQty)(src, srcAmt, dest, msg.sender, uint(0 - 1), minDestAmt, _getAddress("admin"));
}
@@ -169,24 +171,11 @@ contract Kyber is Registry, CommonStuffs {
uint destAmt // minimum slippage rate
) public payable returns (uint tokensBought) {
address eth = _getAddress("eth");
- uint ethQty = _getToken(
- msg.sender,
- src,
- maxSrcAmt,
- eth
- );
+ uint ethQty = _getToken(msg.sender, src, maxSrcAmt, eth);
// Interacting with Kyber Proxy Contract
KyberExchange kyberFunctions = KyberExchange(_getAddress("kyber"));
- tokensBought = kyberFunctions.trade.value(ethQty)(
- src,
- maxSrcAmt,
- dest,
- msg.sender,
- destAmt,
- destAmt,
- _getAddress("admin")
- );
+ tokensBought = kyberFunctions.trade.value(ethQty)(src, maxSrcAmt, dest, msg.sender, destAmt, destAmt, _getAddress("admin"));
// maxDestAmt usecase implementated
if (src == eth && address(this).balance > 0) {
@@ -204,10 +193,8 @@ contract Kyber is Registry, CommonStuffs {
}
-
// Uinswap's dex functions
contract Uniswap is Registry, CommonStuffs {
-
// Get Uniswap's Exchange address from Factory Contract
function _getExchangeAddress(address _token) internal view returns (address) {
UniswapFactory uniswapMain = UniswapFactory(_getAddress("uniswap"));
@@ -236,17 +223,12 @@ contract Uniswap is Registry, CommonStuffs {
}
/**
- * @title Uniswap's get expected rate from source
+ * @dev Uniswap's get expected rate from source
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param srcAmt - source token amount
- * @returns expected Dest Amount
*/
- function getExpectedRateSrcUniswap(
- address src,
- address dest,
- uint srcAmt
- ) internal view returns (uint256) {
+ function getExpectedRateSrcUniswap(address src, address dest, uint srcAmt) internal view returns (uint256) {
address eth = _getAddress("eth");
if (src == eth) {
// define uniswap exchange with dest address
@@ -265,16 +247,12 @@ contract Uniswap is Registry, CommonStuffs {
}
/**
- * @title Uniswap's get expected rate from dest
+ * @dev Uniswap's get expected rate from dest
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param destAmt - dest token amount
*/
- function getExpectedRateDestUniswap(
- address src,
- address dest,
- uint destAmt
- ) internal view returns (uint256) {
+ function getExpectedRateDestUniswap(address src, address dest, uint destAmt) internal view returns (uint256) {
address eth = _getAddress("eth");
if (src == eth) {
// define uniswap exchange with dest address
@@ -292,30 +270,17 @@ contract Uniswap is Registry, CommonStuffs {
}
}
-
/**
- * @title Uniswap's trade when token to sell Amount fixed
+ * @dev Uniswap's trade when token to sell Amount fixed
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param srcAmt - amount of token for sell
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param minDestAmt - min amount of token to buy (slippage)
* @param deadline - time for this transaction to be valid
*/
- function tradeSrcUniswap(
- address src,
- uint srcAmt,
- address dest,
- uint minDestAmt,
- uint deadline
- ) public payable returns (uint) {
-
+ function tradeSrcUniswap(address src, uint srcAmt, address dest, uint minDestAmt, uint deadline) public payable returns (uint) {
address eth = _getAddress("eth");
- uint ethQty = _getToken(
- msg.sender,
- src,
- srcAmt,
- eth
- );
+ uint ethQty = _getToken(msg.sender, src, srcAmt, eth);
if (src == eth) {
UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));
@@ -332,30 +297,17 @@ contract Uniswap is Registry, CommonStuffs {
}
}
-
/**
- * @title Uniswap's trade when token to buy Amount fixed
+ * @dev Uniswap's trade when token to buy Amount fixed
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param maxSrcAmt - max amount of token for sell (slippage)
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param destAmt - amount of token to buy
* @param deadline - time for this transaction to be valid
*/
- function tradeDestUniswap(
- address src,
- uint maxSrcAmt,
- address dest,
- uint destAmt,
- uint deadline
- ) public payable returns (uint) {
-
+ function tradeDestUniswap(address src, uint maxSrcAmt, address dest, uint destAmt, uint deadline) public payable returns (uint) {
address eth = _getAddress("eth");
- uint ethQty = _getToken(
- msg.sender,
- src,
- maxSrcAmt,
- eth
- );
+ uint ethQty = _getToken(msg.sender, src, maxSrcAmt, eth);
if (src == eth) {
UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));
@@ -376,7 +328,7 @@ contract Uniswap is Registry, CommonStuffs {
return tokensSold;
} else {
UniswapExchange exchangeContractSrc = UniswapExchange(_getExchangeAddress(src));
- uint tokensSold = exchangeContractSrc.tokenToTokenTransferOutput(destAmt, maxSrcAmt, uint(0-1), deadline, msg.sender, dest);
+ uint tokensSold = exchangeContractSrc.tokenToTokenTransferOutput(destAmt, maxSrcAmt, uint(0 - 1), deadline, msg.sender, dest);
if (tokensSold < maxSrcAmt) {
IERC20 srcTkn = IERC20(src);
uint srcToReturn = maxSrcAmt - tokensSold;
@@ -389,9 +341,9 @@ contract Uniswap is Registry, CommonStuffs {
}
-contract Trade is Kyber, Uniswap {
- function getRateFromSrc(address src, address dest, uint srcAmt) public view returns(uint, uint) {
+contract Trade is Kyber, Uniswap {
+ function getRateFromSrc(address src, address dest, uint srcAmt) public view returns (uint, uint) {
uint uniswapRate = getExpectedRateSrcUniswap(src, dest, srcAmt);
uint kyberRate = getExpectedRateKyber(src, dest, srcAmt);
if (uniswapRate > kyberRate) {
@@ -401,13 +353,7 @@ contract Trade is Kyber, Uniswap {
}
}
- function tradeFromSrc(
- address src,
- uint srcAmt,
- address dest,
- uint minDestAmt,
- uint dexNum
- ) public payable returns (uint) {
+ function tradeFromSrc(address src, uint srcAmt, address dest, uint minDestAmt, uint dexNum) public payable returns (uint) {
address eth = _getAddress("eth");
if (dexNum == 1) {
if (src == eth) {
@@ -426,13 +372,7 @@ contract Trade is Kyber, Uniswap {
}
}
- function tradeFromDest(
- address src,
- uint maxSrcAmt,
- address dest,
- uint destAmt,
- uint dexNum
- ) public payable returns (uint) {
+ function tradeFromDest(address src, uint maxSrcAmt, address dest, uint destAmt, uint dexNum) public payable returns (uint) {
address eth = _getAddress("eth");
if (dexNum == 1) {
if (src == eth) {
@@ -450,5 +390,4 @@ contract Trade is Kyber, Uniswap {
}
}
}
-
-}
+}
\ No newline at end of file
diff --git a/contracts/Bin/Uniswap.sol b/contracts/Bin/UniswapTrade.sol
similarity index 74%
rename from contracts/Bin/Uniswap.sol
rename to contracts/Bin/UniswapTrade.sol
index 258f522..c417cd9 100644
--- a/contracts/Bin/Uniswap.sol
+++ b/contracts/Bin/UniswapTrade.sol
@@ -1,14 +1,7 @@
-pragma solidity 0.5.0;
+pragma solidity ^0.5.2;
-
-import "./Safemath.sol";
-
-interface IERC20 {
- function balanceOf(address who) external view returns (uint256);
- function transfer(address to, uint256 value) external returns (bool);
- function approve(address spender, uint256 value) external returns (bool);
- function transferFrom(address from, address to, uint256 value) external returns (bool);
-}
+import "openzeppelin-solidity/contracts/math/SafeMath.sol";
+import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
interface AddressRegistry {
function getAddr(string calldata name) external view returns (address);
@@ -28,17 +21,40 @@ interface UniswapExchange {
function getTokenToEthInputPrice(uint256 tokens_sold) external view returns (uint256 eth_bought);
function getTokenToEthOutputPrice(uint256 eth_bought) external view returns (uint256 tokens_sold);
// Trade ETH to ERC20
- function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient) external payable returns (uint256 tokens_bought);
- function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient) external payable returns (uint256 eth_sold);
+ function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient)
+ external
+ payable
+ returns (uint256 tokens_bought);
+ function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient)
+ external
+ payable
+ returns (uint256 eth_sold);
// Trade ERC20 to ETH
- function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_tokens, uint256 deadline, address recipient) external returns (uint256 eth_bought);
- function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient) external returns (uint256 tokens_sold);
+ function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_tokens, uint256 deadline, address recipient)
+ external
+ returns (uint256 eth_bought);
+ function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient)
+ external
+ returns (uint256 tokens_sold);
// Trade ERC20 to ERC20
- function tokenToTokenTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_bought);
- function tokenToTokenTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_sold);
+ function tokenToTokenTransferInput(
+ uint256 tokens_sold,
+ uint256 min_tokens_bought,
+ uint256 min_eth_bought,
+ uint256 deadline,
+ address recipient,
+ address token_addr
+ ) external returns (uint256 tokens_bought);
+ function tokenToTokenTransferOutput(
+ uint256 tokens_bought,
+ uint256 max_tokens_sold,
+ uint256 max_eth_sold,
+ uint256 deadline,
+ address recipient,
+ address token_addr
+ ) external returns (uint256 tokens_sold);
}
-
contract Registry {
address public addressRegistry;
modifier onlyAdmin() {
@@ -51,9 +67,7 @@ contract Registry {
}
}
-
-contract Trade is Registry {
-
+contract UniswapTrade is Registry {
using SafeMath for uint;
// Get Uniswap's Exchange address from Factory Contract
@@ -62,16 +76,8 @@ contract Trade is Registry {
return uniswapMain.getExchange(_token);
}
- // Check required ETH Quantity to execute code
- function _getToken(
- address trader,
- address src,
- uint srcAmt,
- address eth
- )
- internal
- returns (uint ethQty)
- {
+ // Check required ETH Quantity to execute code
+ function _getToken(address trader, address src, uint srcAmt, address eth) internal returns (uint ethQty) {
if (src == eth) {
require(msg.value == srcAmt, "Invalid Operation");
ethQty = srcAmt;
@@ -82,18 +88,13 @@ contract Trade is Registry {
}
}
-
/**
- * @title Uniswap's get expected rate from source
+ * @dev Uniswap's get expected rate from source
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param srcAmt - source token amount
*/
- function getExpectedRateSrcUniswap(
- address src,
- address dest,
- uint srcAmt
- ) external view returns (uint256) {
+ function getExpectedRateSrcUniswap(address src, address dest, uint srcAmt) external view returns (uint256) {
if (src == getAddress("eth")) {
// define uniswap exchange with dest address
UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));
@@ -111,16 +112,12 @@ contract Trade is Registry {
}
/**
- * @title Uniswap's get expected rate from dest
+ * @dev Uniswap's get expected rate from dest
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param destAmt - dest token amount
*/
- function getExpectedRateDestUniswap(
- address src,
- address dest,
- uint destAmt
- ) external view returns (uint256) {
+ function getExpectedRateDestUniswap(address src, address dest, uint destAmt) external view returns (uint256) {
address eth = getAddress("eth");
if (src == eth) {
// define uniswap exchange with dest address
@@ -138,30 +135,17 @@ contract Trade is Registry {
}
}
-
/**
- * @title Uniswap's trade when token to sell Amount fixed
+ * @dev Uniswap's trade when token to sell Amount fixed
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param srcAmt - amount of token for sell
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param minDestAmt - min amount of token to buy (slippage)
* @param deadline - time for this transaction to be valid
*/
- function tradeSrcUniswap(
- address src,
- uint srcAmt,
- address dest,
- uint minDestAmt,
- uint deadline
- ) public payable returns (uint) {
-
+ function tradeSrcUniswap(address src, uint srcAmt, address dest, uint minDestAmt, uint deadline) public payable returns (uint) {
address eth = getAddress("eth");
- uint ethQty = _getToken(
- msg.sender,
- src,
- srcAmt,
- eth
- );
+ uint ethQty = _getToken(msg.sender, src, srcAmt, eth);
if (src == eth) {
UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));
@@ -178,30 +162,17 @@ contract Trade is Registry {
}
}
-
/**
- * @title Uniswap's trade when token to buy Amount fixed
+ * @dev Uniswap's trade when token to buy Amount fixed
* @param src - Token address to sell (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param maxSrcAmt - max amount of token for sell (slippage)
* @param dest - Token address to buy (for ETH it's "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
* @param destAmt - amount of token to buy
* @param deadline - time for this transaction to be valid
*/
- function tradeDestUniswap(
- address src,
- uint maxSrcAmt,
- address dest,
- uint destAmt,
- uint deadline
- ) public payable returns (uint) {
-
+ function tradeDestUniswap(address src, uint maxSrcAmt, address dest, uint destAmt, uint deadline) public payable returns (uint) {
address eth = getAddress("eth");
- uint ethQty = _getToken(
- msg.sender,
- src,
- maxSrcAmt,
- eth
- );
+ uint ethQty = _getToken(msg.sender, src, maxSrcAmt, eth);
if (src == eth) {
UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));
@@ -222,7 +193,7 @@ contract Trade is Registry {
return tokensSold;
} else {
UniswapExchange exchangeContractSrc = UniswapExchange(_getExchangeAddress(src));
- uint tokensSold = exchangeContractSrc.tokenToTokenTransferOutput(destAmt, maxSrcAmt, uint(0-1), deadline, msg.sender, dest);
+ uint tokensSold = exchangeContractSrc.tokenToTokenTransferOutput(destAmt, maxSrcAmt, uint(0 - 1), deadline, msg.sender, dest);
if (tokensSold < maxSrcAmt) {
IERC20 srcTkn = IERC20(src);
uint srcToReturn = maxSrcAmt - tokensSold;
@@ -233,4 +204,4 @@ contract Trade is Registry {
}
-}
\ No newline at end of file
+}
diff --git a/contracts/InstaRegistry.sol b/contracts/InstaRegistry.sol
index 144195b..f8210fb 100644
--- a/contracts/InstaRegistry.sol
+++ b/contracts/InstaRegistry.sol
@@ -1,16 +1,20 @@
-pragma solidity ^0.5.0;
+pragma solidity ^0.5.2;
import "./UserWallet.sol";
-/**
- * @title Address Registry
- */
+/// @title AddressRegistry
+/// @notice
+/// @dev
contract AddressRegistry {
event LogSetAddress(string name, address addr);
+ /// @notice Registry of role and address
mapping(bytes32 => address) registry;
+ /**
+ * @dev Check if msg.sender is admin or owner.
+ */
modifier isAdmin() {
require(
msg.sender == getAddress("admin") ||
@@ -20,103 +24,95 @@ contract AddressRegistry {
_;
}
- /**
- * @dev get the address from system registry
- */
- function getAddress(string memory name) public view returns(address) {
- return registry[keccak256(abi.encodePacked(name))];
+ /// @dev Get the address from system registry
+ /// @param _name (string)
+ /// @return (address) Returns address based on role
+ function getAddress(string memory _name) public view returns(address) {
+ return registry[keccak256(abi.encodePacked(_name))];
}
- /**
- * @dev set new address in system registry
- */
- function setAddress(string memory name, address addr) public isAdmin {
- registry[keccak256(abi.encodePacked(name))] = addr;
- emit LogSetAddress(name, addr);
+ /// @dev Set new address in system registry
+ /// @param _name (string) Role name
+ /// @param _userAddress (string) User Address
+ function setAddress(string memory _name, address _userAddress) public isAdmin {
+ registry[keccak256(abi.encodePacked(_name))] = _userAddress;
+ emit LogSetAddress(_name, _userAddress);
}
-
}
-/**
- * @title Logic Registry
- */
+/// @title LogicRegistry
+/// @notice
+/// @dev LogicRegistry
contract LogicRegistry is AddressRegistry {
- event LogEnableDefaultLogic(address logicAddr);
- event LogEnableLogic(address logicAddr);
- event LogDisableLogic(address logicAddr);
+ event LogEnableDefaultLogic(address logicAddress);
+ event LogEnableLogic(address logicAddress);
+ event LogDisableLogic(address logicAddress);
+ /// @notice Map of default proxy state
mapping(address => bool) public defaultLogicProxies;
+
+ /// @notice Map of logic proxy state
mapping(address => bool) public logicProxies;
- /**
- * @dev get the boolean of the logic contract
- * @param logicAddr is the logic proxy address
- * @return bool logic proxy is authorised by system admin
- * @return bool logic proxy is default proxy
- */
- function logic(address logicAddr) public view returns (bool) {
- if (defaultLogicProxies[logicAddr] || logicProxies[logicAddr]) {
+ /// @dev
+ /// @param _logicAddress (address)
+ /// @return (bool)
+ function logic(address _logicAddress) public view returns (bool) {
+ if (defaultLogicProxies[_logicAddress] || logicProxies[_logicAddress]) {
return true;
} else {
return false;
}
}
- /**
- * @dev this sets the default logic proxy to true
- * default proxies mostly contains the logic for withdrawal of assets
- * and can never be false to freely let user withdraw their assets
- * @param logicAddr is the default logic proxy address
- */
- function enableDefaultLogic(address logicAddr) public isAdmin {
- defaultLogicProxies[logicAddr] = true;
- emit LogEnableDefaultLogic(logicAddr);
+ /// @dev Sets the default logic proxy to true
+ /// default proxies mostly contains the logic for withdrawal of assets
+ /// and can never be false to freely let user withdraw their assets
+ /// @param _logicAddress (address)
+ function enableDefaultLogic(address _logicAddress) public isAdmin {
+ defaultLogicProxies[_logicAddress] = true;
+ emit LogEnableDefaultLogic(_logicAddress);
}
- /**
- * @dev enable logic proxy address and sets true
- * @param logicAddr is the logic proxy address
- */
- function enableLogic(address logicAddr) public isAdmin {
- logicProxies[logicAddr] = true;
- emit LogEnableLogic(logicAddr);
+ /// @dev Enable logic proxy address
+ /// @param _logicAddress (address)
+ function enableLogic(address _logicAddress) public isAdmin {
+ logicProxies[_logicAddress] = true;
+ emit LogEnableLogic(_logicAddress);
}
- /**
- * @dev enable logic proxy address and sets false
- * @param logicAddr is the logic proxy address
- */
- function disableLogic(address logicAddr) public isAdmin {
- logicProxies[logicAddr] = false;
- emit LogDisableLogic(logicAddr);
+ /// @dev Disable logic proxy address
+ /// @param _logicAddress (address)
+ function disableLogic(address _logicAddress) public isAdmin {
+ logicProxies[_logicAddress] = false;
+ emit LogDisableLogic(_logicAddress);
}
}
-
/**
- * @title User Wallet Registry
+ * @dev Deploys a new proxy instance and sets msg.sender as owner of proxy
*/
contract WalletRegistry is LogicRegistry {
event Created(address indexed sender, address indexed owner, address proxy);
event LogRecord(address indexed currentOwner, address indexed nextOwner, address proxy);
+ /// @notice Address to UserWallet proxy map
mapping(address => UserWallet) public proxies;
-
- /**
- * @dev deploys a new proxy instance and sets msg.sender as owner of proxy
- */
+
+ /// @dev Deploys a new proxy instance and sets custom owner of proxy
+ /// Throws if the owner already have a UserWallet
+ /// @return proxy ()
function build() public returns (UserWallet proxy) {
proxy = build(msg.sender);
}
- /**
- * @dev deploys a new proxy instance and sets custom owner of proxy
- * Throws if the owner already have a UserWallet
- */
+ /// @dev update the proxy record whenever owner changed on any proxy
+ /// Throws if msg.sender is not a proxy contract created via this contract
+ /// @return proxy () UserWallet
function build(address owner) public returns (UserWallet proxy) {
require(proxies[owner] == UserWallet(0), "multiple-proxy-per-user-not-allowed");
proxy = new UserWallet();
@@ -125,29 +121,25 @@ contract WalletRegistry is LogicRegistry {
emit Created(msg.sender, owner, address(proxy));
}
- /**
- * @dev update the proxy record whenever owner changed on any proxy
- * Throws if msg.sender is not a proxy contract created via this contract
- */
- function record(address currentOwner, address nextOwner) public {
- require(msg.sender == address(proxies[currentOwner]), "invalid-proxy-or-owner");
- require(proxies[nextOwner] == UserWallet(0), "multiple-proxy-per-user-not-allowed");
- proxies[nextOwner] = proxies[currentOwner];
- proxies[currentOwner] = UserWallet(0);
- emit LogRecord(currentOwner, nextOwner, address(proxies[nextOwner]));
+ /// @dev Transafers ownership
+ /// @param _currentOwner (address) Current Owner
+ /// @param _nextOwner (address) Next Owner
+ function record(address _currentOwner, address _nextOwner) public {
+ require(msg.sender == address(proxies[_currentOwner]), "invalid-proxy-or-owner");
+ require(proxies[_nextOwner] == UserWallet(0), "multiple-proxy-per-user-not-allowed");
+ proxies[_nextOwner] = proxies[_currentOwner];
+ proxies[_currentOwner] = UserWallet(0);
+ emit LogRecord(_currentOwner, _nextOwner, address(proxies[_nextOwner]));
}
}
-
-/**
- * @title Initializing Registry
- */
+/// @title InstaRegistry
+/// @dev Initializing Registry
contract InstaRegistry is WalletRegistry {
constructor() public {
registry[keccak256(abi.encodePacked("admin"))] = msg.sender;
registry[keccak256(abi.encodePacked("owner"))] = msg.sender;
}
-
-}
\ No newline at end of file
+}
diff --git a/contracts/Bin/Migrations.sol b/contracts/Migrations.sol
similarity index 96%
rename from contracts/Bin/Migrations.sol
rename to contracts/Migrations.sol
index 483c891..08dc00e 100644
--- a/contracts/Bin/Migrations.sol
+++ b/contracts/Migrations.sol
@@ -1,4 +1,4 @@
-pragma solidity ^0.5.0;
+pragma solidity ^0.5.2;
/* solium-disable mixedcase */
contract Migrations {
diff --git a/contracts/Bin/Ownable.sol b/contracts/Ownable.sol
similarity index 97%
rename from contracts/Bin/Ownable.sol
rename to contracts/Ownable.sol
index 7b6bff5..d607a1e 100644
--- a/contracts/Bin/Ownable.sol
+++ b/contracts/Ownable.sol
@@ -1,5 +1,4 @@
-pragma solidity ^0.5.0;
-
+pragma solidity ^0.5.2;
/**
* @title Ownable
diff --git a/contracts/ProxyLogics/InstaKyber.sol b/contracts/ProxyLogics/InstaKyber.sol
index 4e13180..1a712e9 100644
--- a/contracts/ProxyLogics/InstaKyber.sol
+++ b/contracts/ProxyLogics/InstaKyber.sol
@@ -1,25 +1,7 @@
pragma solidity ^0.5.0;
-
-library SafeMath {
- function mul(uint256 a, uint256 b) internal pure returns (uint256) {
- if (a == 0) {
- return 0;
- }
- uint256 c = a * b;
- require(c / a == b, "Assertion Failed");
- return c;
- }
-}
-
-
-contract IERC20 {
- function balanceOf(address who) public view returns (uint256);
- function allowance(address _owner, address _spender) public view returns (uint256);
- function transfer(address to, uint256 value) public returns (bool);
- function approve(address spender, uint256 value) public returns (bool);
- function transferFrom(address from, address to, uint256 value) public returns (bool);
-}
+import "openzeppelin-solidity/contracts/math/SafeMath.sol";
+import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
contract KyberInterface {
diff --git a/contracts/ProxyLogics/InstaMaker.sol b/contracts/ProxyLogics/InstaMaker.sol
index e6361ed..062040c 100644
--- a/contracts/ProxyLogics/InstaMaker.sol
+++ b/contracts/ProxyLogics/InstaMaker.sol
@@ -1,5 +1,6 @@
pragma solidity ^0.5.0;
+import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
interface TubInterface {
function open() external returns (bytes32);
diff --git a/contracts/ProxyLogics/InstaUniswapPool.sol b/contracts/ProxyLogics/InstaUniswapPool.sol
index 83677af..1855f6f 100644
--- a/contracts/ProxyLogics/InstaUniswapPool.sol
+++ b/contracts/ProxyLogics/InstaUniswapPool.sol
@@ -1,25 +1,7 @@
pragma solidity ^0.5.0;
-
-library SafeMath {
- function mul(uint256 a, uint256 b) internal pure returns (uint256) {
- if (a == 0) {
- return 0;
- }
- uint256 c = a * b;
- require(c / a == b, "Assertion Failed");
- return c;
- }
-}
-
-
-contract IERC20 {
- function balanceOf(address who) public view returns (uint256);
- function allowance(address _owner, address _spender) public view returns (uint256);
- function transfer(address to, uint256 value) public returns (bool);
- function approve(address spender, uint256 value) public returns (bool);
- function transferFrom(address from, address to, uint256 value) public returns (bool);
-}
+import "openzeppelin-solidity/contracts/math/SafeMath.sol";
+import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
contract UniswapFactory {
diff --git a/contracts/ProxyLogics/default.sol b/contracts/ProxyLogics/default.sol
deleted file mode 100644
index a6b8953..0000000
--- a/contracts/ProxyLogics/default.sol
+++ /dev/null
@@ -1,33 +0,0 @@
-pragma solidity ^0.5.0;
-
-interface IERC20 {
- function transfer(address to, uint256 value) external returns (bool);
-}
-
-interface ICDP {
- function give(bytes32 cup, address guy) external;
-}
-
-
-contract ProxyTest {
- event LogTransferETH(address dest, uint amount);
- event LogTransferERC20(address token, address dest, uint amount);
- event LogTransferCDP(address dest, uint num);
-
- function transferETH(address dest, uint amount) public payable {
- dest.transfer(amount);
- emit LogTransferETH(dest, amount);
- }
-
- function transferERC20(address tokenAddr, address dest, address amount) public {
- IERC20 tkn = IERC20(tokenAddr);
- tkn.transfer(dest, amount);
- emit LogTransferERC20(tokenAddr, dest, amount);
- }
-
- function transferCDP(address tub, address dest, uint num) public {
- ICDP loanMaster = ICDP(tub);
- loanMaster.give(bytes32(num), dest);
- emit LogTransferCDP(dest, num);
- }
-}
\ No newline at end of file
diff --git a/contracts/Reference/Auth.sol b/contracts/Reference/InstaWallet.sol
similarity index 88%
rename from contracts/Reference/Auth.sol
rename to contracts/Reference/InstaWallet.sol
index 91800af..2071f27 100644
--- a/contracts/Reference/Auth.sol
+++ b/contracts/Reference/InstaWallet.sol
@@ -1,20 +1,9 @@
// This Auth Model also includes UserWallet Logics
// TODO => make it single Auth code for future launch where this Auth Contract will be the owner of UserWallet
-pragma solidity ^0.5.0;
-
-
-/**
- * @dev because math is not safe
- */
-library SafeMath {
- function add(uint256 a, uint256 b) internal pure returns (uint256) {
- uint256 c = a + b;
- require(c >= a, "math-not-safe");
- return c;
- }
-}
+pragma solidity ^0.5.2;
+import "openzeppelin-solidity/contracts/math/SafeMath.sol";
/**
* @title AddressRegistryInterface Interface
@@ -30,8 +19,8 @@ interface AddressRegistryInterface {
* @title UserWallet Interface
*/
// interface UserWalletInterface {
- // get the wallet address based on the owner of this wallet
- // and use execute interface from main UserWallet to call execute on this contract
+// get the wallet address based on the owner of this wallet
+// and use execute interface from main UserWallet to call execute on this contract
// }
@@ -39,7 +28,6 @@ interface AddressRegistryInterface {
* @title Address Registry Record
*/
contract AddressRecord {
-
/**
* @dev address registry of system, logic and wallet addresses
*/
@@ -151,14 +139,12 @@ contract UserAuth is AddressRecord {
}
-
/**
* @title User Guardians
* @dev the assigned guardian addresses (upto 3) can set new owners
* but only after certain period of owner's inactivity (i.e. activePeriod)
*/
contract UserGuardian is UserAuth {
-
event LogSetGuardian(uint num, address indexed prevGuardian, address indexed newGuardian);
event LogNewActivePeriod(uint newActivePeriod);
event LogSetOwnerViaGuardian(address nextOwner, address indexed guardian);
@@ -213,12 +199,7 @@ contract UserGuardian is UserAuth {
* @dev Throws if the msg.sender is not guardian
*/
function isGuardian(address _guardian) public view returns (bool) {
- if (
- _guardian == guardians[1] || _guardian == guardians[2] ||
- _guardian == guardians[3] || _guardian == guardians[4] ||
- _guardian == guardians[5]
- )
- {
+ if (_guardian == guardians[1] || _guardian == guardians[2] || _guardian == guardians[3] || _guardian == guardians[4] || _guardian == guardians[5]) {
return true;
} else {
return false;
@@ -227,14 +208,12 @@ contract UserGuardian is UserAuth {
}
-
/**
* @title User Manager
* @dev the assigned manager addresses (upto 3) can manage the wealth in contract to contract fashion
* but can't withdraw the assets on their personal address
*/
contract UserManager is UserGuardian {
-
event LogSetManager(uint num, address indexed prevManager, address indexed newManager);
mapping(uint => address) public managers;
@@ -263,12 +242,7 @@ contract UserManager is UserGuardian {
* @dev Throws if the msg.sender is not manager
*/
function isManager(address _manager) public view returns (bool) {
- if (
- _manager == managers[1] || _manager == managers[2] ||
- _manager == managers[3] || _manager == managers[4] ||
- _manager == managers[5]
- )
- {
+ if (_manager == managers[1] || _manager == managers[2] || _manager == managers[3] || _manager == managers[4] || _manager == managers[5]) {
return true;
} else {
return false;
@@ -277,19 +251,11 @@ contract UserManager is UserGuardian {
}
-
/**
* @dev logging the execute events
*/
contract UserNote {
- event LogNote(
- bytes4 indexed sig,
- address indexed guy,
- bytes32 indexed foo,
- bytes32 bar,
- uint wad,
- bytes fax
- );
+ event LogNote(bytes4 indexed sig, address indexed guy, bytes32 indexed foo, bytes32 bar, uint wad, bytes fax);
modifier note {
bytes32 foo;
@@ -298,24 +264,15 @@ contract UserNote {
foo := calldataload(4)
bar := calldataload(36)
}
- emit LogNote(
- msg.sig,
- msg.sender,
- foo,
- bar,
- msg.value,
- msg.data
- );
+ emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
-
/**
* @title User Owned Contract Wallet
*/
contract InstaWallet is UserManager, UserNote {
-
event LogExecute(address sender, address target, uint srcNum, uint sessionNum);
/**
@@ -337,12 +294,7 @@ contract InstaWallet is UserManager, UserNote {
* @param srcNum to find the source
* @param sessionNum to find the session
*/
- function execute(
- address _target,
- bytes memory _data,
- uint srcNum,
- uint sessionNum
- )
+ function execute(address _target, bytes memory _data, uint srcNum, uint sessionNum)
public
payable
note
@@ -350,13 +302,8 @@ contract InstaWallet is UserManager, UserNote {
returns (bytes memory response)
{
lastActivity = block.timestamp;
- emit LogExecute(
- msg.sender,
- _target,
- srcNum,
- sessionNum
- );
-
+ emit LogExecute(msg.sender, _target, srcNum, sessionNum);
+
// call contract in current context
assembly {
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
@@ -385,16 +332,16 @@ contract InstaWallet is UserManager, UserNote {
(bool isLogic, bool isDefault) = isLogicAuthorised(proxyTarget);
require(isLogic, "logic-proxy-address-not-allowed");
-
+
bool enact = false;
if (isAuth(msg.sender)) {
enact = true;
} else if (isManager(msg.sender) && !isDefault) {
enact = true;
}
-
+
require(enact, "not-executable");
_;
}
-}
\ No newline at end of file
+}
diff --git a/contracts/UserWallet.sol b/contracts/UserWallet.sol
index e70c5a1..a963325 100644
--- a/contracts/UserWallet.sol
+++ b/contracts/UserWallet.sol
@@ -1,17 +1,6 @@
-pragma solidity ^0.5.0;
-
-
-/**
- * @dev because math is not safe
- */
-library SafeMath {
- function add(uint256 a, uint256 b) internal pure returns (uint256) {
- uint256 c = a + b;
- require(c >= a, "math-not-safe");
- return c;
- }
-}
+pragma solidity ^0.5.2;
+import "openzeppelin-solidity/contracts/math/SafeMath.sol";
/**
* @title RegistryInterface Interface
@@ -21,7 +10,6 @@ interface RegistryInterface {
function record(address currentOwner, address nextOwner) external;
}
-
/**
* @title Address Registry Record
*/
@@ -85,7 +73,6 @@ contract UserAuth is AddressRecord {
return false;
}
}
-
}
@@ -140,17 +127,17 @@ contract UserWallet is UserAuth, UserNote {
function() external payable {}
/**
- * @dev execute authorised calls via delegate call
+ * @dev Execute authorised calls via delegate call
* @param _target logic proxy address
* @param _data delegate call data
- * @param srcNum to find the source
- * @param sessionNum to find the session
+ * @param _srcNum to find the source
+ * @param _sessionNum to find the session
*/
function execute(
address _target,
bytes memory _data,
- uint srcNum,
- uint sessionNum
+ uint _srcNum,
+ uint _sessionNum
)
public
payable
@@ -162,8 +149,8 @@ contract UserWallet is UserAuth, UserNote {
emit LogExecute(
msg.sender,
_target,
- srcNum,
- sessionNum
+ _srcNum,
+ _sessionNum
);
// call contract in current context
diff --git a/docs/FreeProxy.json b/docs/FreeProxy.json
new file mode 100644
index 0000000..6f500e3
--- /dev/null
+++ b/docs/FreeProxy.json
@@ -0,0 +1,120 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "FreeProxy",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "getAddressWETH",
+ "outputs": [
+ {
+ "name": "weth",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "getWETHBal",
+ "outputs": [
+ {
+ "name": "freeJam",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [],
+ "name": "withdrawWETH",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "getSaiWETH",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "wamt",
+ "type": "uint256"
+ }
+ ],
+ "name": "freeWETH",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "getSaiTubAddress",
+ "outputs": [
+ {
+ "name": "sai",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "pure",
+ "type": "function"
+ }
+ ],
+ "devdoc": {
+ "methods": {}
+ }
+ },
+ "sources": {
+ "Bin/FreeProxy.sol": {
+ "id": 0
+ }
+ },
+ "sourceCodes": {
+ "Bin/FreeProxy.sol": "pragma solidity ^0.5.2;\n\n\ninterface TubInterface {\n function gem() external view returns (TokenInterface);\n}\n\n\ninterface TokenInterface {\n function allowance(address, address) external view returns (uint);\n function balanceOf(address) external view returns (uint);\n function transfer(address, uint) external returns (bool);\n function approve(address, uint) external;\n function withdraw(uint) external;\n}\n\n\ncontract FreeProxy {\n\n function getSaiTubAddress() public pure returns (address sai) {\n sai = 0x448a5065aeBB8E423F0896E6c5D525C040f59af3;\n }\n\n function getAddressWETH() public pure returns (address weth) {\n weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n }\n\n function freeWETH(uint wamt) public {\n TubInterface tub = TubInterface(getSaiTubAddress());\n TokenInterface weth = tub.gem();\n\n uint freeJam = wamt;\n if (freeJam == 0) {\n freeJam = weth.balanceOf(address(this));\n }\n\n weth.withdraw(freeJam);\n msg.sender.transfer(freeJam);\n }\n\n function withdrawWETH() public {\n TubInterface tub = TubInterface(getSaiTubAddress());\n TokenInterface weth = tub.gem();\n uint freeJam = weth.balanceOf(address(this));\n weth.transfer(msg.sender, freeJam);\n }\n\n function getWETHBal() public view returns (uint freeJam) {\n TubInterface tub = TubInterface(getSaiTubAddress());\n TokenInterface weth = tub.gem();\n freeJam = weth.balanceOf(address(this));\n }\n\n function getSaiWETH() public view returns (address) {\n TubInterface tub = TubInterface(getSaiTubAddress());\n return address(tub.gem());\n }\n\n function setAllowance(TokenInterface token_, address spender_) private {\n if (token_.allowance(address(this), spender_) != uint(-1)) {\n token_.approve(spender_, uint(-1));\n }\n }\n\n}"
+ },
+ "sourceTreeHashHex": "0xa7b0a10e45beb64aec3d940e4bc0933e5908591468fdd83a5c8e0ec82332600f",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/docs/InstaRegistry.json b/docs/InstaRegistry.json
new file mode 100644
index 0000000..de93f0f
--- /dev/null
+++ b/docs/InstaRegistry.json
@@ -0,0 +1,414 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "InstaRegistry",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_logicAddress",
+ "type": "address"
+ }
+ ],
+ "name": "logic",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "logicProxies",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_currentOwner",
+ "type": "address"
+ },
+ {
+ "name": "_nextOwner",
+ "type": "address"
+ }
+ ],
+ "name": "record",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_logicAddress",
+ "type": "address"
+ }
+ ],
+ "name": "enableLogic",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [],
+ "name": "build",
+ "outputs": [
+ {
+ "name": "proxy",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_name",
+ "type": "string"
+ },
+ {
+ "name": "_userAddress",
+ "type": "address"
+ }
+ ],
+ "name": "setAddress",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "defaultLogicProxies",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_name",
+ "type": "string"
+ }
+ ],
+ "name": "getAddress",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "proxies",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_logicAddress",
+ "type": "address"
+ }
+ ],
+ "name": "disableLogic",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_logicAddress",
+ "type": "address"
+ }
+ ],
+ "name": "enableDefaultLogic",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "build",
+ "outputs": [
+ {
+ "name": "proxy",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "proxy",
+ "type": "address"
+ }
+ ],
+ "name": "Created",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "currentOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "nextOwner",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "proxy",
+ "type": "address"
+ }
+ ],
+ "name": "LogRecord",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "logicAddress",
+ "type": "address"
+ }
+ ],
+ "name": "LogEnableDefaultLogic",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "logicAddress",
+ "type": "address"
+ }
+ ],
+ "name": "LogEnableLogic",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "logicAddress",
+ "type": "address"
+ }
+ ],
+ "name": "LogDisableLogic",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "indexed": false,
+ "name": "addr",
+ "type": "address"
+ }
+ ],
+ "name": "LogSetAddress",
+ "type": "event"
+ }
+ ],
+ "devdoc": {
+ "details": "Initializing Registry",
+ "methods": {
+ "build()": {
+ "details": "Deploys a new proxy instance and sets custom owner of proxy Throws if the owner already have a UserWallet",
+ "return": "proxy ()"
+ },
+ "build(address)": {
+ "details": "update the proxy record whenever owner changed on any proxy Throws if msg.sender is not a proxy contract created via this contract",
+ "return": "proxy () UserWallet"
+ },
+ "disableLogic(address)": {
+ "details": "Disable logic proxy address",
+ "params": {
+ "_logicAddress": "(address)"
+ }
+ },
+ "enableDefaultLogic(address)": {
+ "details": "Sets the default logic proxy to true default proxies mostly contains the logic for withdrawal of assets and can never be false to freely let user withdraw their assets",
+ "params": {
+ "_logicAddress": "(address)"
+ }
+ },
+ "enableLogic(address)": {
+ "details": "Enable logic proxy address",
+ "params": {
+ "_logicAddress": "(address)"
+ }
+ },
+ "getAddress(string)": {
+ "details": "Get the address from system registry ",
+ "params": {
+ "_name": "(string)"
+ },
+ "return": "(address) Returns address based on role"
+ },
+ "logic(address)": {
+ "params": {
+ "_logicAddress": "(address)"
+ },
+ "return": "(bool)"
+ },
+ "record(address,address)": {
+ "details": "Transafers ownership",
+ "params": {
+ "_currentOwner": "(address) Current Owner",
+ "_nextOwner": "(address) Next Owner"
+ }
+ },
+ "setAddress(string,address)": {
+ "details": "Set new address in system registry ",
+ "params": {
+ "_name": "(string) Role name",
+ "_userAddress": "(string) User Address"
+ }
+ }
+ },
+ "title": "InstaRegistry"
+ }
+ },
+ "sources": {
+ "InstaRegistry.sol": {
+ "id": 2
+ },
+ "UserWallet.sol": {
+ "id": 7
+ },
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": {
+ "id": 8
+ }
+ },
+ "sourceCodes": {
+ "InstaRegistry.sol": "pragma solidity ^0.5.2;\n\nimport \"./UserWallet.sol\";\n\n\n/// @title AddressRegistry\n/// @notice \n/// @dev \ncontract AddressRegistry {\n event LogSetAddress(string name, address addr);\n\n /// @notice Registry of role and address\n mapping(bytes32 => address) registry;\n\n /**\n * @dev Check if msg.sender is admin or owner.\n */\n modifier isAdmin() {\n require(\n msg.sender == getAddress(\"admin\") || \n msg.sender == getAddress(\"owner\"),\n \"permission-denied\"\n );\n _;\n }\n\n /// @dev Get the address from system registry \n /// @param _name (string)\n /// @return (address) Returns address based on role\n function getAddress(string memory _name) public view returns(address) {\n return registry[keccak256(abi.encodePacked(_name))];\n }\n\n /// @dev Set new address in system registry \n /// @param _name (string) Role name\n /// @param _userAddress (string) User Address\n function setAddress(string memory _name, address _userAddress) public isAdmin {\n registry[keccak256(abi.encodePacked(_name))] = _userAddress;\n emit LogSetAddress(_name, _userAddress);\n }\n}\n\n\n/// @title LogicRegistry\n/// @notice\n/// @dev LogicRegistry \ncontract LogicRegistry is AddressRegistry {\n\n event LogEnableDefaultLogic(address logicAddress);\n event LogEnableLogic(address logicAddress);\n event LogDisableLogic(address logicAddress);\n\n /// @notice Map of default proxy state\n mapping(address => bool) public defaultLogicProxies;\n \n /// @notice Map of logic proxy state\n mapping(address => bool) public logicProxies;\n\n /// @dev \n /// @param _logicAddress (address)\n /// @return (bool)\n function logic(address _logicAddress) public view returns (bool) {\n if (defaultLogicProxies[_logicAddress] || logicProxies[_logicAddress]) {\n return true;\n } else {\n return false;\n }\n }\n\n /// @dev Sets the default logic proxy to true\n /// default proxies mostly contains the logic for withdrawal of assets\n /// and can never be false to freely let user withdraw their assets\n /// @param _logicAddress (address)\n function enableDefaultLogic(address _logicAddress) public isAdmin {\n defaultLogicProxies[_logicAddress] = true;\n emit LogEnableDefaultLogic(_logicAddress);\n }\n\n /// @dev Enable logic proxy address\n /// @param _logicAddress (address)\n function enableLogic(address _logicAddress) public isAdmin {\n logicProxies[_logicAddress] = true;\n emit LogEnableLogic(_logicAddress);\n }\n\n /// @dev Disable logic proxy address\n /// @param _logicAddress (address)\n function disableLogic(address _logicAddress) public isAdmin {\n logicProxies[_logicAddress] = false;\n emit LogDisableLogic(_logicAddress);\n }\n\n}\n\n/**\n * @dev Deploys a new proxy instance and sets msg.sender as owner of proxy\n */\ncontract WalletRegistry is LogicRegistry {\n \n event Created(address indexed sender, address indexed owner, address proxy);\n event LogRecord(address indexed currentOwner, address indexed nextOwner, address proxy);\n \n /// @notice Address to UserWallet proxy map\n mapping(address => UserWallet) public proxies;\n \n /// @dev Deploys a new proxy instance and sets custom owner of proxy\n /// Throws if the owner already have a UserWallet\n /// @return proxy ()\n function build() public returns (UserWallet proxy) {\n proxy = build(msg.sender);\n }\n\n /// @dev update the proxy record whenever owner changed on any proxy\n /// Throws if msg.sender is not a proxy contract created via this contract\n /// @return proxy () UserWallet\n function build(address owner) public returns (UserWallet proxy) {\n require(proxies[owner] == UserWallet(0), \"multiple-proxy-per-user-not-allowed\");\n proxy = new UserWallet();\n proxies[address(this)] = proxy; // will be changed via record() in next line execution\n proxy.setOwner(owner);\n emit Created(msg.sender, owner, address(proxy));\n }\n\n /// @dev Transafers ownership\n /// @param _currentOwner (address) Current Owner\n /// @param _nextOwner (address) Next Owner\n function record(address _currentOwner, address _nextOwner) public {\n require(msg.sender == address(proxies[_currentOwner]), \"invalid-proxy-or-owner\");\n require(proxies[_nextOwner] == UserWallet(0), \"multiple-proxy-per-user-not-allowed\");\n proxies[_nextOwner] = proxies[_currentOwner];\n proxies[_currentOwner] = UserWallet(0);\n emit LogRecord(_currentOwner, _nextOwner, address(proxies[_nextOwner]));\n }\n\n}\n\n/// @title InstaRegistry\n/// @dev Initializing Registry\ncontract InstaRegistry is WalletRegistry {\n\n constructor() public {\n registry[keccak256(abi.encodePacked(\"admin\"))] = msg.sender;\n registry[keccak256(abi.encodePacked(\"owner\"))] = msg.sender;\n }\n}\n",
+ "UserWallet.sol": "pragma solidity ^0.5.2;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\n\n/**\n * @title RegistryInterface Interface \n */\ninterface RegistryInterface {\n function logic(address logicAddr) external view returns (bool);\n function record(address currentOwner, address nextOwner) external;\n}\n\n/**\n * @title Address Registry Record\n */\ncontract AddressRecord {\n\n /**\n * @dev address registry of system, logic and wallet addresses\n */\n address public registry;\n\n /**\n * @dev Throws if the logic is not authorised\n */\n modifier logicAuth(address logicAddr) {\n require(logicAddr != address(0), \"logic-proxy-address-required\");\n bool islogic = RegistryInterface(registry).logic(logicAddr);\n require(islogic, \"logic-not-authorised\");\n _;\n }\n\n}\n\n\n/**\n * @title User Auth\n */\ncontract UserAuth is AddressRecord {\n using SafeMath for uint;\n using SafeMath for uint256;\n\n event LogSetOwner(address indexed owner);\n address public owner;\n\n /**\n * @dev Throws if not called by owner or contract itself\n */\n modifier auth {\n require(isAuth(msg.sender), \"permission-denied\");\n _;\n }\n\n /**\n * @dev sets new owner\n */\n function setOwner(address nextOwner) public auth {\n RegistryInterface(registry).record(owner, nextOwner);\n owner = nextOwner;\n emit LogSetOwner(nextOwner);\n }\n\n /**\n * @dev checks if called by owner or contract itself\n * @param src is the address initiating the call\n */\n function isAuth(address src) public view returns (bool) {\n if (src == owner) {\n return true;\n } else if (src == address(this)) {\n return true;\n } else {\n return false;\n }\n }\n}\n\n\n/**\n * @dev logging the execute events\n */\ncontract UserNote {\n event LogNote(\n bytes4 indexed sig,\n address indexed guy,\n bytes32 indexed foo,\n bytes32 bar,\n uint wad,\n bytes fax\n );\n\n modifier note {\n bytes32 foo;\n bytes32 bar;\n assembly {\n foo := calldataload(4)\n bar := calldataload(36)\n }\n emit LogNote(\n msg.sig, \n msg.sender, \n foo, \n bar, \n msg.value,\n msg.data\n );\n _;\n }\n}\n\n\n/**\n * @title User Owned Contract Wallet\n */\ncontract UserWallet is UserAuth, UserNote {\n\n event LogExecute(address sender, address target, uint srcNum, uint sessionNum);\n\n /**\n * @dev sets the \"address registry\", owner's last activity, owner's active period and initial owner\n */\n constructor() public {\n registry = msg.sender;\n owner = msg.sender;\n }\n\n function() external payable {}\n\n /**\n * @dev Execute authorised calls via delegate call\n * @param _target logic proxy address\n * @param _data delegate call data\n * @param _srcNum to find the source\n * @param _sessionNum to find the session\n */\n function execute(\n address _target,\n bytes memory _data,\n uint _srcNum,\n uint _sessionNum\n ) \n public\n payable\n note\n auth\n logicAuth(_target)\n returns (bytes memory response)\n {\n emit LogExecute(\n msg.sender,\n _target,\n _srcNum,\n _sessionNum\n );\n \n // call contract in current context\n assembly {\n let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)\n let size := returndatasize\n\n response := mload(0x40)\n mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))\n mstore(response, size)\n returndatacopy(add(response, 0x20), 0, size)\n\n switch iszero(succeeded)\n case 1 {\n // throw if delegatecall failed\n revert(add(response, 0x20), size)\n }\n }\n }\n\n}",
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title SafeMath\n * @dev Unsigned math operations with safety checks that revert on error\n */\nlibrary SafeMath {\n /**\n * @dev Multiplies two unsigned integers, reverts on overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b);\n\n return c;\n }\n\n /**\n * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Adds two unsigned integers, reverts on overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a);\n\n return c;\n }\n\n /**\n * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),\n * reverts when dividing by zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b != 0);\n return a % b;\n }\n}\n"
+ },
+ "sourceTreeHashHex": "0xecdf79176b1e2561a89c76017fe06a755e8ab43349a64295e51f6317f5878a73",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/docs/InstaWallet.json b/docs/InstaWallet.json
new file mode 100644
index 0000000..a3f53fe
--- /dev/null
+++ b/docs/InstaWallet.json
@@ -0,0 +1,653 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "InstaWallet",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "activePeriod",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_guardian",
+ "type": "address"
+ }
+ ],
+ "name": "isGuardian",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ }
+ ],
+ "name": "isAuth",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "num",
+ "type": "uint256"
+ },
+ {
+ "name": "_manager",
+ "type": "address"
+ }
+ ],
+ "name": "setManager",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "managers",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [],
+ "name": "setOwner",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_activePeriod",
+ "type": "uint256"
+ }
+ ],
+ "name": "updateActivePeriod",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "logicAddr",
+ "type": "address"
+ }
+ ],
+ "name": "isLogicAuthorised",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ },
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "lastActivity",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "registry",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "claimOnwershipTime",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "gracePeriod",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
+ "name": "setOwnerOnce",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "num",
+ "type": "uint256"
+ },
+ {
+ "name": "_guardian",
+ "type": "address"
+ }
+ ],
+ "name": "setGuardian",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "nextOwner",
+ "type": "address"
+ }
+ ],
+ "name": "setPendingOwner",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "nextOwner",
+ "type": "address"
+ },
+ {
+ "name": "num",
+ "type": "uint256"
+ }
+ ],
+ "name": "setOwnerViaGuardian",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "pendingOwner",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_target",
+ "type": "address"
+ },
+ {
+ "name": "_data",
+ "type": "bytes"
+ },
+ {
+ "name": "srcNum",
+ "type": "uint256"
+ },
+ {
+ "name": "sessionNum",
+ "type": "uint256"
+ }
+ ],
+ "name": "execute",
+ "outputs": [
+ {
+ "name": "response",
+ "type": "bytes"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_manager",
+ "type": "address"
+ }
+ ],
+ "name": "isManager",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "guardians",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "fallback"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "srcNum",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "sessionNum",
+ "type": "uint256"
+ }
+ ],
+ "name": "LogExecute",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "sig",
+ "type": "bytes4"
+ },
+ {
+ "indexed": true,
+ "name": "guy",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "foo",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "name": "bar",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "name": "wad",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "fax",
+ "type": "bytes"
+ }
+ ],
+ "name": "LogNote",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "num",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "name": "prevManager",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "newManager",
+ "type": "address"
+ }
+ ],
+ "name": "LogSetManager",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "num",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "name": "prevGuardian",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "newGuardian",
+ "type": "address"
+ }
+ ],
+ "name": "LogSetGuardian",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "newActivePeriod",
+ "type": "uint256"
+ }
+ ],
+ "name": "LogNewActivePeriod",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "nextOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "guardian",
+ "type": "address"
+ }
+ ],
+ "name": "LogSetOwnerViaGuardian",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "setter",
+ "type": "address"
+ }
+ ],
+ "name": "LogSetOwner",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "pendingOwner",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "setter",
+ "type": "address"
+ }
+ ],
+ "name": "LogSetPendingOwner",
+ "type": "event"
+ }
+ ],
+ "devdoc": {
+ "methods": {
+ "constructor": {
+ "details": "sets the \"address registry\", owner's last activity, owner's active period and initial owner"
+ },
+ "execute(address,bytes,uint256,uint256)": {
+ "details": "execute authorised calls via delegate call",
+ "params": {
+ "_data": "delegate call data",
+ "_target": "logic proxy address",
+ "sessionNum": "to find the session",
+ "srcNum": "to find the source"
+ }
+ },
+ "isAuth(address)": {
+ "details": "checks if called by owner or contract itself",
+ "params": {
+ "src": "is the address initiating the call"
+ }
+ },
+ "isGuardian(address)": {
+ "details": "Throws if the msg.sender is not guardian"
+ },
+ "isLogicAuthorised(address)": {
+ "params": {
+ "logicAddr": "is the logic proxy contract address"
+ },
+ "return": "the true boolean for logic proxy if authorised otherwise false"
+ },
+ "isManager(address)": {
+ "details": "Throws if the msg.sender is not manager"
+ },
+ "setGuardian(uint256,address)": {
+ "details": "sets the guardian with assigned number (upto 5)",
+ "params": {
+ "_guardian": "is the new guardian address",
+ "num": "is the guardian assigned number"
+ }
+ },
+ "setManager(uint256,address)": {
+ "details": "sets the manager with assigned number (upto 5)",
+ "params": {
+ "_manager": "is the new admin address",
+ "num": "is the assigned number of manager"
+ }
+ },
+ "setOwner()": {
+ "details": "sets \"pending owner\" as real owner Throws if no \"pending owner\" Throws if called before 7 day after assigning \"pending owner\""
+ },
+ "setOwnerOnce(address)": {
+ "details": "sets owner and function is only be called once by registry on build() and this hack verifiy the contract on etherscan automatically as no dynamic owner address is sent in the constructor",
+ "params": {
+ "_owner": "is the new owner of this contract wallet"
+ }
+ },
+ "setOwnerViaGuardian(address,uint256)": {
+ "details": "guardians can set \"owner\" after owner stay inactive for minimum \"activePeriod\"",
+ "params": {
+ "nextOwner": "is the new owner",
+ "num": "is the assigned guardian number"
+ }
+ },
+ "setPendingOwner(address)": {
+ "details": "sets the \"pending owner\" and provide 3 days grace period to set the new owner via setOwner() Throws if called before 10 (i.e. 7 + 3) day after assigning \"pending owner\"",
+ "params": {
+ "nextOwner": "is the assigned \"pending owner\""
+ }
+ },
+ "updateActivePeriod(uint256)": {
+ "details": "sets the guardian with assigned number (upto 5)",
+ "params": {
+ "_activePeriod": "is the period when guardians have no rights to dethrone the owner"
+ }
+ }
+ },
+ "title": "User Owned Contract Wallet"
+ }
+ },
+ "sources": {
+ "Reference/InstaWallet.sol": {
+ "id": 0
+ },
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": {
+ "id": 2
+ }
+ },
+ "sourceCodes": {
+ "Reference/InstaWallet.sol": "// This Auth Model also includes UserWallet Logics\n// TODO => make it single Auth code for future launch where this Auth Contract will be the owner of UserWallet\n\npragma solidity ^0.5.2;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\n\n/**\n * @title AddressRegistryInterface Interface \n */\ninterface AddressRegistryInterface {\n function isLogicAuth(address logicAddr) external view returns (bool, bool);\n function updateProxyRecord(address currentOwner, address nextOwner) external;\n function guardianEnabled() external view returns (bool);\n function managerEnabled() external view returns (bool);\n}\n\n/**\n * @title UserWallet Interface\n */\n// interface UserWalletInterface {\n// get the wallet address based on the owner of this wallet\n// and use execute interface from main UserWallet to call execute on this contract\n// }\n\n\n/**\n * @title Address Registry Record\n */\ncontract AddressRecord {\n /**\n * @dev address registry of system, logic and wallet addresses\n */\n address public registry;\n\n /**\n * @param logicAddr is the logic proxy contract address\n * @return the true boolean for logic proxy if authorised otherwise false\n */\n function isLogicAuthorised(address logicAddr) public view returns (bool, bool) {\n AddressRegistryInterface logicProxy = AddressRegistryInterface(registry);\n (bool isLogic, bool isDefault) = logicProxy.isLogicAuth(logicAddr);\n return (isLogic, isDefault);\n }\n\n /**\n * @dev this updates the internal proxy ownership on \"registry\" contract\n * @param currentOwner is the current owner\n * @param nextOwner is the new assigned owner\n */\n function setProxyRecordOwner(address currentOwner, address nextOwner) internal {\n AddressRegistryInterface initCall = AddressRegistryInterface(registry);\n initCall.updateProxyRecord(currentOwner, nextOwner);\n }\n\n}\n\n\n/**\n * @title User Auth\n */\ncontract UserAuth is AddressRecord {\n using SafeMath for uint;\n using SafeMath for uint256;\n\n event LogSetOwner(address indexed owner, address setter);\n event LogSetPendingOwner(address indexed pendingOwner, address setter);\n address public owner;\n address public pendingOwner;\n uint public claimOnwershipTime; // now + 7 days\n uint public gracePeriod; // to set the new owner - defaults to 3 days\n\n /**\n * @dev defines the \"proxy registry\" contract and sets the owner\n */\n constructor() public {\n gracePeriod = 3 days;\n }\n\n /**\n * @dev Throws if not called by owner or contract itself\n */\n modifier auth {\n require(isAuth(msg.sender), \"permission-denied\");\n _;\n }\n\n /**\n * @dev sets the \"pending owner\" and provide 3 days grace period to set the new owner via setOwner()\n * Throws if called before 10 (i.e. 7 + 3) day after assigning \"pending owner\"\n * @param nextOwner is the assigned \"pending owner\"\n */\n function setPendingOwner(address nextOwner) public auth {\n require(block.timestamp > claimOnwershipTime.add(gracePeriod), \"owner-is-still-pending\");\n pendingOwner = nextOwner;\n claimOnwershipTime = block.timestamp.add(7 days);\n emit LogSetPendingOwner(nextOwner, msg.sender);\n }\n\n /**\n * @dev sets \"pending owner\" as real owner\n * Throws if no \"pending owner\"\n * Throws if called before 7 day after assigning \"pending owner\"\n */\n function setOwner() public {\n require(pendingOwner != address(0), \"no-pending-address\");\n require(block.timestamp > claimOnwershipTime, \"owner-is-still-pending\");\n setProxyRecordOwner(owner, pendingOwner);\n owner = pendingOwner;\n pendingOwner = address(0);\n emit LogSetOwner(owner, msg.sender);\n }\n\n /**\n * @dev sets owner and function is only be called once by registry on build()\n * and this hack verifiy the contract on etherscan automatically\n * as no dynamic owner address is sent in the constructor\n * @param _owner is the new owner of this contract wallet\n */\n function setOwnerOnce(address _owner) public auth {\n require(msg.sender == registry, \"permission-denied\");\n owner = _owner;\n emit LogSetOwner(owner, msg.sender);\n }\n\n /**\n * @dev checks if called by owner or contract itself\n * @param src is the address initiating the call\n */\n function isAuth(address src) public view returns (bool) {\n if (src == address(this)) {\n return true;\n } else if (src == owner) {\n return true;\n } else {\n return false;\n }\n }\n\n}\n\n/**\n * @title User Guardians\n * @dev the assigned guardian addresses (upto 3) can set new owners\n * but only after certain period of owner's inactivity (i.e. activePeriod)\n */\ncontract UserGuardian is UserAuth {\n event LogSetGuardian(uint num, address indexed prevGuardian, address indexed newGuardian);\n event LogNewActivePeriod(uint newActivePeriod);\n event LogSetOwnerViaGuardian(address nextOwner, address indexed guardian);\n\n mapping(uint => address) public guardians;\n uint public lastActivity; // time when called \"execute\" last time\n uint public activePeriod; // the period over lastActivity when guardians have no rights\n\n /**\n * @dev Throws if guardians not enabled by system admin\n */\n modifier isGuardianEnabled() {\n AddressRegistryInterface initCall = AddressRegistryInterface(registry);\n require(initCall.guardianEnabled(), \"guardian-not-enabled\");\n _;\n }\n\n /**\n * @dev guardians can set \"owner\" after owner stay inactive for minimum \"activePeriod\"\n * @param nextOwner is the new owner\n * @param num is the assigned guardian number\n */\n function setOwnerViaGuardian(address nextOwner, uint num) public isGuardianEnabled {\n require(isGuardian(msg.sender), \"not-guardian\");\n require(msg.sender == guardians[num], \"permission-denied\");\n require(block.timestamp > lastActivity.add(activePeriod), \"active-period-not-over\");\n owner = nextOwner;\n emit LogSetOwnerViaGuardian(nextOwner, guardians[num]);\n }\n\n /**\n * @dev sets the guardian with assigned number (upto 5)\n * @param num is the guardian assigned number\n * @param _guardian is the new guardian address\n */\n function setGuardian(uint num, address _guardian) public auth isGuardianEnabled {\n require(num > 0 && num < 6, \"guardians-cant-exceed-three\");\n emit LogSetGuardian(num, guardians[num], _guardian);\n guardians[num] = _guardian;\n }\n\n /**\n * @dev sets the guardian with assigned number (upto 5)\n * @param _activePeriod is the period when guardians have no rights to dethrone the owner\n */\n function updateActivePeriod(uint _activePeriod) public auth isGuardianEnabled {\n activePeriod = _activePeriod;\n emit LogNewActivePeriod(_activePeriod);\n }\n\n /**\n * @dev Throws if the msg.sender is not guardian\n */\n function isGuardian(address _guardian) public view returns (bool) {\n if (_guardian == guardians[1] || _guardian == guardians[2] || _guardian == guardians[3] || _guardian == guardians[4] || _guardian == guardians[5]) {\n return true;\n } else {\n return false;\n }\n }\n\n}\n\n/**\n * @title User Manager\n * @dev the assigned manager addresses (upto 3) can manage the wealth in contract to contract fashion\n * but can't withdraw the assets on their personal address\n */\ncontract UserManager is UserGuardian {\n event LogSetManager(uint num, address indexed prevManager, address indexed newManager);\n\n mapping(uint => address) public managers;\n\n /**\n * @dev Throws if manager not enabled by system admin\n */\n modifier isManagerEnabled() {\n AddressRegistryInterface initCall = AddressRegistryInterface(registry);\n require(initCall.managerEnabled(), \"admin-not-enabled\");\n _;\n }\n\n /**\n * @dev sets the manager with assigned number (upto 5)\n * @param num is the assigned number of manager\n * @param _manager is the new admin address\n */\n function setManager(uint num, address _manager) public auth isManagerEnabled {\n require(num > 0 && num < 6, \"guardians-cant-exceed-three\");\n emit LogSetManager(num, managers[num], _manager);\n managers[num] = _manager;\n }\n\n /**\n * @dev Throws if the msg.sender is not manager\n */\n function isManager(address _manager) public view returns (bool) {\n if (_manager == managers[1] || _manager == managers[2] || _manager == managers[3] || _manager == managers[4] || _manager == managers[5]) {\n return true;\n } else {\n return false;\n }\n }\n\n}\n\n/**\n * @dev logging the execute events\n */\ncontract UserNote {\n event LogNote(bytes4 indexed sig, address indexed guy, bytes32 indexed foo, bytes32 bar, uint wad, bytes fax);\n\n modifier note {\n bytes32 foo;\n bytes32 bar;\n assembly {\n foo := calldataload(4)\n bar := calldataload(36)\n }\n emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);\n _;\n }\n}\n\n/**\n * @title User Owned Contract Wallet\n */\ncontract InstaWallet is UserManager, UserNote {\n event LogExecute(address sender, address target, uint srcNum, uint sessionNum);\n\n /**\n * @dev sets the \"address registry\", owner's last activity, owner's active period and initial owner\n */\n constructor() public {\n registry = msg.sender;\n owner = msg.sender; // will be changed in initial call itself\n lastActivity = block.timestamp;\n activePeriod = 30 days; // default on deployment and changeable afterwards\n }\n\n function() external payable {}\n\n /**\n * @dev execute authorised calls via delegate call\n * @param _target logic proxy address\n * @param _data delegate call data\n * @param srcNum to find the source\n * @param sessionNum to find the session\n */\n function execute(address _target, bytes memory _data, uint srcNum, uint sessionNum)\n public\n payable\n note\n isExecutable(_target)\n returns (bytes memory response)\n {\n lastActivity = block.timestamp;\n emit LogExecute(msg.sender, _target, srcNum, sessionNum);\n\n // call contract in current context\n assembly {\n let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)\n let size := returndatasize\n\n response := mload(0x40)\n mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))\n mstore(response, size)\n returndatacopy(add(response, 0x20), 0, size)\n\n switch iszero(succeeded)\n case 1 {\n // throw if delegatecall failed\n revert(add(response, 0x20), size)\n }\n }\n }\n\n /**\n * @dev checks if the proxy is authorised\n * and if the sender is owner or contract itself or manager\n * and if manager then Throws if target is default proxy address\n */\n modifier isExecutable(address proxyTarget) {\n require(proxyTarget != address(0), \"logic-proxy-address-required\");\n\n (bool isLogic, bool isDefault) = isLogicAuthorised(proxyTarget);\n require(isLogic, \"logic-proxy-address-not-allowed\");\n\n bool enact = false;\n if (isAuth(msg.sender)) {\n enact = true;\n } else if (isManager(msg.sender) && !isDefault) {\n enact = true;\n }\n\n require(enact, \"not-executable\");\n _;\n }\n\n}\n",
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title SafeMath\n * @dev Unsigned math operations with safety checks that revert on error\n */\nlibrary SafeMath {\n /**\n * @dev Multiplies two unsigned integers, reverts on overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b);\n\n return c;\n }\n\n /**\n * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Adds two unsigned integers, reverts on overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a);\n\n return c;\n }\n\n /**\n * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),\n * reverts when dividing by zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b != 0);\n return a % b;\n }\n}\n"
+ },
+ "sourceTreeHashHex": "0x10f370d45ab729caa91aca6feb8c7efd3fd8cd0d3df7fe0c19b3eca939b6fd82",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/docs/Kyber.json b/docs/Kyber.json
new file mode 100644
index 0000000..86b60a7
--- /dev/null
+++ b/docs/Kyber.json
@@ -0,0 +1,123 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "Kyber",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "srcQty",
+ "type": "uint256"
+ }
+ ],
+ "name": "getExpectedRate",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ },
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "srcAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "destAddress",
+ "type": "address"
+ },
+ {
+ "name": "maxDestAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "minConversionRate",
+ "type": "uint256"
+ },
+ {
+ "name": "walletId",
+ "type": "address"
+ }
+ ],
+ "name": "trade",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ }
+ ],
+ "devdoc": {
+ "methods": {}
+ }
+ },
+ "sources": {
+ "Bin/Kyber.sol": {
+ "id": 0
+ },
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": {
+ "id": 8
+ },
+ "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol": {
+ "id": 9
+ }
+ },
+ "sourceCodes": {
+ "Bin/Kyber.sol": "pragma solidity ^0.5.2;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\";\n\ninterface AddressRegistry {\n function getAddr(string calldata name) external view returns (address);\n}\n\ninterface Kyber {\n // Kyber's trade function\n function trade(\n address src,\n uint srcAmount,\n address dest,\n address destAddress,\n uint maxDestAmount,\n uint minConversionRate,\n address walletId\n ) external payable returns (uint);\n // Kyber's Get expected Rate function\n function getExpectedRate(address src, address dest, uint srcQty) external view returns (uint, uint);\n}\n\ncontract Registry {\n address public addressRegistry;\n modifier onlyAdmin() {\n require(msg.sender == _getAddress(\"admin\"), \"Permission Denied\");\n _;\n }\n function _getAddress(string memory name) internal view returns (address) {\n AddressRegistry addrReg = AddressRegistry(addressRegistry);\n return addrReg.getAddr(name);\n }\n}\n\ncontract helper is Registry {\n function _getToken(address trader, address src, uint srcAmt, address eth) internal returns (uint ethQty) {\n if (src == eth) {\n require(msg.value == srcAmt, \"Invalid Operation\");\n ethQty = srcAmt;\n } else {\n IERC20 tokenFunctions = IERC20(src);\n tokenFunctions.transferFrom(trader, address(this), srcAmt);\n ethQty = 0;\n }\n }\n\n // approve to Kyber Proxy contract\n function _approveKyber(address token) internal returns (bool) {\n address kyberProxy = _getAddress(\"kyber\");\n IERC20 tokenFunctions = IERC20(token);\n return tokenFunctions.approve(kyberProxy, uint(0 - 1));\n }\n\n // Check Allowance to Kyber Proxy contract\n function _allowanceKyber(address token) internal view returns (uint) {\n address kyberProxy = _getAddress(\"kyber\");\n IERC20 tokenFunctions = IERC20(token);\n return tokenFunctions.allowance(address(this), kyberProxy);\n }\n\n // Check allowance, if not approve\n function _allowanceApproveKyber(address token) internal returns (bool) {\n uint allowanceGiven = _allowanceKyber(token);\n if (allowanceGiven == 0) {\n return _approveKyber(token);\n } else {\n return true;\n }\n }\n}\n\ncontract Trade is helper {\n using SafeMath for uint;\n\n event KyberTrade(address src, uint srcAmt, address dest, uint destAmt, address beneficiary, uint minConversionRate, address affiliate);\n\n function getExpectedRateKyber(address src, address dest, uint srcAmt) public view returns (uint, uint) {\n Kyber kyberFunctions = Kyber(_getAddress(\"kyber\"));\n return kyberFunctions.getExpectedRate(src, dest, srcAmt);\n }\n\n /**\n * @dev Kyber's trade when token to sell Amount fixed\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param srcAmt - amount of token for sell\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param minDestAmt - min amount of token to buy (slippage)\n */\n function tradeSrcKyber(\n address src, // token to sell\n uint srcAmt, // amount of token for sell\n address dest, // token to buy\n uint minDestAmt // minimum slippage rate\n ) public payable returns (uint tokensBought) {\n address eth = _getAddress(\"eth\");\n uint ethQty = _getToken(msg.sender, src, srcAmt, eth);\n\n if (src != eth) {\n _allowanceApproveKyber(src);\n }\n\n // Interacting with Kyber Proxy Contract\n Kyber kyberFunctions = Kyber(_getAddress(\"kyber\"));\n tokensBought = kyberFunctions.trade.value(ethQty)(src, srcAmt, dest, msg.sender, uint(0 - 1), minDestAmt, _getAddress(\"admin\"));\n\n emit KyberTrade(src, srcAmt, dest, tokensBought, msg.sender, minDestAmt, _getAddress(\"admin\"));\n\n }\n\n /**\n * @dev Kyber's trade when token to sell Amount fixed\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param maxSrcAmt - max amount of token for sell (slippage)\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param destAmt - amount of token to buy\n */\n function tradeDestKyber(\n address src, // token to sell\n uint maxSrcAmt, // amount of token for sell\n address dest, // token to buy\n uint destAmt // minimum slippage rate\n ) public payable returns (uint tokensBought) {\n address eth = _getAddress(\"eth\");\n uint ethQty = _getToken(msg.sender, src, maxSrcAmt, eth);\n\n if (src != eth) {\n _allowanceApproveKyber(src);\n }\n\n // Interacting with Kyber Proxy Contract\n Kyber kyberFunctions = Kyber(_getAddress(\"kyber\"));\n tokensBought = kyberFunctions.trade.value(ethQty)(src, maxSrcAmt, dest, msg.sender, destAmt, destAmt - 1, _getAddress(\"admin\"));\n\n // maxDestAmt usecase implementated\n if (src == eth && address(this).balance > 0) {\n msg.sender.transfer(address(this).balance);\n } else if (src != eth) {\n // as there is no balanceOf of eth\n IERC20 srcTkn = IERC20(src);\n uint srcBal = srcTkn.balanceOf(address(this));\n if (srcBal > 0) {\n srcTkn.transfer(msg.sender, srcBal);\n }\n }\n\n emit KyberTrade(src, maxSrcAmt, dest, tokensBought, msg.sender, destAmt, _getAddress(\"admin\"));\n\n }\n\n}\n\n\ncontract InstaKyber is Trade {\n constructor(address rAddr) public {\n addressRegistry = rAddr;\n }\n\n function() external payable {}\n}\n",
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title SafeMath\n * @dev Unsigned math operations with safety checks that revert on error\n */\nlibrary SafeMath {\n /**\n * @dev Multiplies two unsigned integers, reverts on overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b);\n\n return c;\n }\n\n /**\n * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Adds two unsigned integers, reverts on overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a);\n\n return c;\n }\n\n /**\n * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),\n * reverts when dividing by zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b != 0);\n return a % b;\n }\n}\n",
+ "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title ERC20 interface\n * @dev see https://eips.ethereum.org/EIPS/eip-20\n */\ninterface IERC20 {\n function transfer(address to, uint256 value) external returns (bool);\n\n function approve(address spender, uint256 value) external returns (bool);\n\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address who) external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
+ },
+ "sourceTreeHashHex": "0xaa360f8e2c65e34e3697c5f348f1f27a6f75e94c847cf9c08035c8bdd04eb43f",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/docs/Migrations.json b/docs/Migrations.json
new file mode 100644
index 0000000..3c7dc3c
--- /dev/null
+++ b/docs/Migrations.json
@@ -0,0 +1,103 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "Migrations",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_newAddress",
+ "type": "address"
+ }
+ ],
+ "name": "upgrade",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "last_completed_migration",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "completed",
+ "type": "uint256"
+ }
+ ],
+ "name": "setCompleted",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ }
+ ],
+ "devdoc": {
+ "methods": {}
+ }
+ },
+ "sources": {
+ "Migrations.sol": {
+ "id": 2
+ }
+ },
+ "sourceCodes": {
+ "Migrations.sol": "pragma solidity ^0.5.2;\n\n/* solium-disable mixedcase */\ncontract Migrations {\n address public owner;\n uint public last_completed_migration;\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n constructor() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) public restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address _newAddress) public restricted {\n Migrations upgraded = Migrations(_newAddress);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n\n/* solium-enable mixedcase */\n\n"
+ },
+ "sourceTreeHashHex": "0x0f2d82013d4aed92814a1528a406877135ec86becc13d0656d0c375d2cee8715",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/docs/Ownable.json b/docs/Ownable.json
new file mode 100644
index 0000000..82fc926
--- /dev/null
+++ b/docs/Ownable.json
@@ -0,0 +1,104 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "Ownable",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "previousOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "OwnershipTransferred",
+ "type": "event"
+ }
+ ],
+ "devdoc": {
+ "details": "The Ownable contract has an owner address, and provides basic authorization control functions, this simplifies the implementation of \"user permissions\".",
+ "methods": {
+ "constructor": {
+ "details": "The Ownable constructor sets the original `owner` of the contract to the sender account."
+ },
+ "transferOwnership(address)": {
+ "details": "Allows the current owner to transfer control of the contract to a newOwner.",
+ "params": {
+ "newOwner": "The address to transfer ownership to."
+ }
+ }
+ },
+ "title": "Ownable"
+ }
+ },
+ "sources": {
+ "Ownable.sol": {
+ "id": 3
+ }
+ },
+ "sourceCodes": {
+ "Ownable.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title Ownable\n * @dev The Ownable contract has an owner address, and provides basic authorization control\n * functions, this simplifies the implementation of \"user permissions\".\n */\ncontract Ownable {\n address public owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev The Ownable constructor sets the original `owner` of the contract to the sender\n * account.\n */\n constructor() public {\n owner = msg.sender;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(msg.sender == owner, \"Only owner accessible\");\n _;\n }\n\n /**\n * @dev Allows the current owner to transfer control of the contract to a newOwner.\n * @param newOwner The address to transfer ownership to.\n */\n function transferOwnership(address newOwner) public onlyOwner {\n require(newOwner != address(0), \"Address not equal to zero\");\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n }\n}\n"
+ },
+ "sourceTreeHashHex": "0xae5de39110dc28711c6edf34bdad44412eaf72392d1e8fe47add94c996022218",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/docs/Trade.json b/docs/Trade.json
new file mode 100644
index 0000000..d0da797
--- /dev/null
+++ b/docs/Trade.json
@@ -0,0 +1,326 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "Trade",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "srcAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "minDestAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dexNum",
+ "type": "uint256"
+ }
+ ],
+ "name": "tradeFromSrc",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "maxSrcAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "destAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "name": "tradeDestUniswap",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "srcAmt",
+ "type": "uint256"
+ }
+ ],
+ "name": "getRateFromSrc",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ },
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "maxSrcAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "destAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dexNum",
+ "type": "uint256"
+ }
+ ],
+ "name": "tradeFromDest",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "srcAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "minDestAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "name": "tradeSrcUniswap",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "srcAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "minDestAmt",
+ "type": "uint256"
+ }
+ ],
+ "name": "tradeSrcKyber",
+ "outputs": [
+ {
+ "name": "tokensBought",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "maxSrcAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "destAmt",
+ "type": "uint256"
+ }
+ ],
+ "name": "tradeDestKyber",
+ "outputs": [
+ {
+ "name": "tokensBought",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "addressRegistry",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "devdoc": {
+ "methods": {
+ "tradeDestUniswap(address,uint256,address,uint256,uint256)": {
+ "details": "Uniswap's trade when token to buy Amount fixed",
+ "params": {
+ "deadline": "- time for this transaction to be valid",
+ "dest": "- Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "destAmt": "- amount of token to buy",
+ "maxSrcAmt": "- max amount of token for sell (slippage)",
+ "src": "- Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")"
+ }
+ },
+ "tradeSrcKyber(address,uint256,address,uint256)": {
+ "details": "Kyber's trade when token to sell Amount fixed",
+ "params": {
+ "dest": "- Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "minDestAmt": "- min amount of token to buy (slippage)",
+ "src": "- Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "srcAmt": "- amount of token for sell"
+ }
+ },
+ "tradeSrcUniswap(address,uint256,address,uint256,uint256)": {
+ "details": "Uniswap's trade when token to sell Amount fixed",
+ "params": {
+ "deadline": "- time for this transaction to be valid",
+ "dest": "- Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "minDestAmt": "- min amount of token to buy (slippage)",
+ "src": "- Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "srcAmt": "- amount of token for sell"
+ }
+ }
+ }
+ }
+ },
+ "sources": {
+ "Bin/Trade.sol": {
+ "id": 1
+ },
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": {
+ "id": 8
+ },
+ "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol": {
+ "id": 9
+ }
+ },
+ "sourceCodes": {
+ "Bin/Trade.sol": "pragma solidity ^0.5.2;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\";\n\ninterface AddressRegistry {\n function getAddr(string calldata name) external view returns (address);\n}\n\n// Kyber's contract Interface\ninterface KyberExchange {\n // Kyber's trade function\n function trade(\n address src,\n uint srcAmount,\n address dest,\n address destAddress,\n uint maxDestAmount,\n uint minConversionRate,\n address walletId\n ) external payable returns (uint);\n // Kyber's Get expected Rate function\n function getExpectedRate(address src, address dest, uint srcQty) external view returns (uint, uint);\n}\n\n// Uniswap's factory Interface\ninterface UniswapFactory {\n // get exchange from token's address\n function getExchange(address token) external view returns (address exchange);\n}\n\n// Uniswap's exchange Interface\ninterface UniswapExchange {\n // Get Prices\n function getEthToTokenInputPrice(uint256 eth_sold) external view returns (uint256 tokens_bought);\n function getEthToTokenOutputPrice(uint256 tokens_bought) external view returns (uint256 eth_sold);\n function getTokenToEthInputPrice(uint256 tokens_sold) external view returns (uint256 eth_bought);\n function getTokenToEthOutputPrice(uint256 eth_bought) external view returns (uint256 tokens_sold);\n // Trade ETH to ERC20\n function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient)\n external\n payable\n returns (uint256 tokens_bought);\n function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient)\n external\n payable\n returns (uint256 eth_sold);\n // Trade ERC20 to ETH\n function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline, address recipient)\n external\n returns (uint256 eth_bought);\n function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient)\n external\n returns (uint256 tokens_sold);\n // Trade ERC20 to ERC20\n function tokenToTokenTransferInput(\n uint256 tokens_sold,\n uint256 min_tokens_bought,\n uint256 min_eth_bought,\n uint256 deadline,\n address recipient,\n address token_addr\n ) external returns (uint256 tokens_bought);\n function tokenToTokenTransferOutput(\n uint256 tokens_bought,\n uint256 max_tokens_sold,\n uint256 max_eth_sold,\n uint256 deadline,\n address recipient,\n address token_addr\n ) external returns (uint256 tokens_sold);\n}\n\ncontract Registry {\n address public addressRegistry;\n modifier onlyAdmin() {\n require(msg.sender == _getAddress(\"admin\"), \"Permission Denied\");\n _;\n }\n function _getAddress(string memory name) internal view returns (address) {\n AddressRegistry addrReg = AddressRegistry(addressRegistry);\n return addrReg.getAddr(name);\n }\n}\n\n// common stuffs in Kyber and Uniswap's trade\ncontract CommonStuffs {\n using SafeMath for uint;\n\n // Check required ETH Quantity to execute code\n function _getToken(address trader, address src, uint srcAmt, address eth) internal returns (uint ethQty) {\n if (src == eth) {\n require(msg.value == srcAmt, \"Invalid Operation\");\n ethQty = srcAmt;\n } else {\n IERC20 tokenFunctions = IERC20(src);\n tokenFunctions.transferFrom(trader, address(this), srcAmt);\n ethQty = 0;\n }\n }\n\n function _approveDexes(address token, address dexToApprove) internal returns (bool) {\n IERC20 tokenFunctions = IERC20(token);\n return tokenFunctions.approve(dexToApprove, uint(0 - 1));\n }\n\n function _allowance(address token, address spender) internal view returns (uint) {\n IERC20 tokenFunctions = IERC20(token);\n return tokenFunctions.allowance(address(this), spender);\n }\n\n}\n\n// Kyber's dex functions\ncontract Kyber is Registry, CommonStuffs {\n function getExpectedRateKyber(address src, address dest, uint srcAmt) internal view returns (uint) {\n KyberExchange kyberFunctions = KyberExchange(_getAddress(\"kyber\"));\n uint expectedRate;\n (expectedRate, ) = kyberFunctions.getExpectedRate(src, dest, srcAmt);\n uint kyberRate = expectedRate.mul(srcAmt);\n return kyberRate;\n }\n\n // approve to Kyber Proxy contract\n function _approveKyber(address token) internal returns (bool) {\n address kyberProxy = _getAddress(\"kyber\");\n return _approveDexes(token, kyberProxy);\n }\n\n // Check Allowance to Kyber Proxy contract\n function _allowanceKyber(address token) internal view returns (uint) {\n address kyberProxy = _getAddress(\"kyber\");\n return _allowance(token, kyberProxy);\n }\n\n function _allowanceApproveKyber(address token) internal returns (bool) {\n uint allowanceGiven = _allowanceKyber(token);\n if (allowanceGiven == 0) {\n return _approveKyber(token);\n } else {\n return true;\n }\n }\n\n /**\n * @dev Kyber's trade when token to sell Amount fixed\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param srcAmt - amount of token for sell\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param minDestAmt - min amount of token to buy (slippage)\n */\n function tradeSrcKyber(\n address src, // token to sell\n uint srcAmt, // amount of token for sell\n address dest, // token to buy\n uint minDestAmt // minimum slippage rate\n ) public payable returns (uint tokensBought) {\n address eth = _getAddress(\"eth\");\n uint ethQty = _getToken(msg.sender, src, srcAmt, eth);\n\n // Interacting with Kyber Proxy Contract\n KyberExchange kyberFunctions = KyberExchange(_getAddress(\"kyber\"));\n tokensBought = kyberFunctions.trade.value(ethQty)(src, srcAmt, dest, msg.sender, uint(0 - 1), minDestAmt, _getAddress(\"admin\"));\n\n }\n\n function tradeDestKyber(\n address src, // token to sell\n uint maxSrcAmt, // amount of token for sell\n address dest, // token to buy\n uint destAmt // minimum slippage rate\n ) public payable returns (uint tokensBought) {\n address eth = _getAddress(\"eth\");\n uint ethQty = _getToken(msg.sender, src, maxSrcAmt, eth);\n\n // Interacting with Kyber Proxy Contract\n KyberExchange kyberFunctions = KyberExchange(_getAddress(\"kyber\"));\n tokensBought = kyberFunctions.trade.value(ethQty)(src, maxSrcAmt, dest, msg.sender, destAmt, destAmt, _getAddress(\"admin\"));\n\n // maxDestAmt usecase implementated\n if (src == eth && address(this).balance > 0) {\n msg.sender.transfer(address(this).balance);\n } else if (src != eth) {\n // as there is no balanceOf of eth\n IERC20 srcTkn = IERC20(src);\n uint srcBal = srcTkn.balanceOf(address(this));\n if (srcBal > 0) {\n srcTkn.transfer(msg.sender, srcBal);\n }\n }\n\n }\n\n}\n\n// Uinswap's dex functions\ncontract Uniswap is Registry, CommonStuffs {\n // Get Uniswap's Exchange address from Factory Contract\n function _getExchangeAddress(address _token) internal view returns (address) {\n UniswapFactory uniswapMain = UniswapFactory(_getAddress(\"uniswap\"));\n return uniswapMain.getExchange(_token);\n }\n\n // Approve Uniswap's Exchanges\n function _approveUniswapExchange(address token) internal returns (bool) {\n address uniswapExchange = _getExchangeAddress(token);\n return _approveDexes(token, uniswapExchange);\n }\n\n // Check Allowance to Uniswap's Exchanges\n function _allowanceUniswapExchange(address token) internal view returns (uint) {\n address uniswapExchange = _getExchangeAddress(token);\n return _allowance(token, uniswapExchange);\n }\n\n function _allowanceApproveUniswap(address token) internal returns (bool) {\n uint allowanceGiven = _allowanceUniswapExchange(token);\n if (allowanceGiven == 0) {\n return _approveUniswapExchange(token);\n } else {\n return true;\n }\n }\n\n /**\n * @dev Uniswap's get expected rate from source\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param srcAmt - source token amount\n */\n function getExpectedRateSrcUniswap(address src, address dest, uint srcAmt) internal view returns (uint256) {\n address eth = _getAddress(\"eth\");\n if (src == eth) {\n // define uniswap exchange with dest address\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));\n return exchangeContract.getEthToTokenInputPrice(srcAmt);\n } else if (dest == eth) {\n // define uniswap exchange with src address\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n return exchangeContract.getTokenToEthInputPrice(srcAmt);\n } else {\n UniswapExchange exchangeContractSrc = UniswapExchange(_getExchangeAddress(src));\n UniswapExchange exchangeContractDest = UniswapExchange(_getExchangeAddress(dest));\n uint ethQty = exchangeContractSrc.getTokenToEthInputPrice(srcAmt);\n return exchangeContractDest.getEthToTokenInputPrice(ethQty);\n }\n }\n\n /**\n * @dev Uniswap's get expected rate from dest\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param destAmt - dest token amount\n */\n function getExpectedRateDestUniswap(address src, address dest, uint destAmt) internal view returns (uint256) {\n address eth = _getAddress(\"eth\");\n if (src == eth) {\n // define uniswap exchange with dest address\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));\n return exchangeContract.getEthToTokenOutputPrice(destAmt);\n } else if (dest == eth) {\n // define uniswap exchange with src address\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n return exchangeContract.getTokenToEthOutputPrice(destAmt);\n } else {\n UniswapExchange exchangeContractSrc = UniswapExchange(_getExchangeAddress(src));\n UniswapExchange exchangeContractDest = UniswapExchange(_getExchangeAddress(dest));\n uint ethQty = exchangeContractDest.getTokenToEthInputPrice(destAmt);\n return exchangeContractSrc.getEthToTokenInputPrice(ethQty);\n }\n }\n\n /**\n * @dev Uniswap's trade when token to sell Amount fixed\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param srcAmt - amount of token for sell\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param minDestAmt - min amount of token to buy (slippage)\n * @param deadline - time for this transaction to be valid\n */\n function tradeSrcUniswap(address src, uint srcAmt, address dest, uint minDestAmt, uint deadline) public payable returns (uint) {\n address eth = _getAddress(\"eth\");\n uint ethQty = _getToken(msg.sender, src, srcAmt, eth);\n\n if (src == eth) {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));\n uint tokensBought = exchangeContract.ethToTokenTransferInput.value(ethQty)(minDestAmt, deadline, msg.sender);\n return tokensBought;\n } else if (dest == eth) {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n uint ethBought = exchangeContract.tokenToEthTransferInput(srcAmt, minDestAmt, deadline, msg.sender);\n return ethBought;\n } else {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n uint tokensBought = exchangeContract.tokenToTokenTransferInput(srcAmt, minDestAmt, uint(0), deadline, msg.sender, dest);\n return tokensBought;\n }\n }\n\n /**\n * @dev Uniswap's trade when token to buy Amount fixed\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param maxSrcAmt - max amount of token for sell (slippage)\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param destAmt - amount of token to buy\n * @param deadline - time for this transaction to be valid\n */\n function tradeDestUniswap(address src, uint maxSrcAmt, address dest, uint destAmt, uint deadline) public payable returns (uint) {\n address eth = _getAddress(\"eth\");\n uint ethQty = _getToken(msg.sender, src, maxSrcAmt, eth);\n\n if (src == eth) {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));\n uint ethSold = exchangeContract.ethToTokenTransferOutput.value(ethQty)(destAmt, deadline, msg.sender);\n if (ethSold < ethQty) {\n uint srcToReturn = ethQty - ethSold;\n msg.sender.transfer(srcToReturn);\n }\n return ethSold;\n } else if (dest == eth) {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n uint tokensSold = exchangeContract.tokenToEthTransferOutput(destAmt, maxSrcAmt, deadline, msg.sender);\n if (tokensSold < maxSrcAmt) {\n IERC20 srcTkn = IERC20(src);\n uint srcToReturn = maxSrcAmt - tokensSold;\n srcTkn.transfer(msg.sender, srcToReturn);\n }\n return tokensSold;\n } else {\n UniswapExchange exchangeContractSrc = UniswapExchange(_getExchangeAddress(src));\n uint tokensSold = exchangeContractSrc.tokenToTokenTransferOutput(destAmt, maxSrcAmt, uint(0 - 1), deadline, msg.sender, dest);\n if (tokensSold < maxSrcAmt) {\n IERC20 srcTkn = IERC20(src);\n uint srcToReturn = maxSrcAmt - tokensSold;\n srcTkn.transfer(msg.sender, srcToReturn);\n }\n return tokensSold;\n }\n\n }\n\n}\n\n\ncontract Trade is Kyber, Uniswap {\n function getRateFromSrc(address src, address dest, uint srcAmt) public view returns (uint, uint) {\n uint uniswapRate = getExpectedRateSrcUniswap(src, dest, srcAmt);\n uint kyberRate = getExpectedRateKyber(src, dest, srcAmt);\n if (uniswapRate > kyberRate) {\n return (uniswapRate, 1);\n } else {\n return (kyberRate, 2);\n }\n }\n\n function tradeFromSrc(address src, uint srcAmt, address dest, uint minDestAmt, uint dexNum) public payable returns (uint) {\n address eth = _getAddress(\"eth\");\n if (dexNum == 1) {\n if (src == eth) {\n return tradeSrcUniswap(src, srcAmt, dest, minDestAmt, now + 10000000);\n } else {\n _allowanceApproveUniswap(src);\n return tradeSrcUniswap(src, srcAmt, dest, minDestAmt, now + 10000000);\n }\n } else {\n if (src == eth) {\n return tradeSrcKyber(src, srcAmt, dest, minDestAmt);\n } else {\n _allowanceApproveKyber(src);\n return tradeSrcKyber(src, srcAmt, dest, minDestAmt);\n }\n }\n }\n\n function tradeFromDest(address src, uint maxSrcAmt, address dest, uint destAmt, uint dexNum) public payable returns (uint) {\n address eth = _getAddress(\"eth\");\n if (dexNum == 1) {\n if (src == eth) {\n return tradeDestUniswap(src, maxSrcAmt, dest, destAmt, now + 10000000);\n } else {\n _allowanceApproveUniswap(src);\n return tradeDestUniswap(src, maxSrcAmt, dest, destAmt, now + 10000000);\n }\n } else {\n if (src == eth) {\n return tradeDestKyber(src, maxSrcAmt, dest, destAmt);\n } else {\n _allowanceApproveKyber(src);\n return tradeDestKyber(src, maxSrcAmt, dest, destAmt);\n }\n }\n }\n}",
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title SafeMath\n * @dev Unsigned math operations with safety checks that revert on error\n */\nlibrary SafeMath {\n /**\n * @dev Multiplies two unsigned integers, reverts on overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b);\n\n return c;\n }\n\n /**\n * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Adds two unsigned integers, reverts on overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a);\n\n return c;\n }\n\n /**\n * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),\n * reverts when dividing by zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b != 0);\n return a % b;\n }\n}\n",
+ "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title ERC20 interface\n * @dev see https://eips.ethereum.org/EIPS/eip-20\n */\ninterface IERC20 {\n function transfer(address to, uint256 value) external returns (bool);\n\n function approve(address spender, uint256 value) external returns (bool);\n\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address who) external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
+ },
+ "sourceTreeHashHex": "0xbee8534ae72caa346db64d4228c956f28b5b6e5bde284b56c91ae92e3a6fa1e2",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/docs/UniswapTrade.json b/docs/UniswapTrade.json
new file mode 100644
index 0000000..8fe85fb
--- /dev/null
+++ b/docs/UniswapTrade.json
@@ -0,0 +1,224 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "UniswapTrade",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "destAmt",
+ "type": "uint256"
+ }
+ ],
+ "name": "getExpectedRateDestUniswap",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "maxSrcAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "destAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "name": "tradeDestUniswap",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "srcAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "minDestAmt",
+ "type": "uint256"
+ },
+ {
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "name": "tradeSrcUniswap",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ },
+ {
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "name": "srcAmt",
+ "type": "uint256"
+ }
+ ],
+ "name": "getExpectedRateSrcUniswap",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "addressRegistry",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "devdoc": {
+ "methods": {
+ "getExpectedRateDestUniswap(address,address,uint256)": {
+ "details": "Uniswap's get expected rate from dest",
+ "params": {
+ "dest": "- Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "destAmt": "- dest token amount",
+ "src": "- Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")"
+ }
+ },
+ "getExpectedRateSrcUniswap(address,address,uint256)": {
+ "details": "Uniswap's get expected rate from source",
+ "params": {
+ "dest": "- Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "src": "- Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "srcAmt": "- source token amount"
+ }
+ },
+ "tradeDestUniswap(address,uint256,address,uint256,uint256)": {
+ "details": "Uniswap's trade when token to buy Amount fixed",
+ "params": {
+ "deadline": "- time for this transaction to be valid",
+ "dest": "- Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "destAmt": "- amount of token to buy",
+ "maxSrcAmt": "- max amount of token for sell (slippage)",
+ "src": "- Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")"
+ }
+ },
+ "tradeSrcUniswap(address,uint256,address,uint256,uint256)": {
+ "details": "Uniswap's trade when token to sell Amount fixed",
+ "params": {
+ "deadline": "- time for this transaction to be valid",
+ "dest": "- Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "minDestAmt": "- min amount of token to buy (slippage)",
+ "src": "- Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")",
+ "srcAmt": "- amount of token for sell"
+ }
+ }
+ }
+ }
+ },
+ "sources": {
+ "Bin/UniswapTrade.sol": {
+ "id": 0
+ },
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": {
+ "id": 6
+ },
+ "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol": {
+ "id": 7
+ }
+ },
+ "sourceCodes": {
+ "Bin/UniswapTrade.sol": "pragma solidity ^0.5.2;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\";\n\ninterface AddressRegistry {\n function getAddr(string calldata name) external view returns (address);\n}\n\n// Uniswap's factory Interface\ninterface UniswapFactory {\n // get exchange from token's address\n function getExchange(address token) external view returns (address exchange);\n}\n\n// Uniswap's exchange Interface\ninterface UniswapExchange {\n // Get Prices\n function getEthToTokenInputPrice(uint256 eth_sold) external view returns (uint256 tokens_bought);\n function getEthToTokenOutputPrice(uint256 tokens_bought) external view returns (uint256 eth_sold);\n function getTokenToEthInputPrice(uint256 tokens_sold) external view returns (uint256 eth_bought);\n function getTokenToEthOutputPrice(uint256 eth_bought) external view returns (uint256 tokens_sold);\n // Trade ETH to ERC20\n function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient)\n external\n payable\n returns (uint256 tokens_bought);\n function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient)\n external\n payable\n returns (uint256 eth_sold);\n // Trade ERC20 to ETH\n function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_tokens, uint256 deadline, address recipient)\n external\n returns (uint256 eth_bought);\n function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient)\n external\n returns (uint256 tokens_sold);\n // Trade ERC20 to ERC20\n function tokenToTokenTransferInput(\n uint256 tokens_sold,\n uint256 min_tokens_bought,\n uint256 min_eth_bought,\n uint256 deadline,\n address recipient,\n address token_addr\n ) external returns (uint256 tokens_bought);\n function tokenToTokenTransferOutput(\n uint256 tokens_bought,\n uint256 max_tokens_sold,\n uint256 max_eth_sold,\n uint256 deadline,\n address recipient,\n address token_addr\n ) external returns (uint256 tokens_sold);\n}\n\ncontract Registry {\n address public addressRegistry;\n modifier onlyAdmin() {\n require(msg.sender == getAddress(\"admin\"), \"Permission Denied\");\n _;\n }\n function getAddress(string memory name) internal view returns (address) {\n AddressRegistry addrReg = AddressRegistry(addressRegistry);\n return addrReg.getAddr(name);\n }\n}\n\ncontract UniswapTrade is Registry {\n using SafeMath for uint;\n\n // Get Uniswap's Exchange address from Factory Contract\n function _getExchangeAddress(address _token) internal view returns (address) {\n UniswapFactory uniswapMain = UniswapFactory(getAddress(\"uniswap\"));\n return uniswapMain.getExchange(_token);\n }\n\n // Check required ETH Quantity to execute code\n function _getToken(address trader, address src, uint srcAmt, address eth) internal returns (uint ethQty) {\n if (src == eth) {\n require(msg.value == srcAmt, \"Invalid Operation\");\n ethQty = srcAmt;\n } else {\n IERC20 tokenFunctions = IERC20(src);\n tokenFunctions.transferFrom(trader, address(this), srcAmt);\n ethQty = 0;\n }\n }\n\n /**\n * @dev Uniswap's get expected rate from source\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param srcAmt - source token amount\n */\n function getExpectedRateSrcUniswap(address src, address dest, uint srcAmt) external view returns (uint256) {\n if (src == getAddress(\"eth\")) {\n // define uniswap exchange with dest address\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));\n return exchangeContract.getEthToTokenInputPrice(srcAmt);\n } else if (dest == getAddress(\"eth\")) {\n // define uniswap exchange with src address\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n return exchangeContract.getTokenToEthInputPrice(srcAmt);\n } else {\n UniswapExchange exchangeContractSrc = UniswapExchange(_getExchangeAddress(src));\n UniswapExchange exchangeContractDest = UniswapExchange(_getExchangeAddress(dest));\n uint ethQty = exchangeContractSrc.getTokenToEthInputPrice(srcAmt);\n return exchangeContractDest.getEthToTokenInputPrice(ethQty);\n }\n }\n\n /**\n * @dev Uniswap's get expected rate from dest\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param destAmt - dest token amount\n */\n function getExpectedRateDestUniswap(address src, address dest, uint destAmt) external view returns (uint256) {\n address eth = getAddress(\"eth\");\n if (src == eth) {\n // define uniswap exchange with dest address\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));\n return exchangeContract.getEthToTokenOutputPrice(destAmt);\n } else if (dest == eth) {\n // define uniswap exchange with src address\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n return exchangeContract.getTokenToEthOutputPrice(destAmt);\n } else {\n UniswapExchange exchangeContractSrc = UniswapExchange(_getExchangeAddress(src));\n UniswapExchange exchangeContractDest = UniswapExchange(_getExchangeAddress(dest));\n uint ethQty = exchangeContractDest.getTokenToEthInputPrice(destAmt);\n return exchangeContractSrc.getEthToTokenInputPrice(ethQty);\n }\n }\n\n /**\n * @dev Uniswap's trade when token to sell Amount fixed\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param srcAmt - amount of token for sell\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param minDestAmt - min amount of token to buy (slippage)\n * @param deadline - time for this transaction to be valid\n */\n function tradeSrcUniswap(address src, uint srcAmt, address dest, uint minDestAmt, uint deadline) public payable returns (uint) {\n address eth = getAddress(\"eth\");\n uint ethQty = _getToken(msg.sender, src, srcAmt, eth);\n\n if (src == eth) {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));\n uint tokensBought = exchangeContract.ethToTokenTransferInput.value(ethQty)(minDestAmt, deadline, msg.sender);\n return tokensBought;\n } else if (dest == eth) {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n uint ethBought = exchangeContract.tokenToEthTransferInput(srcAmt, minDestAmt, deadline, msg.sender);\n return ethBought;\n } else {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n uint tokensBought = exchangeContract.tokenToTokenTransferInput(srcAmt, minDestAmt, uint(0), deadline, msg.sender, dest);\n return tokensBought;\n }\n }\n\n /**\n * @dev Uniswap's trade when token to buy Amount fixed\n * @param src - Token address to sell (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param maxSrcAmt - max amount of token for sell (slippage)\n * @param dest - Token address to buy (for ETH it's \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\")\n * @param destAmt - amount of token to buy\n * @param deadline - time for this transaction to be valid\n */\n function tradeDestUniswap(address src, uint maxSrcAmt, address dest, uint destAmt, uint deadline) public payable returns (uint) {\n address eth = getAddress(\"eth\");\n uint ethQty = _getToken(msg.sender, src, maxSrcAmt, eth);\n\n if (src == eth) {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(dest));\n uint ethSold = exchangeContract.ethToTokenTransferOutput.value(ethQty)(destAmt, deadline, msg.sender);\n if (ethSold < ethQty) {\n uint srcToReturn = ethQty - ethSold;\n msg.sender.transfer(srcToReturn);\n }\n return ethSold;\n } else if (dest == eth) {\n UniswapExchange exchangeContract = UniswapExchange(_getExchangeAddress(src));\n uint tokensSold = exchangeContract.tokenToEthTransferOutput(destAmt, maxSrcAmt, deadline, msg.sender);\n if (tokensSold < maxSrcAmt) {\n IERC20 srcTkn = IERC20(src);\n uint srcToReturn = maxSrcAmt - tokensSold;\n srcTkn.transfer(msg.sender, srcToReturn);\n }\n return tokensSold;\n } else {\n UniswapExchange exchangeContractSrc = UniswapExchange(_getExchangeAddress(src));\n uint tokensSold = exchangeContractSrc.tokenToTokenTransferOutput(destAmt, maxSrcAmt, uint(0 - 1), deadline, msg.sender, dest);\n if (tokensSold < maxSrcAmt) {\n IERC20 srcTkn = IERC20(src);\n uint srcToReturn = maxSrcAmt - tokensSold;\n srcTkn.transfer(msg.sender, srcToReturn);\n }\n return tokensSold;\n }\n\n }\n\n}\n",
+ "openzeppelin-solidity/contracts/math/SafeMath.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title SafeMath\n * @dev Unsigned math operations with safety checks that revert on error\n */\nlibrary SafeMath {\n /**\n * @dev Multiplies two unsigned integers, reverts on overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b);\n\n return c;\n }\n\n /**\n * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Adds two unsigned integers, reverts on overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a);\n\n return c;\n }\n\n /**\n * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),\n * reverts when dividing by zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b != 0);\n return a % b;\n }\n}\n",
+ "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol": "pragma solidity ^0.5.2;\n\n/**\n * @title ERC20 interface\n * @dev see https://eips.ethereum.org/EIPS/eip-20\n */\ninterface IERC20 {\n function transfer(address to, uint256 value) external returns (bool);\n\n function approve(address spender, uint256 value) external returns (bool);\n\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address who) external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
+ },
+ "sourceTreeHashHex": "0x3abc5fee2f31f9b33dfe99cbcc4bc6a736b4271f07b7cc83b116cc0d7529846e",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/docs/UserWallet.json b/docs/UserWallet.json
new file mode 100644
index 0000000..f3dd6ba
--- /dev/null
+++ b/docs/UserWallet.json
@@ -0,0 +1,243 @@
+{
+ "schemaVersion": "2.0.0",
+ "contractName": "UserWallet",
+ "compilerOutput": {
+ "abi": [
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "nextOwner",
+ "type": "address"
+ }
+ ],
+ "name": "setOwner",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "src",
+ "type": "address"
+ }
+ ],
+ "name": "isAuth",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "registry",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_target",
+ "type": "address"
+ },
+ {
+ "name": "_data",
+ "type": "bytes"
+ },
+ {
+ "name": "_srcNum",
+ "type": "uint256"
+ },
+ {
+ "name": "_sessionNum",
+ "type": "uint256"
+ }
+ ],
+ "name": "execute",
+ "outputs": [
+ {
+ "name": "response",
+ "type": "bytes"
+ }
+ ],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "fallback"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "srcNum",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "sessionNum",
+ "type": "uint256"
+ }
+ ],
+ "name": "LogExecute",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "sig",
+ "type": "bytes4"
+ },
+ {
+ "indexed": true,
+ "name": "guy",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "foo",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "name": "bar",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "name": "wad",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "fax",
+ "type": "bytes"
+ }
+ ],
+ "name": "LogNote",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "LogSetOwner",
+ "type": "event"
+ }
+ ],
+ "devdoc": {
+ "methods": {
+ "constructor": {
+ "details": "sets the \"address registry\", owner's last activity, owner's active period and initial owner"
+ },
+ "execute(address,bytes,uint256,uint256)": {
+ "details": "Execute authorised calls via delegate call",
+ "params": {
+ "_data": "delegate call data",
+ "_sessionNum": "to find the session",
+ "_srcNum": "to find the source",
+ "_target": "logic proxy address"
+ }
+ },
+ "isAuth(address)": {
+ "details": "checks if called by owner or contract itself",
+ "params": {
+ "src": "is the address initiating the call"
+ }
+ },
+ "setOwner(address)": {
+ "details": "sets new owner"
+ }
+ },
+ "title": "User Owned Contract Wallet"
+ }
+ },
+ "sources": {
+ "UserWallet.sol": {
+ "id": 1
+ }
+ },
+ "sourceCodes": {
+ "UserWallet.sol": "pragma solidity ^0.5.2;\n\n\n/**\n * @dev because math is not safe \n */\nlibrary SafeMath {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"math-not-safe\");\n return c;\n }\n}\n\n\n/**\n * @title RegistryInterface Interface \n */\ninterface RegistryInterface {\n function logic(address logicAddr) external view returns (bool);\n function record(address currentOwner, address nextOwner) external;\n}\n\n\n/**\n * @title Address Registry Record\n */\ncontract AddressRecord {\n\n /**\n * @dev address registry of system, logic and wallet addresses\n */\n address public registry;\n\n /**\n * @dev Throws if the logic is not authorised\n */\n modifier logicAuth(address logicAddr) {\n require(logicAddr != address(0), \"logic-proxy-address-required\");\n bool islogic = RegistryInterface(registry).logic(logicAddr);\n require(islogic, \"logic-not-authorised\");\n _;\n }\n\n}\n\n\n/**\n * @title User Auth\n */\ncontract UserAuth is AddressRecord {\n using SafeMath for uint;\n using SafeMath for uint256;\n\n event LogSetOwner(address indexed owner);\n address public owner;\n\n /**\n * @dev Throws if not called by owner or contract itself\n */\n modifier auth {\n require(isAuth(msg.sender), \"permission-denied\");\n _;\n }\n\n /**\n * @dev sets new owner\n */\n function setOwner(address nextOwner) public auth {\n RegistryInterface(registry).record(owner, nextOwner);\n owner = nextOwner;\n emit LogSetOwner(nextOwner);\n }\n\n /**\n * @dev checks if called by owner or contract itself\n * @param src is the address initiating the call\n */\n function isAuth(address src) public view returns (bool) {\n if (src == owner) {\n return true;\n } else if (src == address(this)) {\n return true;\n } else {\n return false;\n }\n }\n}\n\n\n/**\n * @dev logging the execute events\n */\ncontract UserNote {\n event LogNote(\n bytes4 indexed sig,\n address indexed guy,\n bytes32 indexed foo,\n bytes32 bar,\n uint wad,\n bytes fax\n );\n\n modifier note {\n bytes32 foo;\n bytes32 bar;\n assembly {\n foo := calldataload(4)\n bar := calldataload(36)\n }\n emit LogNote(\n msg.sig, \n msg.sender, \n foo, \n bar, \n msg.value,\n msg.data\n );\n _;\n }\n}\n\n\n/**\n * @title User Owned Contract Wallet\n */\ncontract UserWallet is UserAuth, UserNote {\n\n event LogExecute(address sender, address target, uint srcNum, uint sessionNum);\n\n /**\n * @dev sets the \"address registry\", owner's last activity, owner's active period and initial owner\n */\n constructor() public {\n registry = msg.sender;\n owner = msg.sender;\n }\n\n function() external payable {}\n\n /**\n * @dev Execute authorised calls via delegate call\n * @param _target logic proxy address\n * @param _data delegate call data\n * @param _srcNum to find the source\n * @param _sessionNum to find the session\n */\n function execute(\n address _target,\n bytes memory _data,\n uint _srcNum,\n uint _sessionNum\n ) \n public\n payable\n note\n auth\n logicAuth(_target)\n returns (bytes memory response)\n {\n emit LogExecute(\n msg.sender,\n _target,\n _srcNum,\n _sessionNum\n );\n \n // call contract in current context\n assembly {\n let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)\n let size := returndatasize\n\n response := mload(0x40)\n mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))\n mstore(response, size)\n returndatacopy(add(response, 0x20), 0, size)\n\n switch iszero(succeeded)\n case 1 {\n // throw if delegatecall failed\n revert(add(response, 0x20), size)\n }\n }\n }\n\n}"
+ },
+ "sourceTreeHashHex": "0x6c8771a0594acf5f4a7381dae9cf00c28b9cc899151276a8b989eb2edb21c22e",
+ "compiler": {
+ "name": "solc",
+ "version": "soljson-v0.5.7+commit.6da8b019.js",
+ "settings": {
+ "optimizer": {
+ "enabled": false
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "devdoc"
+ ]
+ }
+ },
+ "remappings": [
+ "openzeppelin-solidity=/Users/ravindra/code/contract-v2/node_modules/openzeppelin-solidity"
+ ]
+ }
+ },
+ "networks": {}
+}
\ No newline at end of file
diff --git a/flats/InstaRegistry.sol b/flats/InstaRegistry.sol
new file mode 100644
index 0000000..a35819d
--- /dev/null
+++ b/flats/InstaRegistry.sol
@@ -0,0 +1,391 @@
+
+// File: openzeppelin-solidity/contracts/math/SafeMath.sol
+
+pragma solidity ^0.5.2;
+
+/**
+ * @title SafeMath
+ * @dev Unsigned math operations with safety checks that revert on error
+ */
+library SafeMath {
+ /**
+ * @dev Multiplies two unsigned integers, reverts on overflow.
+ */
+ function mul(uint256 a, uint256 b) internal pure returns (uint256) {
+ // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
+ // benefit is lost if 'b' is also tested.
+ // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
+ if (a == 0) {
+ return 0;
+ }
+
+ uint256 c = a * b;
+ require(c / a == b);
+
+ return c;
+ }
+
+ /**
+ * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
+ */
+ function div(uint256 a, uint256 b) internal pure returns (uint256) {
+ // Solidity only automatically asserts when dividing by 0
+ require(b > 0);
+ uint256 c = a / b;
+ // assert(a == b * c + a % b); // There is no case in which this doesn't hold
+
+ return c;
+ }
+
+ /**
+ * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
+ */
+ function sub(uint256 a, uint256 b) internal pure returns (uint256) {
+ require(b <= a);
+ uint256 c = a - b;
+
+ return c;
+ }
+
+ /**
+ * @dev Adds two unsigned integers, reverts on overflow.
+ */
+ function add(uint256 a, uint256 b) internal pure returns (uint256) {
+ uint256 c = a + b;
+ require(c >= a);
+
+ return c;
+ }
+
+ /**
+ * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
+ * reverts when dividing by zero.
+ */
+ function mod(uint256 a, uint256 b) internal pure returns (uint256) {
+ require(b != 0);
+ return a % b;
+ }
+}
+
+// File: contracts/UserWallet.sol
+
+pragma solidity ^0.5.2;
+
+
+/**
+ * @title RegistryInterface Interface
+ */
+interface RegistryInterface {
+ function logic(address logicAddr) external view returns (bool);
+ function record(address currentOwner, address nextOwner) external;
+}
+
+/**
+ * @title Address Registry Record
+ */
+contract AddressRecord {
+
+ /**
+ * @dev address registry of system, logic and wallet addresses
+ */
+ address public registry;
+
+ /**
+ * @dev Throws if the logic is not authorised
+ */
+ modifier logicAuth(address logicAddr) {
+ require(logicAddr != address(0), "logic-proxy-address-required");
+ bool islogic = RegistryInterface(registry).logic(logicAddr);
+ require(islogic, "logic-not-authorised");
+ _;
+ }
+
+}
+
+
+/**
+ * @title User Auth
+ */
+contract UserAuth is AddressRecord {
+ using SafeMath for uint;
+ using SafeMath for uint256;
+
+ event LogSetOwner(address indexed owner);
+ address public owner;
+
+ /**
+ * @dev Throws if not called by owner or contract itself
+ */
+ modifier auth {
+ require(isAuth(msg.sender), "permission-denied");
+ _;
+ }
+
+ /**
+ * @dev sets new owner
+ */
+ function setOwner(address nextOwner) public auth {
+ RegistryInterface(registry).record(owner, nextOwner);
+ owner = nextOwner;
+ emit LogSetOwner(nextOwner);
+ }
+
+ /**
+ * @dev checks if called by owner or contract itself
+ * @param src is the address initiating the call
+ */
+ function isAuth(address src) public view returns (bool) {
+ if (src == owner) {
+ return true;
+ } else if (src == address(this)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+
+/**
+ * @dev logging the execute events
+ */
+contract UserNote {
+ event LogNote(
+ bytes4 indexed sig,
+ address indexed guy,
+ bytes32 indexed foo,
+ bytes32 bar,
+ uint wad,
+ bytes fax
+ );
+
+ modifier note {
+ bytes32 foo;
+ bytes32 bar;
+ assembly {
+ foo := calldataload(4)
+ bar := calldataload(36)
+ }
+ emit LogNote(
+ msg.sig,
+ msg.sender,
+ foo,
+ bar,
+ msg.value,
+ msg.data
+ );
+ _;
+ }
+}
+
+
+/**
+ * @title User Owned Contract Wallet
+ */
+contract UserWallet is UserAuth, UserNote {
+
+ event LogExecute(address sender, address target, uint srcNum, uint sessionNum);
+
+ /**
+ * @dev sets the "address registry", owner's last activity, owner's active period and initial owner
+ */
+ constructor() public {
+ registry = msg.sender;
+ owner = msg.sender;
+ }
+
+ function() external payable {}
+
+ /**
+ * @dev Execute authorised calls via delegate call
+ * @param _target logic proxy address
+ * @param _data delegate call data
+ * @param _srcNum to find the source
+ * @param _sessionNum to find the session
+ */
+ function execute(
+ address _target,
+ bytes memory _data,
+ uint _srcNum,
+ uint _sessionNum
+ )
+ public
+ payable
+ note
+ auth
+ logicAuth(_target)
+ returns (bytes memory response)
+ {
+ emit LogExecute(
+ msg.sender,
+ _target,
+ _srcNum,
+ _sessionNum
+ );
+
+ // call contract in current context
+ assembly {
+ let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
+ let size := returndatasize
+
+ response := mload(0x40)
+ mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))
+ mstore(response, size)
+ returndatacopy(add(response, 0x20), 0, size)
+
+ switch iszero(succeeded)
+ case 1 {
+ // throw if delegatecall failed
+ revert(add(response, 0x20), size)
+ }
+ }
+ }
+
+}
+
+// File: contracts/InstaRegistry.sol
+
+pragma solidity ^0.5.2;
+
+
+
+/// @title AddressRegistry
+/// @notice
+/// @dev
+contract AddressRegistry {
+ event LogSetAddress(string name, address addr);
+
+ /// @notice Registry of role and address
+ mapping(bytes32 => address) registry;
+
+ /**
+ * @dev Check if msg.sender is admin or owner.
+ */
+ modifier isAdmin() {
+ require(
+ msg.sender == getAddress("admin") ||
+ msg.sender == getAddress("owner"),
+ "permission-denied"
+ );
+ _;
+ }
+
+ /// @dev Get the address from system registry
+ /// @param _name (string)
+ /// @return (address) Returns address based on role
+ function getAddress(string memory _name) public view returns(address) {
+ return registry[keccak256(abi.encodePacked(_name))];
+ }
+
+ /// @dev Set new address in system registry
+ /// @param _name (string) Role name
+ /// @param _userAddress (string) User Address
+ function setAddress(string memory _name, address _userAddress) public isAdmin {
+ registry[keccak256(abi.encodePacked(_name))] = _userAddress;
+ emit LogSetAddress(_name, _userAddress);
+ }
+}
+
+
+/// @title LogicRegistry
+/// @notice
+/// @dev LogicRegistry
+contract LogicRegistry is AddressRegistry {
+
+ event LogEnableDefaultLogic(address logicAddress);
+ event LogEnableLogic(address logicAddress);
+ event LogDisableLogic(address logicAddress);
+
+ /// @notice Map of default proxy state
+ mapping(address => bool) public defaultLogicProxies;
+
+ /// @notice Map of logic proxy state
+ mapping(address => bool) public logicProxies;
+
+ /// @dev
+ /// @param _logicAddress (address)
+ /// @return (bool)
+ function logic(address _logicAddress) public view returns (bool) {
+ if (defaultLogicProxies[_logicAddress] || logicProxies[_logicAddress]) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /// @dev Sets the default logic proxy to true
+ /// default proxies mostly contains the logic for withdrawal of assets
+ /// and can never be false to freely let user withdraw their assets
+ /// @param _logicAddress (address)
+ function enableDefaultLogic(address _logicAddress) public isAdmin {
+ defaultLogicProxies[_logicAddress] = true;
+ emit LogEnableDefaultLogic(_logicAddress);
+ }
+
+ /// @dev Enable logic proxy address
+ /// @param _logicAddress (address)
+ function enableLogic(address _logicAddress) public isAdmin {
+ logicProxies[_logicAddress] = true;
+ emit LogEnableLogic(_logicAddress);
+ }
+
+ /// @dev Disable logic proxy address
+ /// @param _logicAddress (address)
+ function disableLogic(address _logicAddress) public isAdmin {
+ logicProxies[_logicAddress] = false;
+ emit LogDisableLogic(_logicAddress);
+ }
+
+}
+
+/**
+ * @dev Deploys a new proxy instance and sets msg.sender as owner of proxy
+ */
+contract WalletRegistry is LogicRegistry {
+
+ event Created(address indexed sender, address indexed owner, address proxy);
+ event LogRecord(address indexed currentOwner, address indexed nextOwner, address proxy);
+
+ /// @notice Address to UserWallet proxy map
+ mapping(address => UserWallet) public proxies;
+
+ /// @dev Deploys a new proxy instance and sets custom owner of proxy
+ /// Throws if the owner already have a UserWallet
+ /// @return proxy ()
+ function build() public returns (UserWallet proxy) {
+ proxy = build(msg.sender);
+ }
+
+ /// @dev update the proxy record whenever owner changed on any proxy
+ /// Throws if msg.sender is not a proxy contract created via this contract
+ /// @return proxy () UserWallet
+ function build(address owner) public returns (UserWallet proxy) {
+ require(proxies[owner] == UserWallet(0), "multiple-proxy-per-user-not-allowed");
+ proxy = new UserWallet();
+ proxies[address(this)] = proxy; // will be changed via record() in next line execution
+ proxy.setOwner(owner);
+ emit Created(msg.sender, owner, address(proxy));
+ }
+
+ /// @dev Transafers ownership
+ /// @param _currentOwner (address) Current Owner
+ /// @param _nextOwner (address) Next Owner
+ function record(address _currentOwner, address _nextOwner) public {
+ require(msg.sender == address(proxies[_currentOwner]), "invalid-proxy-or-owner");
+ require(proxies[_nextOwner] == UserWallet(0), "multiple-proxy-per-user-not-allowed");
+ proxies[_nextOwner] = proxies[_currentOwner];
+ proxies[_currentOwner] = UserWallet(0);
+ emit LogRecord(_currentOwner, _nextOwner, address(proxies[_nextOwner]));
+ }
+
+}
+
+/// @title InstaRegistry
+/// @dev Initializing Registry
+contract InstaRegistry is WalletRegistry {
+
+ constructor() public {
+ registry[keccak256(abi.encodePacked("admin"))] = msg.sender;
+ registry[keccak256(abi.encodePacked("owner"))] = msg.sender;
+ }
+}
diff --git a/package.json b/package.json
index 1d5acb3..add44db 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
- "name": "smart-contract-starter",
+ "name": "instadapp-contracts",
"description": "Boilerplate for your next Smart Contract, made simple.",
- "version": "0.0.1",
+ "version": "0.0.2",
"author": "Ravindra Kumar ",
"license": "MIT",
"main": "truffle.js",
@@ -11,26 +11,34 @@
"scripts": {
"ganache": "ganache-cli -e 300 -p 9545 -m 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat' --accounts 30 > /dev/null &",
"stop": "sudo kill `sudo lsof -t -i:9545`",
- "test": "npm run ganache sleep 5 && npm run lint ./ && npm run solium && truffle test && npm run stop",
+ "test": "npm run ganache sleep 5 && truffle test && npm run stop",
"test:gas-reporter": "GAS_REPORTER=true npm run test",
- "test-ci": "GAS_REPORTER=true npm run ganache sleep 5 && npm run lint ./ && npm run solium && truffle test",
+ "test-ci": "GAS_REPORTER=true npm run ganache sleep 5 && truffle test",
"coverage": "./node_modules/.bin/solidity-coverage",
"lint": "eslint ./test",
"lint:fix": "eslint ./ --fix",
"solium": "solium -d contracts/",
"solium:fix": "solium -d contracts/ --fix",
- "build": "npm run clean:contracts && truffle compile"
+ "build": "npm run clean:contracts && truffle compile",
+ "audit": "truffle run verify",
+ "docs": "sol-compiler",
+ "flat": "truffle-flattener contracts/InstaRegistry.sol > flats/InstaRegistry.sol",
+ "deploy:testnet": "truffle migrate --network kovan"
},
"dependencies": {
+ "@0x/sol-compiler": "^3.1.5",
"bn.js": "^4.11.8",
- "dotenv": "^6.2.0",
+ "dotenv": "^7.0.0",
"ethereumjs-wallet": "^0.6.3",
- "npm-check-updates": "^2.15.0",
- "openzeppelin-solidity": "^2.0.0",
- "truffle": "^5.0.0",
- "truffle-hdwallet-provider": "^1.0.1",
+ "npm-check-updates": "^3.1.4",
+ "openzeppelin-solidity": "^2.2.0",
+ "truffle": "^5.0.11",
+ "truffle-assertions": "^0.8.2",
+ "truffle-flattener": "^1.3.0",
+ "truffle-hdwallet-provider": "^1.0.6",
+ "truffle-security": "^1.3.2",
"web3": "^1.0.0-beta.37",
- "webpack": "^4.28.1"
+ "webpack": "^4.29.6"
},
"devDependencies": {
"babel-cli": "^6.26.0",
@@ -44,25 +52,26 @@
"chai": "4.2.0",
"chai-as-promised": "7.1.1",
"chai-bignumber": "3.0.0",
- "coveralls": "3.0.2",
- "eslint": "5.10.0",
- "eslint-config-prettier": "^3.3.0",
+ "coveralls": "3.0.3",
+ "eslint": "5.16.0",
+ "eslint-config-prettier": "^4.1.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-babel": "^5.3.0",
- "eslint-plugin-compat": "^2.6.3",
- "eslint-plugin-import": "2.14.0",
- "eslint-plugin-node": "8.0.0",
- "eslint-plugin-prettier": "^3.0.0",
- "eslint-plugin-promise": "4.0.1",
+ "eslint-plugin-compat": "^3.1.0",
+ "eslint-plugin-import": "2.16.0",
+ "eslint-plugin-node": "8.0.1",
+ "eslint-plugin-prettier": "^3.0.1",
+ "eslint-plugin-promise": "4.1.1",
"eslint-plugin-security": "^1.4.0",
"eslint-plugin-standard": "^4.0.0",
"eth-gas-reporter": "^0.1.12",
- "ganache-cli": "^6.2.5",
- "mocha-junit-reporter": "^1.18.0",
+ "ganache-cli": "^6.4.2",
+ "mocha-junit-reporter": "^1.21.0",
"mocha-multi-reporters": "^1.1.7",
+ "openzeppelin-test-helpers": "^0.3.1",
"prettier": "^1.16.4",
"prettier-plugin-solidity-refactor": "^1.0.0-alpha.14",
"solidity-coverage": "0.5.11",
- "solium": "1.1.8"
+ "solium": "1.2.3"
}
}
diff --git a/test/InstaRegistry.test.js b/test/InstaRegistry.test.js
new file mode 100644
index 0000000..8c20682
--- /dev/null
+++ b/test/InstaRegistry.test.js
@@ -0,0 +1,47 @@
+const truffleAssert = require('truffle-assertions')
+const { assertRevert } = require('./helpers/general')
+const InstaRegistry = artifacts.require('InstaRegistry')
+
+contract('InstaRegistry', accounts => {
+ let instaRegistry
+ const user = accounts[0]
+
+ beforeEach(async () => {
+ instaRegistry = await InstaRegistry.new({
+ from: user
+ })
+ })
+
+ it('user should be owner and admin', async () => {
+ const admin = await instaRegistry.getAddress('admin', {
+ from: user
+ })
+
+ assert.equal(admin, user, 'user is admin')
+ })
+
+ it('only admin or owner should be able to set address', async () => {
+ const result = await instaRegistry.setAddress('admin', accounts[2], {
+ from: user
+ })
+
+ expect(result.receipt.status).to.equal(true)
+ truffleAssert.prettyPrintEmittedEvents(result)
+ truffleAssert.eventEmitted(
+ result,
+ 'LogSetAddress',
+ event => {
+ return event.name === 'admin' && event.addr === accounts[2]
+ },
+ 'LogSetAddress should be emitted with correct parameters'
+ )
+ })
+
+ it('revert when non-admin tries to set address', async () => {
+ await assertRevert(
+ instaRegistry.setAddress('admin', accounts[2], {
+ from: user
+ })
+ )
+ })
+})
diff --git a/test/Ownable.test.js b/test/Ownable.test.js
index 6a401fe..96bedae 100644
--- a/test/Ownable.test.js
+++ b/test/Ownable.test.js
@@ -1,4 +1,4 @@
-const { assertRevert } = require('./helpers/general')
+const { shouldFail } = require('openzeppelin-test-helpers')
const Ownable = artifacts.require('Ownable')
@@ -26,6 +26,9 @@ contract('Ownable', accounts => {
const other = accounts[2]
const owner = await ownable.owner.call()
assert.isTrue(owner !== other)
- await assertRevert(ownable.transferOwnership(other, { from: other }))
+ await shouldFail.reverting.withMessage(
+ ownable.transferOwnership(other, { from: other }),
+ "Only owner accessible"
+ );
})
})
diff --git a/truffle-security.json b/truffle-security.json
new file mode 100644
index 0000000..184aab7
--- /dev/null
+++ b/truffle-security.json
@@ -0,0 +1,5 @@
+{
+ "style": "table",
+ "mode": "full",
+ "min-severity": "error"
+}
\ No newline at end of file
diff --git a/truffle.js b/truffle.js
index 86d4281..3097309 100644
--- a/truffle.js
+++ b/truffle.js
@@ -8,6 +8,13 @@ const rinkebyProvider = new HDWalletProvider(
'https://rinkeby.infura.io/'
)
+const kovanWallet =
+ 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat'
+const kovanProvider = new HDWalletProvider(
+ kovanWallet,
+ 'https://kovan.infura.io/'
+)
+
const ropstenWallet =
'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat'
const ropstenProvider = new HDWalletProvider(
@@ -16,6 +23,7 @@ const ropstenProvider = new HDWalletProvider(
)
module.exports = {
+ plugins: ['truffle-security'],
migrations_directory: './migrations',
networks: {
test: {
@@ -32,6 +40,12 @@ module.exports = {
gasPrice: 5e9,
provider: () => ropstenProvider
},
+ kovan: {
+ network_id: 42,
+ gas: 6.5e6,
+ gasPrice: 5e9,
+ provider: () => kovanProvider
+ },
rinkeby: {
network_id: 4,
gas: 6.5e6,
@@ -39,10 +53,15 @@ module.exports = {
provider: () => rinkebyProvider
}
},
- solc: {
- optimizer: {
- enabled: true,
- runs: 500
+ compilers: {
+ solc: {
+ version: '^0.5.2',
+ settings: {
+ optimizer: {
+ enabled: false,
+ runs: 500
+ }
+ }
}
},
mocha: {