Merge pull request from InstaDApp/test-suite

Test Suite Setup
This commit is contained in:
Sowmay Jain 2019-04-06 18:32:42 +05:30 committed by GitHub
commit 6a12915ce0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 3067 additions and 842 deletions

View File

@ -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']
}

13
compiler.json Normal file
View File

@ -0,0 +1,13 @@
{
"contractsDir": "contracts",
"artifactsDir": "docs",
"contracts": "*",
"compilerSettings": {
"optimizer": { "enabled": false },
"outputSelection": {
"*": {
"*": ["abi","devdoc"]
}
}
}
}

View File

@ -1,4 +1,4 @@
pragma solidity ^0.5.0;
pragma solidity ^0.5.2;
interface TubInterface {

View File

@ -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 {}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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);
}
}

View File

@ -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 {
}
}
}
}
}

View File

@ -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 {
}
}
}

View File

@ -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;
}
}
}

View File

@ -1,4 +1,4 @@
pragma solidity ^0.5.0;
pragma solidity ^0.5.2;
/* solium-disable mixedcase */
contract Migrations {

View File

@ -1,5 +1,4 @@
pragma solidity ^0.5.0;
pragma solidity ^0.5.2;
/**
* @title Ownable

View File

@ -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 {

View File

@ -1,5 +1,6 @@
pragma solidity ^0.5.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
interface TubInterface {
function open() external returns (bytes32);

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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");
_;
}
}
}

View File

@ -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

120
docs/FreeProxy.json Normal file
View File

@ -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": {}
}

414
docs/InstaRegistry.json Normal file

File diff suppressed because one or more lines are too long

653
docs/InstaWallet.json Normal file

File diff suppressed because one or more lines are too long

123
docs/Kyber.json Normal file

File diff suppressed because one or more lines are too long

103
docs/Migrations.json Normal file
View File

@ -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": {}
}

104
docs/Ownable.json Normal file
View File

@ -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": {}
}

326
docs/Trade.json Normal file

File diff suppressed because one or more lines are too long

224
docs/UniswapTrade.json Normal file

File diff suppressed because one or more lines are too long

243
docs/UserWallet.json Normal file
View File

@ -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": {}
}

391
flats/InstaRegistry.sol Normal file
View File

@ -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;
}
}

View File

@ -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 <ravidsrk@gmail.com>",
"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"
}
}

View File

@ -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
})
)
})
})

View File

@ -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"
);
})
})

5
truffle-security.json Normal file
View File

@ -0,0 +1,5 @@
{
"style": "table",
"mode": "full",
"min-severity": "error"
}

View File

@ -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: {