编译器
0.4.26+commit.4563c3fc
文件 1 的 8:ConversionRatesInterface.sol
pragma solidity ^0.4.18;
import "./ERC20Interface.sol";
interface ConversionRatesInterface {
function recordImbalance(
ERC20 token,
int buyAmount,
uint rateUpdateBlock,
uint currentBlock
)
public;
function getRate(ERC20 token, uint currentBlockNumber, bool buy, uint qty) public view returns(uint);
}
文件 2 的 8:ERC20Interface.sol
pragma solidity ^0.4.18;
interface ERC20 {
function totalSupply() public view returns (uint supply);
function balanceOf(address _owner) public view returns (uint balance);
function transfer(address _to, uint _value) public returns (bool success);
function transferFrom(address _from, address _to, uint _value) public returns (bool success);
function approve(address _spender, uint _value) public returns (bool success);
function allowance(address _owner, address _spender) public view returns (uint remaining);
function decimals() public view returns(uint digits);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
文件 3 的 8:KyberReserve.sol
pragma solidity ^0.4.18;
import "./ERC20Interface.sol";
import "./Utils.sol";
import "./Withdrawable.sol";
import "./ConversionRatesInterface.sol";
import "./SanityRatesInterface.sol";
import "./KyberReserveInterface.sol";
contract KyberReserve is KyberReserveInterface, Withdrawable, Utils {
address public kyberNetwork;
bool public tradeEnabled;
ConversionRatesInterface public conversionRatesContract;
SanityRatesInterface public sanityRatesContract;
mapping(bytes32=>bool) public approvedWithdrawAddresses;
mapping(address=>address) public tokenWallet;
function KyberReserve(address _kyberNetwork, ConversionRatesInterface _ratesContract, address _admin) public {
require(_admin != address(0));
require(_ratesContract != address(0));
require(_kyberNetwork != address(0));
kyberNetwork = _kyberNetwork;
conversionRatesContract = _ratesContract;
admin = _admin;
tradeEnabled = true;
}
event DepositToken(ERC20 token, uint amount);
function() public payable {
DepositToken(ETH_TOKEN_ADDRESS, msg.value);
}
event TradeExecute(
address indexed origin,
address src,
uint srcAmount,
address destToken,
uint destAmount,
address destAddress
);
function trade(
ERC20 srcToken,
uint srcAmount,
ERC20 destToken,
address destAddress,
uint conversionRate,
bool validate
)
public
payable
returns(bool)
{
require(tradeEnabled);
require(msg.sender == kyberNetwork);
require(doTrade(srcToken, srcAmount, destToken, destAddress, conversionRate, validate));
return true;
}
event TradeEnabled(bool enable);
function enableTrade() public onlyAdmin returns(bool) {
tradeEnabled = true;
TradeEnabled(true);
return true;
}
function disableTrade() public onlyAlerter returns(bool) {
tradeEnabled = false;
TradeEnabled(false);
return true;
}
event WithdrawAddressApproved(ERC20 token, address addr, bool approve);
function approveWithdrawAddress(ERC20 token, address addr, bool approve) public onlyAdmin {
approvedWithdrawAddresses[keccak256(token, addr)] = approve;
WithdrawAddressApproved(token, addr, approve);
setDecimals(token);
if ((tokenWallet[token] == address(0x0)) && (token != ETH_TOKEN_ADDRESS)) {
tokenWallet[token] = this;
require(token.approve(this, 2 ** 255));
}
}
event NewTokenWallet(ERC20 token, address wallet);
function setTokenWallet(ERC20 token, address wallet) public onlyAdmin {
require(wallet != address(0x0));
tokenWallet[token] = wallet;
NewTokenWallet(token, wallet);
}
event WithdrawFunds(ERC20 token, uint amount, address destination);
function withdraw(ERC20 token, uint amount, address destination) public onlyOperator returns(bool) {
require(approvedWithdrawAddresses[keccak256(token, destination)]);
if (token == ETH_TOKEN_ADDRESS) {
destination.transfer(amount);
} else {
require(token.transferFrom(tokenWallet[token], destination, amount));
}
WithdrawFunds(token, amount, destination);
return true;
}
event SetContractAddresses(address network, address rate, address sanity);
function setContracts(
address _kyberNetwork,
ConversionRatesInterface _conversionRates,
SanityRatesInterface _sanityRates
)
public
onlyAdmin
{
require(_kyberNetwork != address(0));
require(_conversionRates != address(0));
kyberNetwork = _kyberNetwork;
conversionRatesContract = _conversionRates;
sanityRatesContract = _sanityRates;
SetContractAddresses(kyberNetwork, conversionRatesContract, sanityRatesContract);
}
function getBalance(ERC20 token) public view returns(uint) {
if (token == ETH_TOKEN_ADDRESS)
return this.balance;
else {
address wallet = tokenWallet[token];
uint balanceOfWallet = token.balanceOf(wallet);
uint allowanceOfWallet = token.allowance(wallet, this);
return (balanceOfWallet < allowanceOfWallet) ? balanceOfWallet : allowanceOfWallet;
}
}
function getDestQty(ERC20 src, ERC20 dest, uint srcQty, uint rate) public view returns(uint) {
uint dstDecimals = getDecimals(dest);
uint srcDecimals = getDecimals(src);
return calcDstQty(srcQty, srcDecimals, dstDecimals, rate);
}
function getSrcQty(ERC20 src, ERC20 dest, uint dstQty, uint rate) public view returns(uint) {
uint dstDecimals = getDecimals(dest);
uint srcDecimals = getDecimals(src);
return calcSrcQty(dstQty, srcDecimals, dstDecimals, rate);
}
function getConversionRate(ERC20 src, ERC20 dest, uint srcQty, uint blockNumber) public view returns(uint) {
ERC20 token;
bool isBuy;
if (!tradeEnabled) return 0;
if (ETH_TOKEN_ADDRESS == src) {
isBuy = true;
token = dest;
} else if (ETH_TOKEN_ADDRESS == dest) {
isBuy = false;
token = src;
} else {
return 0;
}
uint rate = conversionRatesContract.getRate(token, blockNumber, isBuy, srcQty);
uint destQty = getDestQty(src, dest, srcQty, rate);
if (getBalance(dest) < destQty) return 0;
if (sanityRatesContract != address(0)) {
uint sanityRate = sanityRatesContract.getSanityRate(src, dest);
if (rate > sanityRate) return 0;
}
return rate;
}
function doTrade(
ERC20 srcToken,
uint srcAmount,
ERC20 destToken,
address destAddress,
uint conversionRate,
bool validate
)
internal
returns(bool)
{
if (validate) {
require(conversionRate > 0);
if (srcToken == ETH_TOKEN_ADDRESS)
require(msg.value == srcAmount);
else
require(msg.value == 0);
}
uint destAmount = getDestQty(srcToken, destToken, srcAmount, conversionRate);
require(destAmount > 0);
ERC20 token;
int tradeAmount;
if (srcToken == ETH_TOKEN_ADDRESS) {
tradeAmount = int(destAmount);
token = destToken;
} else {
tradeAmount = -1 * int(srcAmount);
token = srcToken;
}
conversionRatesContract.recordImbalance(
token,
tradeAmount,
0,
block.number
);
if (srcToken != ETH_TOKEN_ADDRESS) {
require(srcToken.transferFrom(msg.sender, tokenWallet[srcToken], srcAmount));
}
if (destToken == ETH_TOKEN_ADDRESS) {
destAddress.transfer(destAmount);
} else {
require(destToken.transferFrom(tokenWallet[destToken], destAddress, destAmount));
}
TradeExecute(msg.sender, srcToken, srcAmount, destToken, destAmount, destAddress);
return true;
}
}
文件 4 的 8:KyberReserveInterface.sol
pragma solidity ^0.4.18;
import "./ERC20Interface.sol";
interface KyberReserveInterface {
function trade(
ERC20 srcToken,
uint srcAmount,
ERC20 destToken,
address destAddress,
uint conversionRate,
bool validate
)
public
payable
returns(bool);
function getConversionRate(ERC20 src, ERC20 dest, uint srcQty, uint blockNumber) public view returns(uint);
}
文件 5 的 8:PermissionGroups.sol
pragma solidity ^0.4.18;
contract PermissionGroups {
address public admin;
address public pendingAdmin;
mapping(address=>bool) internal operators;
mapping(address=>bool) internal alerters;
address[] internal operatorsGroup;
address[] internal alertersGroup;
uint constant internal MAX_GROUP_SIZE = 50;
function PermissionGroups() public {
admin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == admin);
_;
}
modifier onlyOperator() {
require(operators[msg.sender]);
_;
}
modifier onlyAlerter() {
require(alerters[msg.sender]);
_;
}
function getOperators () external view returns(address[]) {
return operatorsGroup;
}
function getAlerters () external view returns(address[]) {
return alertersGroup;
}
event TransferAdminPending(address pendingAdmin);
function transferAdmin(address newAdmin) public onlyAdmin {
require(newAdmin != address(0));
TransferAdminPending(pendingAdmin);
pendingAdmin = newAdmin;
}
function transferAdminQuickly(address newAdmin) public onlyAdmin {
require(newAdmin != address(0));
TransferAdminPending(newAdmin);
AdminClaimed(newAdmin, admin);
admin = newAdmin;
}
event AdminClaimed( address newAdmin, address previousAdmin);
function claimAdmin() public {
require(pendingAdmin == msg.sender);
AdminClaimed(pendingAdmin, admin);
admin = pendingAdmin;
pendingAdmin = address(0);
}
event AlerterAdded (address newAlerter, bool isAdd);
function addAlerter(address newAlerter) public onlyAdmin {
require(!alerters[newAlerter]);
require(alertersGroup.length < MAX_GROUP_SIZE);
AlerterAdded(newAlerter, true);
alerters[newAlerter] = true;
alertersGroup.push(newAlerter);
}
function removeAlerter (address alerter) public onlyAdmin {
require(alerters[alerter]);
alerters[alerter] = false;
for (uint i = 0; i < alertersGroup.length; ++i) {
if (alertersGroup[i] == alerter) {
alertersGroup[i] = alertersGroup[alertersGroup.length - 1];
alertersGroup.length--;
AlerterAdded(alerter, false);
break;
}
}
}
event OperatorAdded(address newOperator, bool isAdd);
function addOperator(address newOperator) public onlyAdmin {
require(!operators[newOperator]);
require(operatorsGroup.length < MAX_GROUP_SIZE);
OperatorAdded(newOperator, true);
operators[newOperator] = true;
operatorsGroup.push(newOperator);
}
function removeOperator (address operator) public onlyAdmin {
require(operators[operator]);
operators[operator] = false;
for (uint i = 0; i < operatorsGroup.length; ++i) {
if (operatorsGroup[i] == operator) {
operatorsGroup[i] = operatorsGroup[operatorsGroup.length - 1];
operatorsGroup.length -= 1;
OperatorAdded(operator, false);
break;
}
}
}
}
文件 6 的 8:SanityRatesInterface.sol
pragma solidity ^0.4.18;
import "./ERC20Interface.sol";
interface SanityRatesInterface {
function getSanityRate(ERC20 src, ERC20 dest) public view returns(uint);
}
文件 7 的 8:Utils.sol
pragma solidity ^0.4.18;
import "./ERC20Interface.sol";
contract Utils {
ERC20 constant internal ETH_TOKEN_ADDRESS = ERC20(0x00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee);
uint constant internal PRECISION = (10**18);
uint constant internal MAX_QTY = (10**28);
uint constant internal MAX_RATE = (PRECISION * 10**6);
uint constant internal MAX_DECIMALS = 18;
uint constant internal ETH_DECIMALS = 18;
mapping(address=>uint) internal decimals;
function setDecimals(ERC20 token) internal {
if (token == ETH_TOKEN_ADDRESS) decimals[token] = ETH_DECIMALS;
else decimals[token] = token.decimals();
}
function getDecimals(ERC20 token) internal view returns(uint) {
if (token == ETH_TOKEN_ADDRESS) return ETH_DECIMALS;
uint tokenDecimals = decimals[token];
if(tokenDecimals == 0) return token.decimals();
return tokenDecimals;
}
function calcDstQty(uint srcQty, uint srcDecimals, uint dstDecimals, uint rate) internal pure returns(uint) {
require(srcQty <= MAX_QTY);
require(rate <= MAX_RATE);
if (dstDecimals >= srcDecimals) {
require((dstDecimals - srcDecimals) <= MAX_DECIMALS);
return (srcQty * rate * (10**(dstDecimals - srcDecimals))) / PRECISION;
} else {
require((srcDecimals - dstDecimals) <= MAX_DECIMALS);
return (srcQty * rate) / (PRECISION * (10**(srcDecimals - dstDecimals)));
}
}
function calcSrcQty(uint dstQty, uint srcDecimals, uint dstDecimals, uint rate) internal pure returns(uint) {
require(dstQty <= MAX_QTY);
require(rate <= MAX_RATE);
uint numerator;
uint denominator;
if (srcDecimals >= dstDecimals) {
require((srcDecimals - dstDecimals) <= MAX_DECIMALS);
numerator = (PRECISION * dstQty * (10**(srcDecimals - dstDecimals)));
denominator = rate;
} else {
require((dstDecimals - srcDecimals) <= MAX_DECIMALS);
numerator = (PRECISION * dstQty);
denominator = (rate * (10**(dstDecimals - srcDecimals)));
}
return (numerator + denominator - 1) / denominator;
}
}
文件 8 的 8:Withdrawable.sol
pragma solidity ^0.4.18;
import "./ERC20Interface.sol";
import "./PermissionGroups.sol";
contract Withdrawable is PermissionGroups {
event TokenWithdraw(ERC20 token, uint amount, address sendTo);
function withdrawToken(ERC20 token, uint amount, address sendTo) external onlyAdmin {
require(token.transfer(sendTo, amount));
TokenWithdraw(token, amount, sendTo);
}
event EtherWithdraw(uint amount, address sendTo);
function withdrawEther(uint amount, address sendTo) external onlyAdmin {
sendTo.transfer(amount);
EtherWithdraw(amount, sendTo);
}
}
{
"compilationTarget": {
"KyberReserve.sol": "KyberReserve"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[],"name":"enableTrade","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"alerter","type":"address"}],"name":"removeAlerter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"wallet","type":"address"}],"name":"setTokenWallet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"pendingAdmin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOperators","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"amount","type":"uint256"},{"name":"sendTo","type":"address"}],"name":"withdrawToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newAlerter","type":"address"}],"name":"addAlerter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sanityRatesContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"addr","type":"address"},{"name":"approve","type":"bool"}],"name":"approveWithdrawAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"amount","type":"uint256"},{"name":"destination","type":"address"}],"name":"withdraw","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"disableTrade","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"srcToken","type":"address"},{"name":"srcAmount","type":"uint256"},{"name":"destToken","type":"address"},{"name":"destAddress","type":"address"},{"name":"conversionRate","type":"uint256"},{"name":"validate","type":"bool"}],"name":"trade","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"claimAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"transferAdminQuickly","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getAlerters","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"dest","type":"address"},{"name":"srcQty","type":"uint256"},{"name":"blockNumber","type":"uint256"}],"name":"getConversionRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOperator","type":"address"}],"name":"addOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"dest","type":"address"},{"name":"dstQty","type":"uint256"},{"name":"rate","type":"uint256"}],"name":"getSrcQty","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"tokenWallet","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"operator","type":"address"}],"name":"removeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_kyberNetwork","type":"address"},{"name":"_conversionRates","type":"address"},{"name":"_sanityRates","type":"address"}],"name":"setContracts","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"kyberNetwork","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"},{"name":"sendTo","type":"address"}],"name":"withdrawEther","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"conversionRatesContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tradeEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"approvedWithdrawAddresses","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"dest","type":"address"},{"name":"srcQty","type":"uint256"},{"name":"rate","type":"uint256"}],"name":"getDestQty","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_kyberNetwork","type":"address"},{"name":"_ratesContract","type":"address"},{"name":"_admin","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"DepositToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"origin","type":"address"},{"indexed":false,"name":"src","type":"address"},{"indexed":false,"name":"srcAmount","type":"uint256"},{"indexed":false,"name":"destToken","type":"address"},{"indexed":false,"name":"destAmount","type":"uint256"},{"indexed":false,"name":"destAddress","type":"address"}],"name":"TradeExecute","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"enable","type":"bool"}],"name":"TradeEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"addr","type":"address"},{"indexed":false,"name":"approve","type":"bool"}],"name":"WithdrawAddressApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"wallet","type":"address"}],"name":"NewTokenWallet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"destination","type":"address"}],"name":"WithdrawFunds","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"network","type":"address"},{"indexed":false,"name":"rate","type":"address"},{"indexed":false,"name":"sanity","type":"address"}],"name":"SetContractAddresses","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"sendTo","type":"address"}],"name":"TokenWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"sendTo","type":"address"}],"name":"EtherWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"pendingAdmin","type":"address"}],"name":"TransferAdminPending","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newAdmin","type":"address"},{"indexed":false,"name":"previousAdmin","type":"address"}],"name":"AdminClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newAlerter","type":"address"},{"indexed":false,"name":"isAdd","type":"bool"}],"name":"AlerterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newOperator","type":"address"},{"indexed":false,"name":"isAdd","type":"bool"}],"name":"OperatorAdded","type":"event"}]