Contract Source Code Verified(Similar Match) Note: This contract matches the deployed ByteCode of the Verified Source Code for Contract 0x695192edbcdd5a13b63ec2cb917dd0ffedf83be9
pragma solidity ^0.4.24;
// File: bancor-contracts/solidity/contracts/utility/interfaces/IOwned.sol
/*
Owned contract interface
*/
contract IOwned {
// this function isn't abstract since the compiler emits automatically generated getter functions as external
function owner() public view returns (address) {}
function transferOwnership(address _newOwner) public;
function acceptOwnership() public;
}
// File: bancor-contracts/solidity/contracts/utility/Owned.sol
/*
Provides support and utilities for contract ownership
*/
contract Owned is IOwned {
address public owner;
address public newOwner;
event OwnerUpdate(address indexed _prevOwner, address indexed _newOwner);
/**
@dev constructor
*/
constructor() public {
owner = msg.sender;
}
// allows execution by the owner only
modifier ownerOnly {
require(msg.sender == owner);
_;
}
/**
@dev allows transferring the contract ownership
the new owner still needs to accept the transfer
can only be called by the contract owner
@param _newOwner new contract owner
*/
function transferOwnership(address _newOwner) public ownerOnly {
require(_newOwner != owner);
newOwner = _newOwner;
}
/**
@dev used by a new owner to accept an ownership transfer
*/
function acceptOwnership() public {
require(msg.sender == newOwner);
emit OwnerUpdate(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}
// File: bancor-contracts/solidity/contracts/utility/Utils.sol
/*
Utilities & Common Modifiers
*/
contract Utils {
/**
constructor
*/
constructor() public {
}
// verifies that an amount is greater than zero
modifier greaterThanZero(uint256 _amount) {
require(_amount > 0);
_;
}
// validates an address - currently only checks that it isn't null
modifier validAddress(address _address) {
require(_address != address(0));
_;
}
// verifies that the address is different than this contract address
modifier notThis(address _address) {
require(_address != address(this));
_;
}
// Overflow protected math functions
/**
@dev returns the sum of _x and _y, asserts if the calculation overflows
@param _x value 1
@param _y value 2
@return sum
*/
function safeAdd(uint256 _x, uint256 _y) internal pure returns (uint256) {
uint256 z = _x + _y;
assert(z >= _x);
return z;
}
/**
@dev returns the difference of _x minus _y, asserts if the subtraction results in a negative number
@param _x minuend
@param _y subtrahend
@return difference
*/
function safeSub(uint256 _x, uint256 _y) internal pure returns (uint256) {
assert(_x >= _y);
return _x - _y;
}
/**
@dev returns the product of multiplying _x by _y, asserts if the calculation overflows
@param _x factor 1
@param _y factor 2
@return product
*/
function safeMul(uint256 _x, uint256 _y) internal pure returns (uint256) {
uint256 z = _x * _y;
assert(_x == 0 || z / _x == _y);
return z;
}
}
// File: bancor-contracts/solidity/contracts/token/interfaces/IERC20Token.sol
/*
ERC20 Standard Token interface
*/
contract IERC20Token {
// these functions aren't abstract since the compiler emits automatically generated getter functions as external
function name() public view returns (string) {}
function symbol() public view returns (string) {}
function decimals() public view returns (uint8) {}
function totalSupply() public view returns (uint256) {}
function balanceOf(address _owner) public view returns (uint256) { _owner; }
function allowance(address _owner, address _spender) public view returns (uint256) { _owner; _spender; }
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
}
// File: bancor-contracts/solidity/contracts/utility/interfaces/ITokenHolder.sol
/*
Token Holder interface
*/
contract ITokenHolder is IOwned {
function withdrawTokens(IERC20Token _token, address _to, uint256 _amount) public;
}
// File: bancor-contracts/solidity/contracts/utility/TokenHolder.sol
/*
We consider every contract to be a 'token holder' since it's currently not possible
for a contract to deny receiving tokens.
The TokenHolder's contract sole purpose is to provide a safety mechanism that allows
the owner to send tokens that were sent to the contract by mistake back to their sender.
*/
contract TokenHolder is ITokenHolder, Owned, Utils {
/**
@dev constructor
*/
constructor() public {
}
/**
@dev withdraws tokens held by the contract and sends them to an account
can only be called by the owner
@param _token ERC20 token contract address
@param _to account to receive the new amount
@param _amount amount to withdraw
*/
function withdrawTokens(IERC20Token _token, address _to, uint256 _amount)
public
ownerOnly
validAddress(_token)
validAddress(_to)
notThis(_to)
{
assert(_token.transfer(_to, _amount));
}
}
// File: bancor-contracts/solidity/contracts/utility/interfaces/IContractRegistry.sol
/*
Contract Registry interface
*/
contract IContractRegistry {
function addressOf(bytes32 _contractName) public view returns (address);
// deprecated, backward compatibility
function getAddress(bytes32 _contractName) public view returns (address);
}
// File: openzeppelin-solidity/contracts/cryptography/ECDSA.sol
/**
* @title Elliptic curve signature operations
* @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
* TODO Remove this library once solidity supports passing a signature to ecrecover.
* See https://github.com/ethereum/solidity/issues/864
*/
library ECDSA {
/**
* @dev Recover signer address from a message by using their signature
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
* @param signature bytes signature, the signature is generated using web3.eth.sign()
*/
function recover(bytes32 hash, bytes signature)
internal
pure
returns (address)
{
bytes32 r;
bytes32 s;
uint8 v;
// Check the signature length
if (signature.length != 65) {
return (address(0));
}
// Divide the signature in r, s and v variables
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions
if (v < 27) {
v += 27;
}
// If the version is correct return the signer address
if (v != 27 && v != 28) {
return (address(0));
} else {
// solium-disable-next-line arg-overflow
return ecrecover(hash, v, r, s);
}
}
/**
* toEthSignedMessageHash
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
* and hash the result
*/
function toEthSignedMessageHash(bytes32 hash)
internal
pure
returns (bytes32)
{
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)
);
}
}
// File: openzeppelin-solidity/contracts/math/SafeMath.sol
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, 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 numbers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0); // Solidity only automatically asserts when dividing by 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 numbers, 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 numbers, 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 numbers 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: bancor-contracts/solidity/contracts/ContractIds.sol
/**
Id definitions for bancor contracts
Can be used in conjunction with the contract registry to get contract addresses
*/
contract ContractIds {
// generic
bytes32 public constant CONTRACT_FEATURES = "ContractFeatures";
bytes32 public constant CONTRACT_REGISTRY = "ContractRegistry";
// bancor logic
bytes32 public constant BANCOR_NETWORK = "BancorNetwork";
bytes32 public constant BANCOR_FORMULA = "BancorFormula";
bytes32 public constant BANCOR_GAS_PRICE_LIMIT = "BancorGasPriceLimit";
bytes32 public constant BANCOR_CONVERTER_UPGRADER = "BancorConverterUpgrader";
bytes32 public constant BANCOR_CONVERTER_FACTORY = "BancorConverterFactory";
// Ids of BNT converter and BNT token
bytes32 public constant BNT_TOKEN = "BNTToken";
bytes32 public constant BNT_CONVERTER = "BNTConverter";
// Id of BancorX contract
bytes32 public constant BANCOR_X = "BancorX";
}
// File: contracts/CoinVerseContractIds.sol
contract CoinVerseContractIds {
bytes32 public constant BNUS_TOKEN = "BnusToken";
bytes32 public constant CNUS_TOKEN = "CnusToken";
bytes32 public constant TOKEN_POOL = "TokenPool";
bytes32 public constant CNUS_POOL_FOR_STAKING = "CnusPoolForStaking";
}
// File: contracts/interfaces/ICnusPoolForStaking.sol
contract ICnusPoolForStaking {
/**
@dev can stake Cnus
@param _amount amount of Cnus to stake
@param _udid unique Device Id to prevent abusing
@param _signature signed udid with the private key of CoinUs wallet
*/
function stake(uint256 _amount, bytes _udid, uint256 _expiration, bytes _signature) public;
/**
@dev withdrawing for approved requests
@param _amount amount of Cnus to withdraw
@param _udid unique Device Id to prevent abusing
@param _signature signed udid with the private key of CoinUs wallet
*/
function withdraw(uint256 _amount, bytes _udid, uint256 _expiration, bytes _signature) public;
/**
@dev returns total amount of staked Cnus
*/
function getStakedAmount() public view returns (uint256);
function stakeOf(address _account) public view returns (uint256);
}
// File: contracts/CnusPoolForStaking.sol
contract CnusPoolForStaking is ICnusPoolForStaking, TokenHolder, CoinVerseContractIds {
using ECDSA for bytes32;
using SafeMath for uint256;
IContractRegistry registry;
address public coinUsAccount;
mapping(address => uint256) staking;
event Deposit(address indexed _account, uint256 _amount, uint256 _timestamp);
event Withdrawal(address indexed _account, uint256 _amount, uint256 _timestamp);
constructor() public {}
function setRegistry(address _registry) ownerOnly {
registry = IContractRegistry(_registry);
}
modifier coinUsOnly(uint256 _amount, bytes _udid, uint256 _expiration, bytes _signature) {
bytes32 hash = keccak256(abi.encodePacked(_amount, _udid, _expiration));
address _signer = hash.toEthSignedMessageHash().recover(_signature);
require(_signer == coinUsAccount);
_;
}
function setCoinUsAccount(address _account) public ownerOnly {
coinUsAccount = _account;
}
/**
@dev can stake Cnus
@param _amount amount of Cnus to stake
@param _udid unique Device Id to prevent abusing
@param _signature signed udid with the private key of CoinUs wallet
*/
function stake(uint256 _amount, bytes _udid, uint256 _expiration, bytes _signature)
public
coinUsOnly(_amount, _udid, _expiration, _signature)
{
IERC20Token(registry.addressOf(CNUS_TOKEN)).transferFrom(msg.sender, this, _amount);
staking[msg.sender] = staking[msg.sender].add(_amount);
emit Deposit(msg.sender, _amount, now);
}
/**
@dev withdrawing for approved requests
@param _amount amount of Cnus to withdraw
@param _udid unique Device Id to prevent abusing
@param _signature signed udid with the private key of CoinUs wallet
*/
function withdraw(uint256 _amount, bytes _udid, uint256 _expiration, bytes _signature)
public
coinUsOnly(_amount, _udid, _expiration, _signature)
{
require(staking[msg.sender] >= _amount);
IERC20Token(registry.addressOf(CNUS_TOKEN)).transfer(msg.sender, _amount);
staking[msg.sender] = staking[msg.sender].sub(_amount);
emit Withdrawal(msg.sender, _amount, now);
}
/**
@dev returns total amount of staked Cnus
*/
function getStakedAmount() public view returns (uint256) {
return stakeOf(msg.sender);
}
function stakeOf(address _account) public view returns (uint256) {
return staking[_account];
}
}