Skip to content

Instantly share code, notes, and snippets.

@asoong
Created September 18, 2018 10:17
Show Gist options
  • Save asoong/ddaa9b732084ca8d32c07d3a13c4118d to your computer and use it in GitHub Desktop.
Save asoong/ddaa9b732084ca8d32c07d3a13c4118d to your computer and use it in GitHub Desktop.
Kyber Contract TestRPC
const BigNumber = require('bignumber.js');
const Bank = artifacts.require("./MockCentralBank.sol");
const CentralizedExchange = artifacts.require("./MockExchange.sol");
const ConversionRates = artifacts.require("./ConversionRates.sol");
const ExpectedRate = artifacts.require("./ExpectedRate.sol");
const FeeBurner = artifacts.require("./FeeBurner.sol");
const Network = artifacts.require("./KyberNetwork.sol");
const NetworkProxy = artifacts.require("./KyberNetworkProxy.sol");
const Reserve = artifacts.require("./KyberReserve.sol");
const TestToken = artifacts.require("./TestToken.sol");
const Whitelist = artifacts.require("./WhiteList.sol");
var contractDeployer; // Master Account
var tokenDecimals = [];
var tokenName = [];
var tokenSymbol = [];
var tokenInstance = [];
var internalUseTokens = []
var listedTokens = []
var tokenInitialReserveBalance = [];
var reserveInitialEth;
var kncInstance;
var kgtInstance;
const kgtName = "Kyber genesis token";
const kgtSymbol = "KGT";
const kgtDec = 0;
var conversionRate = (((new BigNumber(10)).pow(18)).mul(2));
var counterConversionRate = (((new BigNumber(10)).pow(18)).div(2));
var expBlock = 10**10;
var validBlockDuration = 256;
const maxGas = 4612388;
var tokenOwner;
var networkProxy;
var network;
var reserve;
var ethAddress = new BigNumber("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
var exchanges = [];
var exchangesInstance = [];
var exchangeDepositAddresses = [];
var supportedTokens = {}
var bank;
var whitelist;
var conversionRates;
var feeBurner;
var expectedRate;
////////////////////////////////////////////////////////////////////////////////
var deployTokens = function(owner) {
return new Promise(function (fulfill, reject) {
var inputs = [];
for (var i = 0; i < tokenSymbol.length; i++) {
inputs.push(i);
}
//deploy all tokens from json
return inputs.reduce(function (promise, item) {
return promise.then(function () {
var symbol = tokenSymbol[item];
var name = tokenName[item];
var decimals = tokenDecimals[item];
return TestToken.new(
name,
symbol,
decimals,
{ from: owner }
);
}).then(function(instance){
if(tokenSymbol[item] === "KNC") {
kncInstance = instance;
}
tokenInstance.push(instance);
})
}, Promise.resolve()).then(function() {
return TestToken.new(kgtName, kgtSymbol, kgtDec).then(function (instance) {
kgtInstance = instance;
}).then(function() {
fulfill(true);
});
}).catch(function(err) {
reject(err);
});
});
};
////////////////////////////////////////////////////////////////////////////////
var transferFundsToBank = function(owner, bankAddress, amount) {
return new Promise(function (fulfill, reject) {
var inputs = [];
for (var i = 0; i < tokenInstance.length; i++) {
inputs.push(tokenInstance[i]);
}
return inputs.reduce(function (promise, item) {
return promise.then(function () {
return item.transfer(bankAddress, amount, { from: owner });
});
}, Promise.resolve()).then(function() {
fulfill(true);
}).catch(function(err) {
reject(err);
});
});
};
var getBlockNumberWithPromise = function() {
return new Promise(function (fulfill, reject) {
web3.eth.getBlockNumber(function(error, result) {
if (error) {
return reject(error);
} else {
return fulfill(result);
}
});
});
};
////////////////////////////////////////////////////////////////////////////////
var depositTokensToReserve = function(owner, reserveInstance) {
return new Promise(function (fulfill, reject) {
var inputs = [];
for (var i = 0; i < tokenInstance.length; i++) {
inputs.push(i);
}
var actualAmount;
return inputs.reduce(function (promise, item) {
var token = tokenInstance[item];
var amount = tokenInitialReserveBalance[item];
return promise.then(function () {
return token.decimals();
}).then(function(decimals) {
actualAmount = new BigNumber(amount).mul(new BigNumber(10).pow(decimals));
return token.transfer(
reserveInstance.address,
actualAmount,
{ from: owner }
);
});
}, Promise.resolve()).then(function() {
fulfill(true);
}).catch(function(err){
reject(err);
});
});
};
////////////////////////////////////////////////////////////////////////////////
var createExchanges = function(owner, bankAddress) {
return new Promise(function (fulfill, reject) {
var inputs = [];
for (var i = 0; i < exchanges.length; i++) {
inputs.push(exchanges[i]);
}
return inputs.reduce(function (promise, item) {
return promise.then(function () {
return CentralizedExchange.new(
item,
bankAddress,
{ from:owner }
);
}).then(function(instance) {
exchangesInstance.push(instance);
return addDepositAddressToExchange(
instance,
owner,
item
);
});
}, Promise.resolve()).then(function() {
fulfill(true);
}).catch(function(err){
reject(err);
});
});
};
/////////////////////////////////////////////////////////////////
var addDepositAddressToExchange = function(exchange, owner, exchangeName) {
return new Promise(function (fulfill, reject) {
var tokens = [];
var depositAddresses = {}; //dict (JS object) of deposit address per token for this exchange
//create array of tokens
for (var i = 0 ; i < tokenInstance.length ; i++) {
if (supportedTokens[exchangeName].indexOf(tokenSymbol[i].toLowerCase()) >= 0) {
tokens.push(i);
}
}
return tokens.reduce(function (promise, item) {
return promise.then(function () {
return exchange.addMockDepositAddress(
tokenInstance[item].address,
{ from: owner }
);
}).then(function() {
return exchange.tokenDepositAddresses(tokenInstance[item].address)
}).then (function (mockDepositAddress) {
depositAddresses[tokenSymbol[item]] = mockDepositAddress;
return reserve.approveWithdrawAddress(
tokenInstance[item].address,
mockDepositAddress,
true
);
});
}, Promise.resolve()).then(function() {
return exchange.addMockDepositAddress(
ethAddress,
{ from: owner }
);
}).then(function() {
return exchange.tokenDepositAddresses(ethAddress);
}).then(function(depositAddress) {
depositAddresses["ETH"] = depositAddress;
exchangeDepositAddresses.push(depositAddresses);
return reserve.approveWithdrawAddress(
ethAddress,
depositAddress,
true
);
}).then(function() {
fulfill(true);
}).catch(function(err) {
reject(err);
});
});
};
////////////////////////////////////////////////////////////////////////////////
var sendEtherWithPromise = function(sender, recv, amount) {
return new Promise(function(fulfill, reject) {
web3.eth.sendTransaction({ to: recv, from: sender, value: amount }, function(error, result) {
if(error) {
return reject(error);
} else {
return fulfill(true);
}
});
});
};
////////////////////////////////////////////////////////////////////////////////
var listTokens = function(owner, reserve, network, expBlock, rate, convRate) {
return new Promise(function (fulfill, reject) {
var inputs = [];
for (var i = 0 ; i < tokenInstance.length ; i++) {
inputs.push(tokenInstance[i]);
}
return inputs.reduce(function (promise, item) {
var tokenAddress = item.address;
return promise.then(function () {
// list (eth=>token) in reserve
// list (token=>eth) in reserve
// list (eth=>token) in network
// list (token=>eth) in network
return conversionRates.addToken(tokenAddress);
}).then(function(){
return item.decimals();
}).then(function(decimals){
return conversionRates.setTokenControlInfo(
tokenAddress,
10 ** (decimals - 2),
(10 ** decimals) * 50000,
(10 ** decimals) * 1000000
);
}).then(function() {
return conversionRates.enableTokenTrade(tokenAddress);
}).then(function() {
var x = [0];
var y = [0];
return conversionRates.setQtyStepFunction(tokenAddress, x, y, x, y);
}).then(function() {
var x = [0];
var y = [0];
return conversionRates.setImbalanceStepFunction(tokenAddress, x, y, x, y);
}).then(function() {
return conversionRates.setBaseRate(
[tokenAddress],
[convRate],
[rate],
[0/*,2,3,4,5,6,7,8,9,10,11,12,13,14*/],
[0/*,2,3,4,5,6,7,8,9,10,11,12,13,14*/],
web3.eth.blockNumber,
[0]
);
}).then(function() {
return network.listPairForReserve(
reserve.address,
tokenAddress,
true,
true,
true,
{ from: contractDeployer }
);
});
}, Promise.resolve()).then(function() {
fulfill(true);
}).catch(function(err) {
reject(err);
});
});
};
////////////////////////////////////////////////////////////////////////////////
contract('Deployment', function(accounts) {
// Set constants
before(function() {
contractDeployer = accounts[0];
var tokenInfo = {
"KNC": {
"name": "KyberNetwork",
"decimals": 18,
"reserve balance": 3291.3726
}
};
Object.keys(tokenInfo).forEach(function(key) {
var val = tokenInfo[key];
var symbol = key;
var name = val["name"];
var decimals = val["decimals"];
var initialBalance = val["reserve balance"];
if (initialBalance === undefined) {
initialBalance = 1000000;
}
tokenSymbol.push(key);
tokenName.push(name);
tokenDecimals.push(decimals);
tokenInitialReserveBalance.push(initialBalance);
});
internalUseTokens = ["knc"];
listedTokens = ["knc"];
var exchangeInfo = ["binance"];
exchangeInfo.forEach(function(exchange) {
exchanges.push(exchange);
});
supportedTokens = {
"binance": [
"knc"
]
};
reserveInitialEth = 16
});
it("Deploy Tokens", function() {
this.timeout(31000000);
tokenOwner = accounts[0];
return deployTokens(tokenOwner);
});
it("Create Central Bank", function() {
this.timeout(31000000);
var amount = (new BigNumber(10)).pow(40+18);
return Bank.new().then(function(instance) {
bank = instance;
return transferFundsToBank(
tokenOwner,
bank.address,
amount
);
}).then(function() {
return bank.depositEther({ value: 10 }); // Deposit 10 wei
});
});
it("Deploy Whitelist Contract", function() {
this.timeout(31000000);
return Whitelist.new(
accounts[0],
kgtInstance.address
).then(function(instance) {
whitelist = instance;
return whitelist.addOperator(accounts[0]);
}).then(function() {
return whitelist.setCategoryCap(0, 5000);
}).then(function() {
return whitelist.setCategoryCap(1, 0);
}).then(function() {
return whitelist.setCategoryCap(2, 1000);
}).then(function() {
// IMPORTANT: What is a user category?
// return whitelist.setUserCategory("0x9f1a678b0079773b5c4f5aa8573132d2b8bcb1e7", 1);
}).then(function() {
// IMPORTANT: What are categories?
// transfer kgt to this user to it will be treated as category 2.
// kgtInstance.transfer("0x089bAa07Eb9097031bABC99DBa4222D85521883E", 1);
}).then(function() {
return whitelist.setSgdToEthRate((new BigNumber(10).pow(15)).mul(2));
});
});
it("Deploy KyberNetwork Contract", function() {
this.timeout(31000000);
return Network.new(
contractDeployer,
{ gas: maxGas }
).then(function(instance) {
network = instance;
});
});
it("Deploy KyberNetworkProxy", function() {
this.timeout(31000000);
return NetworkProxy.new(
contractDeployer,
{ gas: maxGas }
).then(function(instance) {
networkProxy = instance;
});
});
it("Deploy ConversionRates Contract", function() {
this.timeout(31000000);
return ConversionRates.new(
accounts[0],
{ gas: maxGas }
).then(function(instance) {
conversionRates = instance;
return conversionRates.addOperator(
accounts[0],
{ from: accounts[0] }
);
});
});
it("Deploy Reserve and Deposit Tokens/ETH", function() {
this.timeout(30000000);
return Reserve.new(
network.address,
conversionRates.address,
contractDeployer,
{ gas:maxGas }
).then(function(instance) {
reserve = instance;
}).then(function() {
return conversionRates.setValidRateDurationInBlocks(new BigNumber(1000000));
}).then(function() {
return conversionRates.setReserveAddress(reserve.address);
}).then(function() {
// IMPORTANT: UNCOMMENT if you want to exchange KNC for ETH
// var amount = new BigNumber(5).mul(10**18);
// return sendEtherWithPromise(
// accounts[0],
// reserve.address,
// amount
// );
}).then(function() {
return depositTokensToReserve(tokenOwner, reserve);
});;
});
it("Deploy Exchange Contract", function() {
this.timeout(31000000);
return createExchanges(
tokenOwner,
bank.address
);
});
it("Deploy FeeBurner Contract and Configure", function() {
this.timeout(31000000);
return FeeBurner.new(
accounts[0],
kncInstance.address,
network.address
).then(function(instance) {
feeBurner = instance;
return feeBurner.addOperator(
accounts[0],
{ from:accounts[0] }
);
}).then(function(result) {
return kncInstance.approve(
feeBurner.address,
new BigNumber(10**18).mul(10000),
{ from: accounts[0] }
);
}).then(function() {
// set fees for reserve
// 0.25% from accounts
return feeBurner.setReserveData(
reserve.address,
25,
accounts[0]
);
}).then(function() {
return feeBurner.setWalletFees(0, 50);
}).then(function() {
return feeBurner.setTaxInBps(2000);
});
});
it("Deploy ExpectedRate Contract and Configure", function() {
this.timeout(31000000);
return ExpectedRate.new(network.address, accounts[0]).then(function(instance) {
expectedRate = instance;
}).then(function() {
return expectedRate.addOperator(accounts[0]);
}).then(function() {
return expectedRate.setWorstCaseRateFactor(500);
});
});
it("Configure NetworkProxy", function() {
this.timeout(31000000);
return networkProxy.setKyberNetworkContract(network.address);
});
it("Configure Network", function() {
this.timeout(31000000);
// Set Contract addresses and enable Network
return network.setWhiteList(whitelist.address).then(function() {
return network.setExpectedRate(expectedRate.address);
}).then(function(){
return network.setFeeBurner(feeBurner.address);
}).then(function(){
return network.setKyberProxy(networkProxy.address);
}).then(function(){
return network.setParams(50 * 10**9, 15); // 50 gwei, 15 negligible diff
}).then( function() {
return network.setEnable(true);
});
});
it("Add Reserve to Network", function() {
this.timeout(31000000);
return network.addReserve(reserve.address, true, { from: contractDeployer });
});
it("List Tokens on Network Contract", function() {
this.timeout(30000000);
return listTokens(
tokenOwner,
reserve,
network,
expBlock,
conversionRate,
counterConversionRate
);
});
// TODO: Understand these optimizations
// it("make some optimizations", function() {
//
// // send 1 twei to kyber network
// return tokenInstance[0].transfer(network.address, 0).then(function() {
//
// // send 1 wei of knc to fee burner
// return tokenInstance[0].transfer(accounts[3], 1);
//
// }).then(function() {
// return kncInstance.transfer(feeBurner.address, 1);
// }).then(function() {
// return tokenInstance[0].balanceOf(network.address);
// }).then(function(result) {
// console.log("balance", result.valueOf());
// });
// });
it("Set ETH to KNC Rate", function() {
return getBlockNumberWithPromise().then(function(blockNumber) {
return conversionRates.setBaseRate(
[tokenInstance[0].address],
[0x47d40a969bd7c0021],
[conversionRate],
[0],
[0],
blockNumber,
[0]
);
});
});
// it("Performs ETH for KNC exchange", function() {
// this.timeout(31000000);
// var kncAddress = tokenInstance[0].address;
// var ethAmount = 1 * 10**16;
// var rate = 0x47d40a969bd7c0021;
// var expectedKNC = (ethAmount * rate / 10**18) / (10**18 / 10**tokenDecimals[1]);
// var destAddress = accounts[3];
// return networkProxy.trade(
// ethAddress,
// ethAmount,
// kncAddress,
// destAddress,
// new BigNumber(2).pow(255),
// rate,
// 0,
// { value: ethAmount, gasPrice: 49 * 10**9 }
// ).then(function(result) {
// return tokenInstance[0].balanceOf(destAddress);
// }).then(function(result){
// if (result.valueOf() > expectedKNC.valueOf() + 100) {
// assert.fail("unexpected knc balance", result.valueOf(), expectedKNC.valueOf());
// }
// if (result.valueOf() < expectedKNC.valueOf() - 100) {
// assert.fail("unexpected knc balance", result.valueOf(), expectedKNC.valueOf());
// }
// }).then(function() {
// return tokenInstance[0].balanceOf(destAddress);
// }).then(function(result) {
// console.log("balance 2", result.valueOf());
// });
// });
// it("Performs KNC for ETH exchange", function() {
// this.timeout(31000000);
// var kncAddress = tokenInstance[0].address;
// var kncAmount = 10**tokenDecimals[1];
// var rate = conversionRate;
// var destAddress = accounts[3];
// return tokenInstance[0].approve(networkProxy.address, kncAmount).then(function() {
// return networkProxy.trade(
// kncAddress,
// kncAmount,
// ethAddress,
// destAddress,
// new BigNumber(2).pow(255),
// rate,
// 0,
// { value: 0, gasPrice: 49* 10**9 }
// );
// }).then(function(result){
// for (var i = 0; i < result.receipt.logs.length; i++) {
// console.log(result.receipt.logs[i].data);
// }
// });
// });
it("print addresses", function() {
tokensDict = {};
tokensDict["ETH"] = {
"address" : "0x" + ethAddress.toString(16),
"name" : "Ethereum",
"decimals" : 18,
"internal use": true,
"listed": true
};
for (var i = 0; i < tokenSymbol.length; i++) {
var symbol = tokenSymbol[i].toLowerCase();
tokenDict = {
"address" : tokenInstance[i].address,
"name" : tokenName[i],
"decimals" : tokenDecimals[i],
"internal use": internalUseTokens.indexOf(symbol) >= 0,
"listed": listedTokens.indexOf(symbol) >= 0
};
tokensDict[tokenSymbol[i]] = tokenDict;
}
exchangesDepositAddressesDict = {};
exchangesAddressDict = {};
for (var exchangeInd = 0; exchangeInd < exchanges.length; exchangeInd++) {
exchangesAddressDict[exchanges[exchangeInd]] = exchangesInstance[exchangeInd].address;
exchangesDepositAddressesDict[exchanges[exchangeInd]] = exchangeDepositAddresses[exchangeInd];
}
dict = { "Tokens" : tokensDict, "ExchangesAddress" : exchangesAddressDict, "Exchanges" : exchangesDepositAddressesDict };
dict["MockCentralBank"] = bank.address;
dict["KyberReserve"] = reserve.address;
dict["ConversionRates"] = conversionRates.address;
dict["KyberNetworkProxy"] = networkProxy.address;
dict["KyberNetwork"] = network.address;
dict["FeeBurner"] = feeBurner.address;
dict["KGT Address"] = kgtInstance.address;
var json = JSON.stringify(dict, null, 2);
console.log(json);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment