Created
September 18, 2018 10:17
-
-
Save asoong/ddaa9b732084ca8d32c07d3a13c4118d to your computer and use it in GitHub Desktop.
Kyber Contract TestRPC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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