pragma solidity ^0.4.22;
//Math operations with safety checks that throw on error
library SafeMath {
//multiply
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
//divide
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws 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;
}
//subtract
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
//addition
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract Ownable {
address public contractOwner;
event TransferredOwnership(address indexed _previousOwner, address indexed _newOwner);
constructor() public {
contractOwner = msg.sender;
}
modifier ownerOnly() {
require(msg.sender == contractOwner);
_;
}
function transferOwnership(address _newOwner) internal ownerOnly {
require(_newOwner != address(0));
contractOwner = _newOwner;
emit TransferredOwnership(contractOwner, _newOwner);
}
}
// Natmin vesting contract for team members
contract SalientVesting is Ownable {
struct Vesting {
uint256 amount;
uint256 endTime;
}
mapping(address => Vesting) internal vestings;
function addVesting(address _user, uint256 _amount, uint256 _endTime) public ;
function getVestedAmount(address _user) public view returns (uint256 _amount);
function getVestingEndTime(address _user) public view returns (uint256 _endTime);
function vestingEnded(address _user) public view returns (bool) ;
function endVesting(address _user) public ;
}
//ERC20 Standard interface specification
contract ERC20Standard {
function balanceOf(address _user) public view returns (uint256 balance);
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);
function allowance(address _owner, address _spender) public view returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
//ERC223 Standard interface specification
contract ERC223Standard {
function transfer(address _to, uint256 _value, bytes _data) public returns (bool success);
event Transfer(address indexed _from, address indexed _to, uint _value, bytes _data);
}
//ERC223 function to handle incoming token transfers
contract ERC223ReceivingContract {
function tokenFallback(address _from, uint256 _value, bytes _data) public;
}
contract BurnToken is Ownable {
using SafeMath for uint256;
function burn(uint256 _value) public;
function _burn(address _user, uint256 _value) internal;
event Burn(address indexed _user, uint256 _value);
}
//Salient implements the ERC20, ERC223 standard methods
contract Salient is ERC20Standard, ERC223Standard, Ownable, SalientVesting, BurnToken {
using SafeMath for uint256;
string _name = "Salient Investment Holding";
string _symbol = "SIH";
string _standard = "ERC20 / ERC223";
uint256 _decimals = 18; // same value as wei
uint256 _totalSupply;
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowed;
constructor(uint256 _supply) public {
require(_supply != 0);
_totalSupply = _supply * (10 ** 18);
balances[contractOwner] = _totalSupply;
}
// Returns the _name of the token
function name() public view returns (string) {
return _name;
}
// Returns the _symbol of the token
function symbol() public view returns (string) {
return _symbol;
}
// Returns the _standard of the token
function standard() public view returns (string) {
return _standard;
}
// Returns the _decimals of the token
function decimals() public view returns (uint256) {
return _decimals;
}
// Function to return the total supply of the token
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
// Function to return the balance of a specified address
function balanceOf(address _user) public view returns (uint256 balance){
return balances[_user];
}
// Transfer function to be compatable with ERC20 Standard
function transfer(address _to, uint256 _value) public returns (bool success){
require(_to != 0x0);
bytes memory _empty;
if(isContract(_to)){
return transferToContract(_to, _value, _empty);
}else{
return transferToAddress(_to, _value, _empty);
}
}
// Transfer function to be compatable with ERC223 Standard
function transfer(address _to, uint256 _value, bytes _data) public returns (bool success) {
require(_to != 0x0);
if(isContract(_to)){
return transferToContract(_to, _value, _data);
}else{
return transferToAddress(_to, _value, _data);
}
}
// This function checks if the address is a contract or wallet
// If the codeLength is greater than 0, it is a contract
function isContract(address _to) internal view returns (bool) {
uint256 _codeLength;
assembly {
_codeLength := extcodesize(_to)
}
return _codeLength > 0;
}
// This function to be used if the target is a contract address
function transferToContract(address _to, uint256 _value, bytes _data) internal returns (bool) {
require(balances[msg.sender] >= _value);
require(validateTransferAmount(msg.sender,_value));
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
ERC223ReceivingContract _tokenReceiver = ERC223ReceivingContract(_to);
_tokenReceiver.tokenFallback(msg.sender, _value, _data);
emit Transfer(msg.sender, _to, _value);
emit Transfer(msg.sender, _to, _value, _data);
return true;
}
// This function to be used if the target is a normal eth/wallet address
function transferToAddress(address _to, uint256 _value, bytes _data) internal returns (bool) {
require(balances[msg.sender] >= _value);
require(validateTransferAmount(msg.sender,_value));
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
emit Transfer(msg.sender, _to, _value, _data);
return true;
}
// ERC20 standard function
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){
require(_to != 0x0);
require(_value <= allowed[_from][msg.sender]);
require(_value <= balances[_from]);
require(validateTransferAmount(_from,_value));
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
emit Transfer(_from, _to, _value);
return true;
}
// ERC20 standard function
function approve(address _spender, uint256 _value) public returns (bool success){
allowed[msg.sender][_spender] = 0;
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
// ERC20 standard function
function allowance(address _owner, address _spender) public view returns (uint256 remaining){
return allowed[_owner][_spender];
}
// Stops any attempt from sending Ether to this contract
function () public {
revert();
}
// public function to call the _burn function
function burn(uint256 _value) public ownerOnly {
_burn(msg.sender, _value);
}
// Burn the specified amount of tokens by the owner
function _burn(address _user, uint256 _value) internal ownerOnly {
require(balances[_user] >= _value);
balances[_user] = balances[_user].sub(_value);
_totalSupply = _totalSupply.sub(_value);
emit Burn(_user, _value);
emit Transfer(_user, address(0), _value);
bytes memory _empty;
emit Transfer(_user, address(0), _value, _empty);
}
// Create a vesting entry for the specified user
function addVesting(address _user, uint256 _amount, uint256 _endTime) public ownerOnly {
vestings[_user].amount = _amount;
vestings[_user].endTime = _endTime;
}
// Returns the vested amount for a specified user
function getVestedAmount(address _user) public view returns (uint256 _amount) {
_amount = vestings[_user].amount;
return _amount;
}
// Returns the vested end time for a specified user
function getVestingEndTime(address _user) public view returns (uint256 _endTime) {
_endTime = vestings[_user].endTime;
return _endTime;
}
// Checks if the venting period is over for a specified user
function vestingEnded(address _user) public view returns (bool) {
if(vestings[_user].endTime <= now) {
return true;
}
else {
return false;
}
}
// This function checks the transfer amount against the current balance and vested amount
// Returns true if transfer amount is smaller than the difference between the balance and vested amount
function validateTransferAmount(address _user, uint256 _amount) internal view returns (bool) {
if(vestingEnded(_user)){
return true;
}else{
uint256 _vestedAmount = getVestedAmount(_user);
uint256 _currentBalance = balanceOf(_user);
uint256 _availableBalance = _currentBalance.sub(_vestedAmount);
if(_amount <= _availableBalance) {
return true;
}else{
return false;
}
}
}
// Manual end vested time
function endVesting(address _user) public ownerOnly {
vestings[_user].endTime = now;
}
}
{
"compilationTarget": {
"Salient.sol": "Salient"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_user","type":"address"}],"name":"getVestingEndTime","outputs":[{"name":"_endTime","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_user","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_endTime","type":"uint256"}],"name":"addVesting","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"standard","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_user","type":"address"}],"name":"endVesting","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"contractOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_user","type":"address"}],"name":"getVestedAmount","outputs":[{"name":"_amount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_user","type":"address"}],"name":"vestingEnded","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_supply","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":false,"stateMutability":"nonpayable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_user","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_previousOwner","type":"address"},{"indexed":true,"name":"_newOwner","type":"address"}],"name":"TransferredOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"},{"indexed":false,"name":"_data","type":"bytes"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]