Contract Source Code:
File 1 of 1 : OMNIS
pragma solidity 0.4.25;
/**
_____ __ __ ______ ____ ____ ______ ______
/\ __`\ /'\_/`\ /\ \/\ \ /\__ _\ /\ _`\ /\ _`\ /\__ _\ /\__ _\
\ \ \/\ \ /\ \ \ \ `\\ \ \/_/\ \/ \ \,\L\_\ \ \ \L\ \ \/_/\ \/ \/_/\ \/
\ \ \ \ \ \ \ \__\ \ \ \ , ` \ \ \ \ \/_\__ \ _______ \ \ _ <' \ \ \ \ \ \
\ \ \_\ \ \ \ \_/\ \ \ \ \`\ \ \_\ \__ /\ \L\ \ /\______\ \ \ \L\ \ \_\ \__ \ \ \
\ \_____\ \ \_\\ \_\ \ \_\ \_\ /\_____\ \ `\____\\/______/ \ \____/ /\_____\ \ \_\
\/_____/ \/_/ \/_/ \/_/\/_/ \/_____/ \/_____/ \/___/ \/_____/ \/_/
WEBSITE: omnis-bit.com
*/
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns(uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
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;
}
function sub(uint256 a, uint256 b) internal pure returns(uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns(uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner public {
require(newOwner != address(0));
owner = newOwner;
}
}
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/179
*/
contract ERC20Basic {
uint256 public totalSupply;
function balanceOf(address who) public view returns(uint256);
function transfer(address to, uint256 value) public returns(bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20 is ERC20Basic {
function allowance(address owner, address spender) public view returns(uint256);
function transferFrom(address from, address to, uint256 value) public returns(bool);
function approve(address spender, uint256 value) public returns(bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract StakerToken {
uint256 public stakeStartTime;
uint256 public stakeMinAge;
uint256 public stakeMaxAge;
function claimStake() public returns(bool);
function coinAge() public view returns(uint256);
function annualInterest() public view returns(uint256);
event ClaimStake(address indexed _address, uint _reward);
}
contract OMNIS is ERC20, StakerToken, Ownable {
using SafeMath
for uint256;
string public name = "OMNIS-BIT";
string public symbol = "OMNIS";
uint public decimals = 18;
uint public chainStartTime;
uint public chainStartBlockNumber;
uint public stakeStartTime;
uint public stakeMinAge = 3 days;
uint public stakeMaxAge = 90 days;
uint public totalSupply;
uint public maxTotalSupply;
uint public totalInitialSupply;
struct Airdrop {
uint value;
bool claimed;
}
mapping(address => Airdrop) public airdrops;
//ESCROW RELATED
enum PaymentStatus {
Pending,
Completed,
Refunded
}
event NewFeeRate(uint newFee);
event NewCollectionWallet(address newWallet);
event PaymentCreation(uint indexed orderId, address indexed customer, uint value);
event PaymentCompletion(uint indexed orderId, address indexed provider, address indexed customer, uint value, PaymentStatus status);
struct Payment {
address provider;
address customer;
uint value;
PaymentStatus status;
bool refundApproved;
}
uint escrowCounter;
uint public escrowFeePercent = 5; //0.5%
mapping(uint => Payment) public payments;
address public collectionAddress;
//ESCROW SECTION END
struct transferInStruct {
uint128 amount;
uint64 time;
}
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowed;
mapping(address => transferInStruct[]) transferIns;
modifier canPoSclaimStake() {
require(totalSupply < maxTotalSupply);
_;
}
constructor() public {
maxTotalSupply = 1000000000 * 10 ** 18;
totalInitialSupply = 820000000 * 10 ** 18;
chainStartTime = now; //Original Time
chainStartBlockNumber = block.number; //Original Block
totalSupply = totalInitialSupply;
collectionAddress = msg.sender; //Initially collection address to owner
balances[msg.sender] = totalInitialSupply;
emit Transfer(address(0), msg.sender, totalInitialSupply);
}
function setCurrentEscrowFee(uint _newFee) onlyOwner public {
require(_newFee != 0 && _newFee < 1000);
escrowFeePercent = _newFee;
emit NewFeeRate(escrowFeePercent);
}
function setCollectionWallet(address _newWallet) onlyOwner public {
require(_newWallet != address(0));
collectionAddress = _newWallet;
emit NewCollectionWallet(collectionAddress);
}
function transfer(address _to, uint256 _value) public returns(bool) {
require(_to != address(0));
if (msg.sender == _to) return claimStake();
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
if (transferIns[msg.sender].length > 0) delete transferIns[msg.sender];
uint64 _now = uint64(now);
transferIns[msg.sender].push(transferInStruct(uint128(balances[msg.sender]), _now));
transferIns[_to].push(transferInStruct(uint128(_value), _now));
return true;
}
function balanceOf(address _owner) public view returns(uint256 balance) {
return balances[_owner];
}
function transferFrom(address _from, address _to, uint256 _value) public returns(bool) {
require(_to != address(0));
uint256 _allowance = allowed[_from][msg.sender];
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = _allowance.sub(_value);
emit Transfer(_from, _to, _value);
if (transferIns[_from].length > 0) delete transferIns[_from];
uint64 _now = uint64(now);
transferIns[_from].push(transferInStruct(uint128(balances[_from]), _now));
transferIns[_to].push(transferInStruct(uint128(_value), _now));
return true;
}
function approve(address _spender, uint256 _value) public returns(bool) {
require((_value == 0) || (allowed[msg.sender][_spender] == 0));
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public view returns(uint256 remaining) {
return allowed[_owner][_spender];
}
/**
* @dev claimStake
* @dev Allow any user to claim stake earned
*/
function claimStake() canPoSclaimStake public returns(bool) {
if (balances[msg.sender] <= 0) return false;
if (transferIns[msg.sender].length <= 0) return false;
uint reward = getProofOfStakeReward(msg.sender);
if (reward <= 0) return false;
totalSupply = totalSupply.add(reward);
balances[msg.sender] = balances[msg.sender].add(reward);
delete transferIns[msg.sender];
transferIns[msg.sender].push(transferInStruct(uint128(balances[msg.sender]), uint64(now)));
emit Transfer(address(0),msg.sender,reward);
emit ClaimStake(msg.sender, reward);
return true;
}
/**
* @dev getBlockNumber
* @dev Returns the block number since deployment
*/
function getBlockNumber() public view returns(uint blockNumber) {
blockNumber = block.number.sub(chainStartBlockNumber);
}
/**
* @dev coinAge
* @dev Returns the coinage for the callers account
*/
function coinAge() public view returns(uint myCoinAge) {
myCoinAge = getCoinAge(msg.sender, now);
}
/**
* @dev annualInterest
* @dev Returns the current interest rate
*/
function annualInterest() public view returns(uint interest) {
uint _now = now;
interest = 0;
if ((_now.sub(stakeStartTime)).div(365 days) == 0) {
interest = (106 * 1e15);
} else if ((_now.sub(stakeStartTime)).div(365 days) == 1) {
interest = (49 * 1e15);
} else if ((_now.sub(stakeStartTime)).div(365 days) == 2) {
interest = (24 * 1e15);
} else if ((_now.sub(stakeStartTime)).div(365 days) == 3) {
interest = (13 * 1e15);
} else if ((_now.sub(stakeStartTime)).div(365 days) == 4) {
interest = (11 * 1e15);
}
}
/**
* @dev getProofOfStakeReward
* @dev Returns the current stake of a wallet
* @param _address is the user wallet
*/
function getProofOfStakeReward(address _address) public view returns(uint) {
require((now >= stakeStartTime) && (stakeStartTime > 0));
uint _now = now;
uint _coinAge = getCoinAge(_address, _now);
if (_coinAge <= 0) return 0;
uint interest = 0;
if ((_now.sub(stakeStartTime)).div(365 days) == 0) {
interest = (106 * 1e15);
} else if ((_now.sub(stakeStartTime)).div(365 days) == 1) {
interest = (49 * 1e15);
} else if ((_now.sub(stakeStartTime)).div(365 days) == 2) {
interest = (24 * 1e15);
} else if ((_now.sub(stakeStartTime)).div(365 days) == 3) {
interest = (13 * 1e15);
} else if ((_now.sub(stakeStartTime)).div(365 days) == 4) {
interest = (11 * 1e1);
}
return (_coinAge * interest).div(365 * (10 ** decimals));
}
function getCoinAge(address _address, uint _now) internal view returns(uint _coinAge) {
if (transferIns[_address].length <= 0) return 0;
for (uint i = 0; i < transferIns[_address].length; i++) {
if (_now < uint(transferIns[_address][i].time).add(stakeMinAge)) continue;
uint nCoinSeconds = _now.sub(uint(transferIns[_address][i].time));
if (nCoinSeconds > stakeMaxAge) nCoinSeconds = stakeMaxAge;
_coinAge = _coinAge.add(uint(transferIns[_address][i].amount) * nCoinSeconds.div(1 days));
}
}
/**
* @dev ownerSetStakeStartTime
* @dev Used by the owner to define the staking period start
* @param timestamp time in UNIX format
*/
function ownerSetStakeStartTime(uint timestamp) onlyOwner public {
require((stakeStartTime <= 0) && (timestamp >= chainStartTime));
stakeStartTime = timestamp;
}
/**
* @dev batchTransfer
* @dev Used by the owner to deliver several transfers at the same time (Airdrop)
* @param _recipients Array of addresses
* @param _values Array of values
*/
function batchTransfer(address[] _recipients, uint[] _values) onlyOwner external returns(bool) {
//Check data sizes
require(_recipients.length > 0 && _recipients.length == _values.length);
//Total value calc
uint total = 0;
for (uint i = 0; i < _values.length; i++) {
total = total.add(_values[i]);
}
//Sender must hold funds
require(total <= balances[msg.sender]);
//Make transfers
uint64 _now = uint64(now);
for (uint j = 0; j < _recipients.length; j++) {
balances[_recipients[j]] = balances[_recipients[j]].add(_values[j]);
transferIns[_recipients[j]].push(transferInStruct(uint128(_values[j]), _now));
emit Transfer(msg.sender, _recipients[j], _values[j]);
}
//Reduce all balance on a single transaction from sender
balances[msg.sender] = balances[msg.sender].sub(total);
if (transferIns[msg.sender].length > 0) delete transferIns[msg.sender];
if (balances[msg.sender] > 0) transferIns[msg.sender].push(transferInStruct(uint128(balances[msg.sender]), _now));
return true;
}
/**
* @dev dropSet
* @dev Used by the owner to set several self-claiming drops at the same time (Airdrop)
* @param _recipients Array of addresses
* @param _values Array of values
*/
function dropSet(address[] _recipients, uint[] _values) onlyOwner external returns(bool) {
//Check data sizes
require(_recipients.length > 0 && _recipients.length == _values.length);
for (uint j = 0; j < _recipients.length; j++) {
//Store user drop info
airdrops[_recipients[j]].value = _values[j];
airdrops[_recipients[j]].claimed = false;
}
return true;
}
/**
* @dev claimAirdrop
* @dev Allow any user with a drop set to claim it
*/
function claimAirdrop() external returns(bool) {
//Check if not claimed
require(airdrops[msg.sender].claimed == false);
require(airdrops[msg.sender].value != 0);
//Set Claim to True
airdrops[msg.sender].claimed = true;
//Clear value
airdrops[msg.sender].value = 0;
//Tokens are on owner wallet
address _from = owner;
//Tokens goes to costumer
address _to = msg.sender;
//Original value
uint _value = airdrops[msg.sender].value;
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(_from, _to, _value);
if (transferIns[_from].length > 0) delete transferIns[_from];
uint64 _now = uint64(now);
transferIns[_from].push(transferInStruct(uint128(balances[_from]), _now));
transferIns[_to].push(transferInStruct(uint128(_value), _now));
return true;
}
//ESCROW SECTION
/**
* @dev createPayment
* @dev Allow a user to start a Escrow process
* @param _customer Counterpart that will receive payment on success
* @param _value Amount to be escrowed
*/
function createPayment(address _customer, uint _value) external returns(uint) {
address _to = address(this);
require(_value > 0);
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
if (transferIns[msg.sender].length > 0) delete transferIns[msg.sender];
uint64 _now = uint64(now);
transferIns[msg.sender].push(transferInStruct(uint128(balances[msg.sender]), _now));
payments[escrowCounter] = Payment(msg.sender, _customer, _value, PaymentStatus.Pending, false);
emit PaymentCreation(escrowCounter, _customer, _value);
escrowCounter = escrowCounter.add(1);
return escrowCounter - 1;
}
/**
* @dev release
* @dev Allow a user to release a payment
* @param _orderId Ticket number of the escrow service
*/
function release(uint _orderId) external returns(bool) {
//Get Payment Handler
Payment storage payment = payments[_orderId];
//Only if pending
require(payment.status == PaymentStatus.Pending);
//Only owner or token provider
require(msg.sender == owner || msg.sender == payment.provider);
//Tokens are on contract
address _from = address(this);
//Tokens goes to costumer
address _to = payment.customer;
//Original value
uint _value = payment.value;
//Fee calculation
uint _fee = _value.mul(escrowFeePercent).div(1000);
//Value less fees
_value = _value.sub(_fee);
//Costumer transfer
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(_from, _to, _value);
//collectionAddress fee recolection
balances[_from] = balances[_from].sub(_fee);
balances[collectionAddress] = balances[collectionAddress].add(_fee);
emit Transfer(_from, collectionAddress, _fee);
//Delete any staking from contract address itself
if (transferIns[_from].length > 0) delete transferIns[_from];
//Store staking information for receivers
uint64 _now = uint64(now);
//Costumer
transferIns[_to].push(transferInStruct(uint128(_value), _now));
//collectionAddress
transferIns[collectionAddress].push(transferInStruct(uint128(_fee), _now));
//Payment Escrow Completed
payment.status = PaymentStatus.Completed;
//Emit Event
emit PaymentCompletion(_orderId, payment.provider, payment.customer, payment.value, payment.status);
return true;
}
/**
* @dev refund
* @dev Allow a user to refund a payment
* @param _orderId Ticket number of the escrow service
*/
function refund(uint _orderId) external returns(bool) {
//Get Payment Handler
Payment storage payment = payments[_orderId];
//Only if pending
require(payment.status == PaymentStatus.Pending);
//Only if refund was approved
require(payment.refundApproved);
//Tokens are on contract
address _from = address(this);
//Tokens go back to provider
address _to = payment.provider;
//Original value
uint _value = payment.value;
//Provider transfer
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(_from, _to, _value);
//Delete any staking from contract address itself
if (transferIns[_from].length > 0) delete transferIns[_from];
//Store staking information for receivers
uint64 _now = uint64(now);
transferIns[_to].push(transferInStruct(uint128(_value), _now));
//Payment Escrow Refunded
payment.status = PaymentStatus.Refunded;
//Emit Event
emit PaymentCompletion(_orderId, payment.provider, payment.customer, payment.value, payment.status);
return true;
}
/**
* @dev approveRefund
* @dev Allow a user to approve a refund
* @param _orderId Ticket number of the escrow service
*/
function approveRefund(uint _orderId) external returns(bool) {
//Get Payment Handler
Payment storage payment = payments[_orderId];
//Only if pending
require(payment.status == PaymentStatus.Pending);
//Only owner or costumer
require(msg.sender == owner || msg.sender == payment.customer);
//Approve Refund
payment.refundApproved = true;
return true;
}
//ESCROW SECTION END
}