Skip to content

Instantly share code, notes, and snippets.

@gorbunovperm
Created November 23, 2018 04:36
Show Gist options
  • Save gorbunovperm/f08ae6561b5584eb0bcfba0b4aaf2a94 to your computer and use it in GitHub Desktop.
Save gorbunovperm/f08ae6561b5584eb0bcfba0b4aaf2a94 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.24+commit.e67f0147.js&optimize=false&gist=
pragma solidity ^0.4.22;
import "./ERC20Basic.sol";
import "./SafeMath.sol";
/**
* @title Basic token
* @dev Basic version of StandardToken, with no allowances.
*/
contract BasicToken is ERC20Basic {
using SafeMath for uint256;
mapping(address => uint256) balances;
uint256 totalSupply_;
/**
* @dev total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
/**
* @dev transfer token for a specified address
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
*/
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[msg.sender]);
// SafeMath.sub will throw if there is not enough balance.
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
return true;
}
/**
* @dev Gets the balance of the specified address.
* @param _owner The address to query the the balance of.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
}
pragma solidity ^0.4.22;
import "./BasicToken.sol";
/**
* @title Burnable Token
* @dev Token that can be irreversibly burned (destroyed).
*/
contract BurnableToken is BasicToken {
event Burn(address indexed burner, uint256 value);
/**
* @dev Burns a specific amount of tokens.
* @param _value The amount of token to be burned.
*/
function burn(uint256 _value) public {
require(_value <= balances[msg.sender]);
// no need to require value <= totalSupply, since that would imply the
// sender's balance is greater than the totalSupply, which *should* be an assertion failure
address burner = msg.sender;
balances[burner] = balances[burner].sub(_value);
totalSupply_ = totalSupply_.sub(_value);
emit Burn(burner, _value);
emit Transfer(burner, address(0), _value);
}
}
pragma solidity ^0.4.22;
import "./ERC20Basic.sol";
/**
* @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);
}
pragma solidity ^0.4.22;
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/179
*/
contract ERC20Basic {
function totalSupply() public view returns (uint256);
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);
}
pragma solidity ^0.4.24;
contract IBonus {
function getCurrentDayBonus(uint startSaleDate, bool saleState) public view returns(uint);
function _currentDay(uint startSaleDate, bool saleState) public view returns(uint);
function getBonusData() public view returns(string);
function getPreSaleBonusPercent() public view returns(uint);
function getMinReachUsdPayInCents() public view returns(uint);
}
pragma solidity ^0.4.24;
contract ICurrency {
function getUsdAbsRaisedInCents() external view returns(uint);
function getCoinRaisedBonusInWei() external view returns(uint);
function getCoinRaisedInWei() public view returns(uint);
function getUsdFromETH(uint ethWei) public view returns(uint);
function getTokenFromETH(uint ethWei) public view returns(uint);
function getCurrencyRate(string _ticker) public view returns(uint);
function addPay(string _ticker, uint value, uint usdAmount, uint coinRaised, uint coinRaisedBonus) public returns(bool);
function checkTickerExists(string ticker) public view returns(bool);
function getUsdFromCurrency(string ticker, uint value) public view returns(uint);
function getUsdFromCurrency(string ticker, uint value, uint usd) public view returns(uint);
function getUsdFromCurrency(bytes32 ticker, uint value) public view returns(uint);
function getUsdFromCurrency(bytes32 ticker, uint value, uint usd) public view returns(uint);
function getTokenWeiFromUSD(uint usdCents) public view returns(uint);
function editPay(bytes32 ticker, uint currencyValue, uint currencyUsdRaised, uint _usdAbsRaisedInCents, uint _coinRaisedInWei, uint _coinRaisedBonusInWei) public returns(bool);
function getCurrencyList(string ticker) public view returns(bool active, uint usd, uint devision, uint raised, uint usdRaised, uint usdRaisedExchangeRate, uint counter, uint lastUpdate);
function getCurrencyList(bytes32 ticker) public view returns(bool active, uint usd, uint devision, uint raised, uint usdRaised, uint usdRaisedExchangeRate, uint counter, uint lastUpdate);
function getTotalUsdRaisedInCents() public view returns(uint);
function getAllCurrencyTicker() public view returns(string);
function getCoinUSDRate() public view returns(uint);
function addPreSaleBonus(uint bonusToken) public returns(bool);
function editPreSaleBonus(uint beforeBonus, uint afterBonus) public returns(bool);
}
pragma solidity ^0.4.24;
contract IStorage {
function processPreSaleBonus(uint minTotalUsdAmountInCents, uint bonusPercent, uint _start, uint _limit) external returns(uint);
function checkNeedProcessPreSaleBonus(uint minTotalUsdAmountInCents) external view returns(bool);
function getCountNeedProcessPreSaleBonus(uint minTotalUsdAmountInCents, uint start, uint limit) external view returns(uint);
function reCountUserPreSaleBonus(uint uId, uint minTotalUsdAmountInCents, uint bonusPercent, uint maxPayTime) external returns(uint, uint);
function getContributorIndexes(uint index) external view returns(uint);
function checkNeedSendSHPC(bool proc) external view returns(bool);
function getCountNeedSendSHPC(uint start, uint limit) external view returns(uint);
function checkETHRefund(bool proc) external view returns(bool);
function getCountETHRefund(uint start, uint limit) external view returns(uint);
function addPayment(address _addr, string pType, uint _value, uint usdAmount, uint currencyUSD, uint tokenWithoutBonus, uint tokenBonus, uint bonusPercent, uint payId) public returns(bool);
function addPayment(uint uId, string pType, uint _value, uint usdAmount, uint currencyUSD, uint tokenWithoutBonus, uint tokenBonus, uint bonusPercent, uint payId) public returns(bool);
function checkUserIdExists(uint uId) public view returns(bool);
function getContributorAddressById(uint uId) public view returns(address);
function editPaymentByUserId(uint uId, uint payId, uint _payValue, uint _usdAmount, uint _currencyUSD, uint _totalToken, uint _tokenWithoutBonus, uint _tokenBonus, uint _bonusPercent) public returns(bool);
function getUserPaymentById(uint uId, uint payId) public view returns(uint time, bytes32 pType, uint currencyUSD, uint bonusPercent, uint payValue, uint totalToken, uint tokenBonus, uint tokenWithoutBonus, uint usdAbsRaisedInCents, bool refund);
function checkWalletExists(address addr) public view returns(bool result);
function checkReceivedCoins(address addr) public view returns(bool);
function getContributorId(address addr) public view returns(uint);
function getTotalCoin(address addr) public view returns(uint);
function setReceivedCoin(uint uId) public returns(bool);
function checkPreSaleReceivedBonus(address addr) public view returns(bool);
function checkRefund(address addr) public view returns(bool);
function setRefund(uint uId) public returns(bool);
function getEthPaymentContributor(address addr) public view returns(uint);
function refundPaymentByUserId(uint uId, uint payId) public returns(bool);
function changeSupportChangeMainWallet(bool support) public returns(bool);
}
pragma solidity ^0.4.24;
contract Migrations {
address public owner;
uint public last_completed_migration;
constructor() public {
owner = msg.sender;
}
modifier restricted() {
if (msg.sender == owner) _;
}
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
pragma solidity ^0.4.22;
import "./StandardToken.sol";
import "./Ownable.sol";
/**
* @title Mintable token
* @dev Simple ERC20 Token example, with mintable token creation
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
*/
contract MintableToken is StandardToken, Ownable {
event Mint(address indexed to, uint256 amount);
event MintFinished();
bool public mintingFinished = false;
modifier canMint() {
require(!mintingFinished);
_;
}
/**
* @dev Function to mint tokens
* @param _to The address that will receive the minted tokens.
* @param _amount The amount of tokens to mint.
* @return A boolean that indicates if the operation was successful.
*/
function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
totalSupply_ = totalSupply_.add(_amount);
balances[_to] = balances[_to].add(_amount);
emit Mint(_to, _amount);
emit Transfer(address(0), _to, _amount);
return true;
}
/**
* @dev Function to stop minting new tokens.
* @return True if the operation was successful.
*/
function finishMinting() onlyOwner canMint public returns (bool) {
mintingFinished = true;
emit MintFinished();
return true;
}
}
pragma solidity ^0.4.24;
import "./Ownable.sol";
/**
* @title MultiOwnable
* @dev The MultiOwnable contract has an owner address[], and provides basic authorization control
*/
contract MultiOwnable is Ownable {
struct Types {
mapping (address => bool) access;
}
mapping (uint => Types) private multiOwnersTypes;
event AddOwner(uint _type, address addr);
event AddOwner(uint[] types, address addr);
event RemoveOwner(uint _type, address addr);
modifier onlyMultiOwnersType(uint _type) {
require(multiOwnersTypes[_type].access[msg.sender] || msg.sender == owner, "403");
_;
}
function onlyMultiOwnerType(uint _type, address _sender) public view returns(bool) {
if (multiOwnersTypes[_type].access[_sender] || _sender == owner) {
return true;
}
return false;
}
function addMultiOwnerType(uint _type, address _owner) public onlyOwner returns(bool) {
require(_owner != address(0));
multiOwnersTypes[_type].access[_owner] = true;
emit AddOwner(_type, _owner);
return true;
}
function addMultiOwnerTypes(uint[] types, address _owner) public onlyOwner returns(bool) {
require(_owner != address(0));
require(types.length > 0);
for (uint i = 0; i < types.length; i++) {
multiOwnersTypes[types[i]].access[_owner] = true;
}
emit AddOwner(types, _owner);
return true;
}
function removeMultiOwnerType(uint types, address _owner) public onlyOwner returns(bool) {
require(_owner != address(0));
multiOwnersTypes[types].access[_owner] = false;
emit RemoveOwner(types, _owner);
return true;
}
}
pragma solidity ^0.4.24;
/**
* @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;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @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) public onlyOwner {
require(newOwner != address(0));
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner);
owner = address(0);
}
}
pragma solidity ^0.4.24;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
// Gas optimization: this is cheaper than asserting '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;
}
c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
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 a / b;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
pragma solidity ^0.4.22;
import "./StandardToken.sol";
/**
* @title SimpleToken
* @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
* Note they can later distribute these tokens as they wish using `transfer` and other
* `StandardToken` functions.
*/
contract ShipCoin is StandardToken {
string public constant name = "ShipCoin"; // solium-disable-line uppercase
string public constant symbol = "SHPC"; // solium-disable-line uppercase
uint8 public constant decimals = 18; // solium-disable-line uppercase
uint256 public constant INITIAL_SUPPLY = 1000000000 * (10 ** uint256(decimals));
/**
* @dev Constructor that gives msg.sender all of existing tokens.
*/
constructor () public {
totalSupply_ = INITIAL_SUPPLY;
balances[msg.sender] = INITIAL_SUPPLY;
emit Transfer(0x0, msg.sender, INITIAL_SUPPLY);
}
}
pragma solidity ^0.4.24;
import "./IBonus.sol";
import "./SafeMath.sol";
import "./MultiOwnable.sol";
import "./String.sol";
contract ShipCoinBonusSystem is IBonus, MultiOwnable, String {
using SafeMath for uint256;
struct Bonus {
uint startDay;
uint endDay;
uint percent;
}
Bonus[] public bonus;
uint256 private constant ONE_DAY = 86400;
uint private preSaleBonusPercent = 40;
uint private minReachUsdPayInCents = 1000000;
event AddBonus(uint startDay, uint endDay, uint percent);
event ChangeBonus(uint startDay, uint endDay, uint percentOld, uint percentNew);
event DeleteBonus(uint startDay, uint endDay, uint percent);
/**
* @dev constructor
*/
constructor() public {
bonus.push(Bonus(0, 2, 20)); // 20% for the first 48 hours | 0 - 2 days
bonus.push(Bonus(3, 14, 15)); // 15% for weeks 1-2 starting from day 3 | 3 - 14 days
bonus.push(Bonus(15, 28, 10)); // 10% for weeks 3-4 | 15 - 28 days
bonus.push(Bonus(29, 42, 5));// 5% for weeks 5-6 | 29 - 42 days
}
/**
* @dev Add or change bonus data
* @param _startDay timestamp
* @param _endDay timestamp
* @param _percent uint
*/
function addChangeBonus(uint _startDay, uint _endDay, uint _percent) public onlyMultiOwnersType(1) returns(bool) {
for (uint i = 0; i < bonus.length; i++) {
if (bonus[i].startDay == _startDay && bonus[i].endDay == _endDay) {
uint oldPercent = bonus[i].percent;
if (bonus[i].percent != _percent) {
bonus[i].percent = _percent;
emit ChangeBonus(_startDay, _endDay, oldPercent, _percent);
}
return true;
}
}
bonus.push(Bonus(_startDay, _endDay, _percent));
emit AddBonus(_startDay, _endDay, _percent);
return true;
}
/**
* @dev Delete bonus data
* @param _startDay timestamp
* @param _endDay timestamp
* @param _percent uint
*/
function delBonus(uint _startDay, uint _endDay, uint _percent) public onlyMultiOwnersType(2) returns(bool) {
for (uint i = 0; i < bonus.length; i++) {
if (bonus[i].startDay == _startDay && bonus[i].endDay == _endDay && bonus[i].percent == _percent) {
delete bonus[i];
emit DeleteBonus(_startDay, _endDay, _percent);
return true;
}
}
return false;
}
/**
* @dev Get current day bonus percent.
* @param startSaleDate timestamp
* @param saleState bool
*/
function getCurrentDayBonus(uint startSaleDate, bool saleState) public view returns(uint) {
if (saleState) {
for (uint i = 0; i < bonus.length; i++) {
if ((startSaleDate > 0 && block.timestamp >= startSaleDate) && (_currentDay(startSaleDate, saleState) >= bonus[i].startDay) && (_currentDay(startSaleDate, saleState) <= bonus[i].endDay)) {
if (bonus[i].percent > 0) {
return bonus[i].percent;
}
}
}
}
return 0;
}
/**
* @dev Change preSale bonus percent
* @param _bonus uint
*/
function changePreSaleBonus(uint _bonus) public onlyOwner returns(bool) {
require(_bonus > 20);
preSaleBonusPercent = _bonus;
}
/**
* @dev Change the minimum required amount to participate in the PreSale.
* @param _minUsdInCents minReachUsdPayInCents
*/
function changePreSaleMinUsd(uint _minUsdInCents) public onlyOwner returns(bool) {
require(_minUsdInCents > 100000);
minReachUsdPayInCents = _minUsdInCents;
}
/**
* @dev Сurrent day from the moment of start sale
* @param startSaleDate timestamp
* @param saleState bool
*/
function _currentDay(uint startSaleDate, bool saleState) public view returns(uint) {
if (!saleState || startSaleDate == 0 || startSaleDate > block.timestamp) {
return 0;
}
return block.timestamp.sub(startSaleDate).div(ONE_DAY);
}
/**
* @dev get all bonus data in json format
*/
function getBonusData() public view returns(string) {
string memory _array = "[";
for (uint i = 0; i < bonus.length; i++) {
_array = strConcat(
_array,
strConcat("{\"startDay\":", uint2str(bonus[i].startDay), ",\"endDay\":", uint2str(bonus[i].endDay), ",\"percent\":"),
uint2str(bonus[i].percent),
(i+1 == bonus.length) ? "}]" : "},"
);
}
return _array;
}
/**
* @dev get preSale bonus prcent
*/
function getPreSaleBonusPercent() public view returns(uint) {
return preSaleBonusPercent;
}
/**
* @dev get minimum required amount to participate in the PreSale
*/
function getMinReachUsdPayInCents() public view returns(uint) {
return minReachUsdPayInCents;
}
}
pragma solidity ^0.4.24;
import "./ERC20Basic.sol";
import "./IStorage.sol";
import "./ICurrency.sol";
import "./IBonus.sol";
import "./SafeMath.sol";
import "./MultiOwnable.sol";
/**
* @title ShipCoin Crowdsale
*/
contract ShipCoinCrowdsale is MultiOwnable {
using SafeMath for uint256;
ERC20Basic public coinContract;
IStorage public storageContract;
ICurrency public currencyContract;
IBonus public bonusContract;
enum SaleState {NEW, PRESALE, CALCPSBONUS, SALE, END, REFUND}
uint256 private constant ONE_DAY = 86400;
SaleState public state;
bool public paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
// minimum goal USD
uint public softCapUSD = 500000000; // 5,000,000$ in cents
// maximum goal USD
uint public hardCapUSD = 6200000000; // 62,000,000$ in cents
// maximum available SHPC with a bonus
uint public maxDistributeCoin = 600000000 * 1 ether; //600,000,000 shpc (incl. bonus)
// minimal accept payment
uint public minimalContributionUSD = 100000; // 1000$ in cents
// start and end timestamps where investments are allowed in PreSale
uint public startPreSaleDate;
uint public endPreSaleDate;
uint public unfreezeRefundPreSale;
uint public unfreezeRefundAll;
// start and end timestamps where investments are allowed in sale
uint public startSaleDate;
uint public endSaleDate;
bool public softCapAchieved = false;
address public multiSig1;
address public multiSig2;
bool public multiSigReceivedSoftCap = false;
/* Events */
event ChangeState(uint blockNumber, SaleState state);
event ChangeMinContribUSD(uint oldAmount, uint newAmount);
event ChangeStorageContract(address oldAddress, address newAddress);
event ChangeCurrencyContract(address oldAddress, address newAddress);
event ChangeCoinContract(address oldAddress, address newAddress);
event ChangeBonusContract(address oldAddress, address newAddress);
event AddPay(address contributor);
event EditPay(address contributor);
event SoftCapAchieved(uint amount);
event ManualChangeStartPreSaleDate(uint oldDate, uint newDate);
event ManualChangeEndPreSaleDate(uint oldDate, uint newDate);
event ManualChangeStartSaleDate(uint oldDate, uint newDate);
event ManualEndSaleDate(uint oldDate, uint newDate);
event SendSHPCtoContributor(address contributor);
event SoftCapChanged();
event Refund(address contributor);
event RefundPay(address contributor);
struct PaymentInfo {
bytes32 pType;
uint currencyUSD;
uint bonusPercent;
uint payValue;
uint totalToken;
uint tokenBonus;
uint usdAbsRaisedInCents;
bool refund;
}
struct CurrencyInfo {
uint value;
uint usdRaised;
uint usdAbsRaisedInCents;
uint coinRaisedInWei;
uint coinRaisedBonusInWei;
}
struct EditPaymentInfo {
uint usdAmount;
uint currencyUSD;
uint bonusPercent;
uint totalToken;
uint tokenWithoutBonus;
uint tokenBonus;
CurrencyInfo currency;
}
function () external whenNotPaused payable {
buyTokens(msg.sender);
}
/**
* @dev Run after deploy. Initialize initial variables
* @param _coinAddress address coinContract
* @param _storageContract address storageContract
* @param _currencyContract address currencyContract
* @param _bonusContract address bonusContract
* @param _multiSig1 address multiSig where eth will be transferred
* @param _startPreSaleDate timestamp
* @param _endPreSaleDate timestamp
* @param _startSaleDate timestamp
* @param _endSaleDate timestamp
*/
function init(
address _coinAddress,
address _storageContract,
address _currencyContract,
address _bonusContract,
address _multiSig1,
uint _startPreSaleDate,
uint _endPreSaleDate,
uint _startSaleDate,
uint _endSaleDate
)
public
onlyOwner
{
require(_coinAddress != address(0));
require(_storageContract != address(0));
require(_currencyContract != address(0));
require(_multiSig1 != address(0));
require(_bonusContract != address(0));
require(_startPreSaleDate > 0 && _startSaleDate > 0);
require(_startSaleDate > _endPreSaleDate);
require(_endSaleDate > _startSaleDate);
require(startSaleDate == 0);
coinContract = ERC20Basic(_coinAddress);
storageContract = IStorage(_storageContract);
currencyContract = ICurrency(_currencyContract);
bonusContract = IBonus(_bonusContract);
multiSig1 = _multiSig1;
multiSig2 = 0x231121dFCB61C929BCdc0D1E6fC760c84e9A02ad;
startPreSaleDate = _startPreSaleDate;
endPreSaleDate = _endPreSaleDate;
startSaleDate = _startSaleDate;
endSaleDate = _endSaleDate;
unfreezeRefundPreSale = _endSaleDate;
unfreezeRefundAll = _endSaleDate.add(ONE_DAY);
state = SaleState.NEW;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() public onlyOwner {
paused = true;
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() public onlyOwner {
paused = false;
}
/**
* @dev Change the minimum amount in dollars indicated in cents to accept payment.
* @param minContribUsd in cents
*/
function setMinimalContributionUSD(uint minContribUsd) public onlyOwner {
require(minContribUsd > 100); // > 1$
uint oldMinAmount = minimalContributionUSD;
minimalContributionUSD = minContribUsd;
emit ChangeMinContribUSD(oldMinAmount, minimalContributionUSD);
}
/**
* @dev Set the time when contributors can receive tokens
* @param _time timestamp
*/
function setUnfreezeRefund(uint _time) public onlyOwner {
require(_time > startSaleDate);
unfreezeRefundPreSale = _time;
unfreezeRefundAll = _time.add(ONE_DAY);
}
/**
* @dev Change address ShipCoinStorage contracts.
* @param _storageContract address ShipCoinStorage contracts
*/
function setStorageContract(address _storageContract) public onlyOwner {
require(_storageContract != address(0));
address oldStorageContract = storageContract;
storageContract = IStorage(_storageContract);
emit ChangeStorageContract(oldStorageContract, storageContract);
}
/**
* @dev Change address ShipCoin contracts.
* @param _coinContract address ShipCoin contracts
*/
function setCoinContract(address _coinContract) public onlyOwner {
require(_coinContract != address(0));
address oldCoinContract = coinContract;
coinContract = ERC20Basic(_coinContract);
emit ChangeCoinContract(oldCoinContract, coinContract);
}
/**
* @dev Change address ShipCoinCurrency contracts.
* @param _currencyContract address ShipCoinCurrency contracts
*/
function setCurrencyContract(address _currencyContract) public onlyOwner {
require(_currencyContract != address(0));
address oldCurContract = currencyContract;
currencyContract = ICurrency(_currencyContract);
emit ChangeCurrencyContract(oldCurContract, currencyContract);
}
/**
* @dev Change address ShipCoinBonusSystem contracts.
* @param _bonusContract address ShipCoinBonusSystem contracts
*/
function setBonusContract(address _bonusContract) public onlyOwner {
require(_bonusContract != address(0));
address oldContract = _bonusContract;
bonusContract = IBonus(_bonusContract);
emit ChangeBonusContract(oldContract, bonusContract);
}
/**
* @dev Change address multiSig1.
* @param _address address multiSig1
*/
function setMultisig(address _address) public onlyOwner {
require(_address != address(0));
multiSig1 = _address;
}
/**
* @dev Set softCapUSD
* @param _softCapUsdInCents uint softCapUSD > 100000
*/
function setSoftCap(uint _softCapUsdInCents) public onlyOwner {
require(_softCapUsdInCents > 100000);
softCapUSD = _softCapUsdInCents;
emit SoftCapChanged();
}
/**
* @dev Change maximum number of tokens sold
* @param _maxCoin maxDistributeCoin
*/
function changeMaxDistributeCoin(uint _maxCoin) public onlyOwner {
require(_maxCoin > 0 && _maxCoin >= currencyContract.getCoinRaisedInWei());
maxDistributeCoin = _maxCoin;
}
/**
* @dev Change status. Start presale.
*/
function startPreSale() public onlyMultiOwnersType(1) {
require(block.timestamp <= endPreSaleDate);
require(state == SaleState.NEW);
state = SaleState.PRESALE;
emit ChangeState(block.number, state);
}
/**
* @dev Change status. Start calculate presale bonus.
*/
function startCalculatePreSaleBonus() public onlyMultiOwnersType(5) {
require(state == SaleState.PRESALE);
state = SaleState.CALCPSBONUS;
emit ChangeState(block.number, state);
}
/**
* @dev Change status. Start sale.
*/
function startSale() public onlyMultiOwnersType(2) {
require(block.timestamp <= endSaleDate);
require(state == SaleState.CALCPSBONUS);
//require(!storageContract.checkNeedProcessPreSaleBonus(getMinReachUsdPayInCents()));
state = SaleState.SALE;
emit ChangeState(block.number, state);
}
/**
* @dev Change status. Set end if sale it was successful.
*/
function saleSetEnded() public onlyMultiOwnersType(3) {
require((state == SaleState.SALE) || (state == SaleState.PRESALE));
require(block.timestamp >= startSaleDate);
require(checkSoftCapAchieved());
state = SaleState.END;
storageContract.changeSupportChangeMainWallet(false);
emit ChangeState(block.number, state);
}
/**
* @dev Change status. Set refund when sale did not reach softcap.
*/
function saleSetRefund() public onlyMultiOwnersType(4) {
require((state == SaleState.SALE) || (state == SaleState.PRESALE));
require(block.timestamp >= endSaleDate);
require(!checkSoftCapAchieved());
state = SaleState.REFUND;
emit ChangeState(block.number, state);
}
/**
* @dev Payable function. Processes contribution in ETH.
*/
function buyTokens(address _beneficiary) public whenNotPaused payable {
require((state == SaleState.PRESALE && block.timestamp >= startPreSaleDate && block.timestamp <= endPreSaleDate) || (state == SaleState.SALE && block.timestamp >= startSaleDate && block.timestamp <= endSaleDate));
require(_beneficiary != address(0));
require(msg.value > 0);
uint usdAmount = currencyContract.getUsdFromETH(msg.value);
assert(usdAmount >= minimalContributionUSD);
uint bonusPercent = 0;
if (state == SaleState.SALE) {
bonusPercent = bonusContract.getCurrentDayBonus(startSaleDate, (state == SaleState.SALE));
}
(uint totalToken, uint tokenWithoutBonus, uint tokenBonus) = calcToken(usdAmount, bonusPercent);
assert((totalToken > 0 && totalToken <= calculateMaxCoinIssued()));
uint usdRate = currencyContract.getCurrencyRate("ETH");
assert(storageContract.addPayment(_beneficiary, "ETH", msg.value, usdAmount, usdRate, tokenWithoutBonus, tokenBonus, bonusPercent, 0));
assert(currencyContract.addPay("ETH", msg.value, usdAmount, totalToken, tokenBonus));
emit AddPay(_beneficiary);
}
/**
* @dev Manually add alternative contribution payment.
* @param ticker string
* @param value uint
* @param uId uint contributor identificator
* @param _pId uint payment identificator
* @param _currencyUSD uint current ticker rate (optional field)
*/
function addPay(string ticker, uint value, uint uId, uint _pId, uint _currencyUSD) public onlyMultiOwnersType(6) {
require(value > 0);
require(storageContract.checkUserIdExists(uId));
require(_pId > 0);
string memory _ticker = ticker;
uint _value = value;
assert(currencyContract.checkTickerExists(_ticker));
uint usdAmount = currencyContract.getUsdFromCurrency(_ticker, _value, _currencyUSD);
assert(usdAmount > 0);
uint bonusPercent = 0;
if (state == SaleState.SALE) {
bonusPercent = bonusContract.getCurrentDayBonus(startSaleDate, (state == SaleState.SALE));
}
(uint totalToken, uint tokenWithoutBonus, uint tokenBonus) = calcToken(usdAmount, bonusPercent);
assert(tokenWithoutBonus > 0);
uint usdRate = _currencyUSD > 0 ? _currencyUSD : currencyContract.getCurrencyRate(_ticker);
uint pId = _pId;
assert(storageContract.addPayment(uId, _ticker, _value, usdAmount, usdRate, tokenWithoutBonus, tokenBonus, bonusPercent, pId));
assert(currencyContract.addPay(_ticker, _value, usdAmount, totalToken, tokenBonus));
emit AddPay(storageContract.getContributorAddressById(uId));
}
/**
* @dev Edit contribution payment.
* @param uId uint contributor identificator
* @param payId uint payment identificator
* @param value uint
* @param _currencyUSD uint current ticker rate (optional field)
* @param _bonusPercent uint current ticker rate (optional field)
*/
function editPay(uint uId, uint payId, uint value, uint _currencyUSD, uint _bonusPercent) public onlyMultiOwnersType(7) {
require(value > 0);
require(storageContract.checkUserIdExists(uId));
require(payId > 0);
require((_bonusPercent == 0 || _bonusPercent <= getPreSaleBonusPercent()));
PaymentInfo memory payment = getPaymentInfo(uId, payId);
EditPaymentInfo memory paymentInfo = calcEditPaymentInfo(payment, value, _currencyUSD, _bonusPercent);
assert(paymentInfo.tokenWithoutBonus > 0);
assert(paymentInfo.currency.value > 0);
assert(paymentInfo.currency.usdRaised > 0);
assert(paymentInfo.currency.usdAbsRaisedInCents > 0);
assert(paymentInfo.currency.coinRaisedInWei > 0);
assert(currencyContract.editPay(payment.pType, paymentInfo.currency.value, paymentInfo.currency.usdRaised, paymentInfo.currency.usdAbsRaisedInCents, paymentInfo.currency.coinRaisedInWei, paymentInfo.currency.coinRaisedBonusInWei));
assert(storageContract.editPaymentByUserId(uId, payId, value, paymentInfo.usdAmount, paymentInfo.currencyUSD, paymentInfo.totalToken, paymentInfo.tokenWithoutBonus, paymentInfo.tokenBonus, paymentInfo.bonusPercent));
assert(reCountUserPreSaleBonus(uId));
emit EditPay(storageContract.getContributorAddressById(uId));
}
/**
* @dev Refund contribution payment.
* @param uId uint
* @param payId uint
*/
function refundPay(uint uId, uint payId) public onlyMultiOwnersType(18) {
require(storageContract.checkUserIdExists(uId));
require(payId > 0);
(CurrencyInfo memory currencyInfo, bytes32 pType) = calcCurrency(getPaymentInfo(uId, payId), 0, 0, 0, 0);
assert(storageContract.refundPaymentByUserId(uId, payId));
assert(currencyContract.editPay(pType, currencyInfo.value, currencyInfo.usdRaised, currencyInfo.usdAbsRaisedInCents, currencyInfo.coinRaisedInWei, currencyInfo.coinRaisedBonusInWei));
assert(reCountUserPreSaleBonus(uId));
emit RefundPay(storageContract.getContributorAddressById(uId));
}
/**
* @dev Check if softCap is reached
*/
function checkSoftCapAchieved() public view returns(bool) {
return softCapAchieved || getTotalUsdRaisedInCents() >= softCapUSD;
}
/**
* @dev Set softCapAchieved=true if softCap is reached
*/
function activeSoftCapAchieved() public onlyMultiOwnersType(8) {
require(checkSoftCapAchieved());
require(getCoinBalance() >= maxDistributeCoin);
softCapAchieved = true;
emit SoftCapAchieved(getTotalUsdRaisedInCents());
}
/**
* @dev Send ETH from contract balance to multiSig.
*/
function getEther() public onlyMultiOwnersType(9) {
require(getETHBalance() > 0);
require(softCapAchieved && (!multiSigReceivedSoftCap || (state == SaleState.END)));
uint sendEther = (address(this).balance / 2);
assert(sendEther > 0);
address(multiSig1).transfer(sendEther);
address(multiSig2).transfer(sendEther);
multiSigReceivedSoftCap = true;
}
/**
* @dev Return maximum amount buy token.
*/
function calculateMaxCoinIssued() public view returns (uint) {
return maxDistributeCoin - currencyContract.getCoinRaisedInWei();
}
/**
* @dev Return raised SHPC in wei.
*/
function getCoinRaisedInWei() public view returns (uint) {
return currencyContract.getCoinRaisedInWei();
}
/**
* @dev Return raised usd in cents.
*/
function getTotalUsdRaisedInCents() public view returns (uint) {
return currencyContract.getTotalUsdRaisedInCents();
}
/**
* @dev Return all currency rate in json.
*/
function getAllCurrencyTicker() public view returns (string) {
return currencyContract.getAllCurrencyTicker();
}
/**
* @dev Return SHPC price in cents.
*/
function getCoinUSDRate() public view returns (uint) {
return currencyContract.getCoinUSDRate();
}
/**
* @dev Retrun SHPC balance in contract.
*/
function getCoinBalance() public view returns (uint) {
return coinContract.balanceOf(address(this));
}
/**
* @dev Return balance ETH from contract.
*/
function getETHBalance() public view returns (uint) {
return address(this).balance;
}
/**
* @dev Processing of the data of the contributors. Bonus assignment for presale.
* @param start uint > 0
* @param limit uint > 0
*/
function processSetPreSaleBonus(uint start, uint limit) public onlyMultiOwnersType(10) {
require(state == SaleState.CALCPSBONUS);
require(start >= 0 && limit > 0);
//require(storageContract.checkNeedProcessPreSaleBonus(getMinReachUsdPayInCents()));
uint bonusToken = storageContract.processPreSaleBonus(getMinReachUsdPayInCents(), getPreSaleBonusPercent(), start, limit);
if (bonusToken > 0) {
assert(currencyContract.addPreSaleBonus(bonusToken));
}
}
/**
* @dev Processing of the data of the contributor by uId. Bonus assignment for presale.
* @param uId uint
*/
function reCountUserPreSaleBonus(uint uId) public onlyMultiOwnersType(11) returns(bool) {
if (uint(state) > 1) { // > PRESALE
uint maxPayTime = 0;
if (state != SaleState.CALCPSBONUS) {
maxPayTime = startSaleDate;
}
(uint befTokenBonus, uint aftTokenBonus) = storageContract.reCountUserPreSaleBonus(uId, getMinReachUsdPayInCents(), getPreSaleBonusPercent(), maxPayTime);
assert(currencyContract.editPreSaleBonus(befTokenBonus, aftTokenBonus));
}
return true;
}
/**
* @dev Contributor get SHPC.
*/
function getCoins() public {
return _getCoins(msg.sender);
}
/**
* @dev Send contributors SHPC.
* @param start uint
* @param limit uint
*/
function sendSHPCtoContributors(uint start, uint limit) public onlyMultiOwnersType(12) {
require(state == SaleState.END);
require(start >= 0 && limit > 0);
require(getCoinBalance() > 0);
//require(storageContract.checkNeedSendSHPC(state == SaleState.END));
for (uint i = start; i < limit; i++) {
uint uId = storageContract.getContributorIndexes(i);
if (uId > 0) {
address addr = storageContract.getContributorAddressById(uId);
uint coins = storageContract.getTotalCoin(addr);
if (!storageContract.checkReceivedCoins(addr) && storageContract.checkWalletExists(addr) && coins > 0 && ((storageContract.checkPreSaleReceivedBonus(addr) && block.timestamp >= unfreezeRefundPreSale) || (!storageContract.checkPreSaleReceivedBonus(addr) && block.timestamp >= unfreezeRefundAll))) {
if (coinContract.transfer(addr, coins)) {
storageContract.setReceivedCoin(uId);
emit SendSHPCtoContributor(addr);
}
}
}
}
}
/**
* @dev Set startPreSaleDate
* @param date timestamp
*/
function setStartPreSaleDate(uint date) public onlyMultiOwnersType(13) {
uint oldDate = startPreSaleDate;
startPreSaleDate = date;
emit ManualChangeStartPreSaleDate(oldDate, date);
}
/**
* @dev Set startPreSaleDate
* @param date timestamp
*/
function setEndPreSaleDate(uint date) public onlyMultiOwnersType(14) {
uint oldDate = endPreSaleDate;
endPreSaleDate = date;
emit ManualChangeEndPreSaleDate(oldDate, date);
}
/**
* @dev Set startSaleDate
* @param date timestamp
*/
function setStartSaleDate(uint date) public onlyMultiOwnersType(15) {
uint oldDate = startSaleDate;
startSaleDate = date;
emit ManualChangeStartSaleDate(oldDate, date);
}
/**
* @dev Set endSaleDate
* @param date timestamp
*/
function setEndSaleDate(uint date) public onlyMultiOwnersType(16) {
uint oldDate = endSaleDate;
endSaleDate = date;
emit ManualEndSaleDate(oldDate, date);
}
/**
* @dev Return SHPC from contract. When sale ended end contributor got SHPC.
*/
function getSHPCBack() public onlyMultiOwnersType(17) {
require(state == SaleState.END);
require(getCoinBalance() > 0);
//require(!storageContract.checkNeedSendSHPC(state == SaleState.END));
coinContract.transfer(msg.sender, getCoinBalance());
}
/**
* @dev Refund ETH contributor.
*/
function refundETH() public {
return _refundETH(msg.sender);
}
/**
* @dev Refund ETH contributors.
* @param start uint
* @param limit uint
*/
function refundETHContributors(uint start, uint limit) public onlyMultiOwnersType(19) {
require(state == SaleState.REFUND);
require(start >= 0 && limit > 0);
require(getETHBalance() > 0);
//require(storageContract.checkETHRefund(state == SaleState.REFUND));
for (uint i = start; i < limit; i++) {
uint uId = storageContract.getContributorIndexes(i);
if (uId > 0) {
address addr = storageContract.getContributorAddressById(uId);
uint ethAmount = storageContract.getEthPaymentContributor(addr);
if (!storageContract.checkRefund(addr) && storageContract.checkWalletExists(addr) && ethAmount > 0) {
storageContract.setRefund(uId);
addr.transfer(ethAmount);
emit Refund(addr);
}
}
}
}
/**
* @dev Return pre-sale bonus getPreSaleBonusPercent.
*/
function getPreSaleBonusPercent() public view returns(uint) {
return bonusContract.getPreSaleBonusPercent();
}
/**
* @dev Return pre-sale minReachUsdPayInCents.
*/
function getMinReachUsdPayInCents() public view returns(uint) {
return bonusContract.getMinReachUsdPayInCents();
}
/**
* @dev Return current sale day.
*/
function _currentDay() public view returns(uint) {
return bonusContract._currentDay(startSaleDate, (state == SaleState.SALE));
}
/**
* @dev Return current sale day bonus percent.
*/
function getCurrentDayBonus() public view returns(uint) {
return bonusContract.getCurrentDayBonus(startSaleDate, (state == SaleState.SALE));
}
/**
* @dev Return contributor payment info.
* @param uId uint
* @param pId uint
*/
function getPaymentInfo(uint uId, uint pId) private view returns(PaymentInfo) {
(, bytes32 pType,
uint currencyUSD,
uint bonusPercent,
uint payValue,
uint totalToken,
uint tokenBonus,,
uint usdAbsRaisedInCents,
bool refund) = storageContract.getUserPaymentById(uId, pId);
return PaymentInfo(pType, currencyUSD, bonusPercent, payValue, totalToken, tokenBonus, usdAbsRaisedInCents, refund);
}
/**
* @dev Return recalculate payment data from old payment user.
*/
function calcEditPaymentInfo(PaymentInfo payment, uint value, uint _currencyUSD, uint _bonusPercent) private view returns(EditPaymentInfo) {
(uint usdAmount, uint currencyUSD, uint bonusPercent) = getUsdAmountFromPayment(payment, value, _currencyUSD, _bonusPercent);
(uint totalToken, uint tokenWithoutBonus, uint tokenBonus) = calcToken(usdAmount, bonusPercent);
(CurrencyInfo memory currency,) = calcCurrency(payment, value, usdAmount, totalToken, tokenBonus);
return EditPaymentInfo(usdAmount, currencyUSD, bonusPercent, totalToken, tokenWithoutBonus, tokenBonus, currency);
}
/**
* @dev Return usd from payment amount.
*/
function getUsdAmountFromPayment(PaymentInfo payment, uint value, uint _currencyUSD, uint _bonusPercent) private view returns(uint, uint, uint) {
_currencyUSD = _currencyUSD > 0 ? _currencyUSD : payment.currencyUSD;
_bonusPercent = _bonusPercent > 0 ? _bonusPercent : payment.bonusPercent;
uint usdAmount = currencyContract.getUsdFromCurrency(payment.pType, value, _currencyUSD);
return (usdAmount, _currencyUSD, _bonusPercent);
}
/**
* @dev Return payment SHPC data from usd amount and bonusPercent
*/
function calcToken(uint usdAmount, uint _bonusPercent) private view returns(uint, uint, uint) {
uint tokenWithoutBonus = currencyContract.getTokenWeiFromUSD(usdAmount);
uint tokenBonus = _bonusPercent > 0 ? tokenWithoutBonus.mul(_bonusPercent).div(100) : 0;
uint totalToken = tokenBonus > 0 ? tokenWithoutBonus.add(tokenBonus) : tokenWithoutBonus;
return (totalToken, tokenWithoutBonus, tokenBonus);
}
/**
* @dev Calculate currency data when edit user payment data
*/
function calcCurrency(PaymentInfo payment, uint value, uint usdAmount, uint totalToken, uint tokenBonus) private view returns(CurrencyInfo, bytes32) {
(,,, uint currencyValue, uint currencyUsdRaised,,,) = currencyContract.getCurrencyList(payment.pType);
uint usdAbsRaisedInCents = currencyContract.getUsdAbsRaisedInCents();
uint coinRaisedInWei = currencyContract.getCoinRaisedInWei();
uint coinRaisedBonusInWei = currencyContract.getCoinRaisedBonusInWei();
currencyValue -= payment.payValue;
currencyUsdRaised -= payment.usdAbsRaisedInCents;
usdAbsRaisedInCents -= payment.usdAbsRaisedInCents;
coinRaisedInWei -= payment.totalToken;
coinRaisedBonusInWei -= payment.tokenBonus;
currencyValue += value;
currencyUsdRaised += usdAmount;
usdAbsRaisedInCents += usdAmount;
coinRaisedInWei += totalToken;
coinRaisedBonusInWei += tokenBonus;
return (CurrencyInfo(currencyValue, currencyUsdRaised, usdAbsRaisedInCents, coinRaisedInWei, coinRaisedBonusInWei), payment.pType);
}
/**
* @dev Getting the SHPC from the contributor
*/
function _getCoins(address addr) private {
require(state == SaleState.END);
require(storageContract.checkWalletExists(addr));
require(!storageContract.checkReceivedCoins(addr));
require((storageContract.checkPreSaleReceivedBonus(addr) && block.timestamp >= unfreezeRefundPreSale) || (!storageContract.checkPreSaleReceivedBonus(addr) && block.timestamp >= unfreezeRefundAll));
uint uId = storageContract.getContributorId(addr);
uint coins = storageContract.getTotalCoin(addr);
assert(uId > 0 && coins > 0);
if (coinContract.transfer(addr, coins)) {
storageContract.setReceivedCoin(uId);
emit SendSHPCtoContributor(addr);
}
}
/**
* @dev Refund ETH contributor when sale not reach softcap.
*/
function _refundETH(address addr) private {
require(state == SaleState.REFUND);
require(storageContract.checkWalletExists(addr));
require(!storageContract.checkRefund(addr));
uint uId = storageContract.getContributorId(addr);
uint ethAmount = storageContract.getEthPaymentContributor(addr);
assert(uId > 0 && ethAmount > 0 && getETHBalance() >= ethAmount);
storageContract.setRefund(uId);
addr.transfer(ethAmount);
emit Refund(addr);
}
}
pragma solidity ^0.4.24;
import "./MultiOwnable.sol";
import "./String.sol";
import "./SafeMath.sol";
import "./ICurrency.sol";
/**
* @title Convert eth,btc,eur,amb to usd and storage payment from currency
*/
contract ShipCoinCurrency is ICurrency, MultiOwnable, String {
using SafeMath for uint256;
uint private coinUSDRate = 12; // in wei 0.12$
uint private currVolPercent = 5; // 5% currency volatility
// Amount of wei raised SHPC
uint256 private coinRaisedInWei = 0;
// Amount of cents raised USD at the time of payment
uint private usdAbsRaisedInCents = 0;
uint private coinRaisedBonusInWei = 0;
struct CurrencyData {
bool active;
uint usd;
uint devision;
uint raised;
uint usdRaised;
uint counter;
uint lastUpdate;
}
mapping(bytes32 => CurrencyData) private currencyList;
bytes32[] private currencyTicker;
/* Events */
event ChangeCoinUSDRate(uint oldPrice, uint newPrice);
event ChangeCurrVolPercent(uint oldPercent, uint newPercent);
event ChangeCurrency();
event AddPay();
event EditPay();
/**
* @dev constructor 50328,655575,116
* @param _ethPrice in cents example 58710 = 587.10$
* @param _btcPrice in cents example 772301 = 7723.01$
* @param _eurPrice in cents example 117 = 1.17$
* @param _ambPrice in cents example 18 = 0.18$
*/
constructor(uint _ethPrice, uint _btcPrice, uint _eurPrice, uint _ambPrice) public {
require(addUpdateCurrency("ETH", _ethPrice, (1 ether)));
require(addUpdateCurrency("BTC", _btcPrice, (10**8)));
require(addUpdateCurrency("USD", 1, 1));
require(addUpdateCurrency("EUR", _eurPrice, 100));
require(addUpdateCurrency("AMB", _ambPrice, (1 ether)));
}
/**
* @dev Returns the collected amount in dollars. Summarize at the rate when the payment was made.
*/
function getUsdAbsRaisedInCents() external view returns(uint) {
return usdAbsRaisedInCents;
}
/**
* @dev Return the amount of SHPC sold as a bonus.
*/
function getCoinRaisedBonusInWei() external view returns(uint) {
return coinRaisedBonusInWei;
}
/**
* @dev Add or Update currency
*/
function addUpdateCurrency(string _ticker, uint _usd, uint _devision) public returns(bool) {
return addUpdateCurrency(_ticker, _usd, _devision, 0, 0);
}
/**
* @dev Add or Update currency
*/
function addUpdateCurrency(string _ticker, uint _usd) public returns(bool) {
return addUpdateCurrency(_ticker, _usd, 0, 0, 0);
}
/**
* @dev Add or Update currency
* @param _ticker string
* @param _usd uint rate in cents
* @param _devision uint
* @param _raised uint
* @param _usdRaised uint raised in usd cents
*/
function addUpdateCurrency(string _ticker, uint _usd, uint _devision, uint _raised, uint _usdRaised) public onlyMultiOwnersType(1) returns(bool) {
require(_usd > 0, "1");
bytes32 ticker = stringToBytes32(_ticker);
if (!currencyList[ticker].active) {
currencyTicker.push(ticker);
}
currencyList[ticker] = CurrencyData({
active : true,
usd : _usd,
devision : (_devision == 0) ? currencyList[ticker].devision : _devision,
raised : currencyList[ticker].raised > 0 ? currencyList[ticker].raised : _raised,
usdRaised: currencyList[ticker].usdRaised > 0 ? currencyList[ticker].usdRaised : _usdRaised,
counter: currencyList[ticker].counter > 0 ? currencyList[ticker].counter : 0,
lastUpdate: block.timestamp
});
return true;
}
/**
* @dev Set SHPC price in cents
*/
function setCoinUSDRate(uint _value) public onlyOwner returns(bool) {
require(_value > 0);
uint oldCoinUSDRate = coinUSDRate;
coinUSDRate = _value;
emit ChangeCoinUSDRate(oldCoinUSDRate, coinUSDRate);
return true;
}
/**
* @dev Percent deducted from the amount raised getTotalUsdRaisedInCents
*/
function setCurrVolPercent(uint _value) public onlyOwner returns(bool) {
require(_value > 0 && _value <= 10);
uint oldCurrVolPercent = currVolPercent;
currVolPercent = _value;
emit ChangeCurrVolPercent(oldCurrVolPercent, currVolPercent);
return true;
}
/**
* @dev Returns the number of SHPC from USD
* @param usdCents amount of dollars in cents example 100$ = 10000
* @return SHPC in wei
*/
function getTokenWeiFromUSD(uint usdCents) public view returns(uint) {
return usdCents.mul(1 ether).div(coinUSDRate); // (100.00$ * (10**18)) / 0.12$ = 833333333333333333333 SHPC wei = 833.33 SHPC
}
/**
* @dev Returns the number of SHPC in wei
* @param ethWei eth в wei
* @return SHPC in wei
*/
function getTokenFromETH(uint ethWei) public view returns(uint) {
return ethWei.mul(currencyList["ETH"].usd).div(coinUSDRate); // (1 ETH * 587.10$) / 0.12$ = 4892500000000000000000 SHPC wei = 4892.50 SHPC
}
/**
* @dev Returns the amount of USD from ETH
* @param ethWei ETH в wei
* @return USD in cents
*/
function getUsdFromETH(uint ethWei) public view returns(uint) {
return ethWei.mul(currencyList["ETH"].usd).div(1 ether);
}
/**
* @dev Add payment data to currency
* @param _ticker string
* @param value uint
* @param usdAmount uint in cents
* @param coinRaised uint in wei
* @param coinRaisedBonus uint in wei (optional field)
*/
function addPay(string _ticker, uint value, uint usdAmount, uint coinRaised, uint coinRaisedBonus) public onlyMultiOwnersType(2) returns(bool) {
require(value > 0);
require(usdAmount > 0);
require(coinRaised > 0);
bytes32 ticker = stringToBytes32(_ticker);
assert(currencyList[ticker].active);
coinRaisedInWei += coinRaised;
coinRaisedBonusInWei += coinRaisedBonus;
usdAbsRaisedInCents += usdAmount;
currencyList[ticker].usdRaised += usdAmount;
currencyList[ticker].raised += value;
currencyList[ticker].counter++;
emit AddPay();
return true;
}
/**
* @dev Chacnge currency data when change contributor payment
* @param ticker bytes32
* @param currencyValue uint
* @param currencyUsdRaised uint in cents
* @param _usdAbsRaisedInCents uint in cents
* @param _coinRaisedInWei uint in wei
* @param _coinRaisedBonusInWei uint in wei (optional field)
*/
function editPay(
bytes32 ticker,
uint currencyValue,
uint currencyUsdRaised,
uint _usdAbsRaisedInCents,
uint _coinRaisedInWei,
uint _coinRaisedBonusInWei
)
public
onlyMultiOwnersType(3)
returns(bool)
{
require(currencyValue > 0);
require(currencyUsdRaised > 0);
require(_usdAbsRaisedInCents > 0);
require(_coinRaisedInWei > 0);
assert(currencyList[ticker].active);
coinRaisedInWei = _coinRaisedInWei;
coinRaisedBonusInWei = _coinRaisedBonusInWei;
usdAbsRaisedInCents = _usdAbsRaisedInCents;
currencyList[ticker].usdRaised = currencyUsdRaised;
currencyList[ticker].raised = currencyValue;
emit EditPay();
return true;
}
/**
* @dev Add bonus SHPC
*/
function addPreSaleBonus(uint bonusToken) public onlyMultiOwnersType(4) returns(bool) {
coinRaisedInWei += bonusToken;
coinRaisedBonusInWei += bonusToken;
emit EditPay();
return true;
}
/**
* @dev Change bonus SHPC
*/
function editPreSaleBonus(uint beforeBonus, uint afterBonus) public onlyMultiOwnersType(5) returns(bool) {
coinRaisedInWei -= beforeBonus;
coinRaisedBonusInWei -= beforeBonus;
coinRaisedInWei += afterBonus;
coinRaisedBonusInWei += afterBonus;
emit EditPay();
return true;
}
/**
* @dev Returns the sum of investments with conversion to dollars at the current rate with a deduction of interest.
*/
function getTotalUsdRaisedInCents() public view returns(uint) {
uint totalUsdAmount = 0;
if (currencyTicker.length > 0) {
for (uint i = 0; i < currencyTicker.length; i++) {
if (currencyList[currencyTicker[i]].raised > 0) {
totalUsdAmount += getUsdFromCurrency(currencyTicker[i], currencyList[currencyTicker[i]].raised);
}
}
}
return subPercent(totalUsdAmount, currVolPercent);
}
/**
* @dev Converts to dollars
*/
function getUsdFromCurrency(string ticker, uint value) public view returns(uint) {
return getUsdFromCurrency(stringToBytes32(ticker), value);
}
/**
* @dev Converts to dollars
*/
function getUsdFromCurrency(string ticker, uint value, uint usd) public view returns(uint) {
return getUsdFromCurrency(stringToBytes32(ticker), value, usd);
}
/**
* @dev Converts to dollars
*/
function getUsdFromCurrency(bytes32 ticker, uint value) public view returns(uint) {
return getUsdFromCurrency(ticker, value, 0);
}
/**
* @dev Converts to dollars
*/
function getUsdFromCurrency(bytes32 ticker, uint value, uint usd) public view returns(uint) {
if (currencyList[ticker].active && value > 0) {
return value.mul(usd > 0 ? usd : currencyList[ticker].usd).div(currencyList[ticker].devision);
}
return 0;
}
/**
* @dev Returns information about available currencies in json format
*/
function getAllCurrencyTicker() public view returns(string) {
string memory _tickers = "{";
for (uint i = 0; i < currencyTicker.length; i++) {
_tickers = strConcat(_tickers, strConcat("\"", bytes32ToString(currencyTicker[i]), "\":"), uint2str(currencyList[currencyTicker[i]].usd), (i+1 < currencyTicker.length) ? "," : "}");
}
return _tickers;
}
/**
* @dev Update currency rate.
*/
function updateCurrency(string ticker, uint value) public onlyMultiOwnersType(6) returns(bool) {
bytes32 _ticker = stringToBytes32(ticker);
require(currencyList[_ticker].active);
require(value > 0);
currencyList[_ticker].usd = value;
currencyList[_ticker].lastUpdate = block.timestamp;
emit ChangeCurrency();
return true;
}
/**
* @dev Check currency is available.
*/
function checkTickerExists(string ticker) public view returns(bool) {
return currencyList[stringToBytes32(ticker)].active;
}
/**
* @dev Returns currency info.
*/
function getCurrencyList(string ticker)
public
view
returns(
bool active,
uint usd,
uint devision,
uint raised,
uint usdRaised,
uint usdRaisedExchangeRate,
uint counter,
uint lastUpdate
)
{
return getCurrencyList(stringToBytes32(ticker));
}
/**
* @dev Return curency info.
*/
function getCurrencyList(bytes32 ticker)
public
view
returns(
bool active,
uint usd,
uint devision,
uint raised,
uint usdRaised,
uint usdRaisedExchangeRate,
uint counter,
uint lastUpdate
)
{
CurrencyData memory _obj = currencyList[ticker];
uint _usdRaisedExchangeRate = getUsdFromCurrency(ticker, _obj.raised);
return (
_obj.active,
_obj.usd,
_obj.devision,
_obj.raised,
_obj.usdRaised,
_usdRaisedExchangeRate,
_obj.counter,
_obj.lastUpdate
);
}
function getCurrencyRate(string _ticker) public view returns(uint) {
return currencyList[stringToBytes32(_ticker)].usd;
}
/**
* @dev Return all currency data in json.
*/
function getCurrencyData() public view returns(string) {
string memory _array = "{";
if (currencyTicker.length > 0) {
for (uint i = 0; i < currencyTicker.length; i++) {
if (currencyList[currencyTicker[i]].active) {
_array = strConcat(_array, strConcat("\"", bytes32ToString(currencyTicker[i]), "\":"), getJsonCurrencyData(currencyList[currencyTicker[i]]), (i+1 == currencyTicker.length) ? "}" : ",");
}
}
} else {
return "[]";
}
return _array;
}
/**
* @dev Returns the number of SHPC sold
*/
function getCoinRaisedInWei() public view returns(uint) {
return coinRaisedInWei;
}
/**
* @dev Returns SHPC price in cents
*/
function getCoinUSDRate() public view returns(uint) {
return coinUSDRate;
}
/**
* @dev Returns percent.
*/
function getCurrVolPercent() public view returns(uint) {
return currVolPercent;
}
/**
* @dev Returns json info from currency
*/
function getJsonCurrencyData(CurrencyData memory _obj) private pure returns (string) {
return strConcat(
strConcat("{\"usd\":", uint2str(_obj.usd), ",\"devision\":", uint2str(_obj.devision), ",\"raised\":\""),
strConcat(uint2str(_obj.raised), "\",\"usdRaised\":", uint2str(_obj.usdRaised), ",\"usdRaisedCurrency\":", uint2str((_obj.raised.mul(_obj.usd).div(_obj.devision)))),
strConcat(",\"counter\":", uint2str(_obj.counter), ",\"lastUpdate\":", uint2str(_obj.lastUpdate), "}")
);
}
/**
* @dev Calculate the percentage of the amount
* example: 100 - 5% = 95
*/
function subPercent(uint a, uint b) private pure returns(uint) {
uint c = (a / 100) * b;
assert(c <= a);
return a - c;
}
}
pragma solidity ^0.4.24;
import "./MultiOwnable.sol";
import "./String.sol";
import "./SafeMath.sol";
import "./IStorage.sol";
/**
* @title Whitelist
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions.
* @dev This simplifies the implementation of "user permissions".
*/
contract ShipCoinStorage is IStorage, MultiOwnable, String {
using SafeMath for uint256;
/* Events */
event WhitelistAddressAdded(address addr);
event WhitelistAddressRemoved(address addr);
event AddPayment(address addr);
event GotPreSaleBonus(address addr);
event EditUserPayments(address addr, uint payId);
event RefundPayment(address addr, uint payId);
event ReceivedCoin(address addr);
event Refund(address addr);
event ChangeMainWallet(address addr);
struct PaymentData {
uint time;
bytes32 pType;
uint currencyUSD;
uint payValue;
uint totalToken;
uint tokenWithoutBonus;
uint tokenBonus;
uint bonusPercent;
uint usdAbsRaisedInCents;
}
struct StorageData {
bool active;
mapping(bytes32 => uint) payInCurrency;
uint totalToken;
uint tokenWithoutBonus;
uint tokenBonus;
uint usdAbsRaisedInCents;
mapping(uint => PaymentData) paymentInfo;
address mainWallet;
address[] wallet;
}
// uId = { }
mapping(uint => StorageData) private contributorList;
// wallet = uId
mapping(address => uint) private contributorIds;
// i++ = uId
mapping(uint => uint) private contributorIndexes;
//uId = payIds
mapping(uint => uint[]) private contributorPayIds;
uint public nextContributorIndex;
bytes32[] private currencyTicker;
// uId
mapping(uint => uint) private receivedPreSaleBonus;
// uId
mapping(uint => bool) private receivedCoin;
//payIds
mapping(uint => bool) private payIds;
//payIds
mapping(uint => bool) private refundPayIds;
//uId
mapping(uint => bool) private refundUserIds;
uint private startGenId = 100000;
bool public supportChangeMainWallet = true;
/**
* @dev Calculate contributors appoint presale bonus
*/
function processPreSaleBonus(uint minTotalUsdAmountInCents, uint bonusPercent, uint _start, uint _limit) external onlyMultiOwnersType(12) returns(uint) {
require(minTotalUsdAmountInCents > 10000);
require(bonusPercent > 20 && bonusPercent < 50);
require(_limit >= 10);
uint start = _start;
uint limit = _limit;
uint bonusTokenAll = 0;
for (uint i = start; i < limit; i++) {
uint uId = contributorIndexes[i];
if (contributorList[uId].active && !checkPreSaleReceivedBonus(uId) && contributorList[uId].usdAbsRaisedInCents >= minTotalUsdAmountInCents) {
uint bonusToken = contributorList[uId].tokenWithoutBonus.mul(bonusPercent).div(100);
contributorList[uId].totalToken += bonusToken;
contributorList[uId].tokenBonus = bonusToken;
receivedPreSaleBonus[uId] = bonusToken;
bonusTokenAll += bonusToken;
emit GotPreSaleBonus(contributorList[uId].mainWallet);
}
}
return bonusTokenAll;
}
/**
* @dev Checks contributors who have not received their presale bonuses
*/
function checkNeedProcessPreSaleBonus(uint minTotalUsdAmountInCents) external view returns(bool) {
require(minTotalUsdAmountInCents > 10000);
bool processed = false;
for (uint i = 0; i < nextContributorIndex; i++) {
if (processed) {
break;
}
uint uId = contributorIndexes[i];
if (contributorList[uId].active && !refundUserIds[uId] && !checkPreSaleReceivedBonus(uId) && contributorList[uId].usdAbsRaisedInCents >= minTotalUsdAmountInCents) {
processed = true;
}
}
return processed;
}
/**
* @dev Returns the number of contributors who have not received their presale bonuses
*/
function getCountNeedProcessPreSaleBonus(uint minTotalUsdAmountInCents, uint start, uint limit) external view returns(uint) {
require(minTotalUsdAmountInCents > 10000);
require(start >= 0 && limit >= 10);
uint processed = 0;
for (uint i = start; i < (limit > nextContributorIndex ? nextContributorIndex : limit); i++) {
uint uId = contributorIndexes[i];
if (contributorList[uId].active && !refundUserIds[uId] && !checkPreSaleReceivedBonus(uId) && contributorList[uId].usdAbsRaisedInCents >= minTotalUsdAmountInCents) {
processed++;
}
}
return processed;
}
/**
* @dev Checks contributors who have not received their SHPC
*/
function checkNeedSendSHPC(bool proc) external view returns(bool) {
bool processed = false;
if (proc) {
for (uint i = 0; i < nextContributorIndex; i++) {
if (processed) {
break;
}
uint uId = contributorIndexes[i];
if (contributorList[uId].active && !refundUserIds[uId] && !checkReceivedCoins(uId) && contributorList[uId].totalToken > 0) {
processed = true;
}
}
}
return processed;
}
/**
* @dev Returns the number of contributors who have not received their SHPC
*/
function getCountNeedSendSHPC(uint start, uint limit) external view returns(uint) {
require(start >= 0 && limit >= 10);
uint processed = 0;
for (uint i = start; i < (limit > nextContributorIndex ? nextContributorIndex : limit); i++) {
uint uId = contributorIndexes[i];
if (contributorList[uId].active && !refundUserIds[uId] && !checkReceivedCoins(uId) && contributorList[uId].totalToken > 0) {
processed++;
}
}
return processed;
}
/**
* @dev Checks contributors who have not received their ETH when refund
*/
function checkETHRefund(bool proc) external view returns(bool) {
bool processed = false;
if (proc) {
for (uint i = 0; i < nextContributorIndex; i++) {
if (processed) {
break;
}
uint uId = contributorIndexes[i];
if (contributorList[uId].active && !refundUserIds[uId] && getEthPaymentContributor(uId) > 0) {
processed = true;
}
}
}
return processed;
}
/**
* @dev Returns the number of contributors who have not received their ETH when refund
*/
function getCountETHRefund(uint start, uint limit) external view returns(uint) {
require(start >= 0 && limit >= 10);
uint processed = 0;
for (uint i = start; i < (limit > nextContributorIndex ? nextContributorIndex : limit); i++) {
uint uId = contributorIndexes[i];
if (contributorList[uId].active && !refundUserIds[uId] && getEthPaymentContributor(uId) > 0) {
processed++;
}
}
return processed;
}
/**
* @dev Returns uId by index;
*/
function getContributorIndexes(uint index) external onlyMultiOwnersType(7) view returns(uint) {
return contributorIndexes[index];
}
/**
* @dev Recalculation contributors presale bonus
*/
function reCountUserPreSaleBonus(uint _uId, uint minTotalUsdAmountInCents, uint bonusPercent, uint maxPayTime) external onlyMultiOwnersType(13) returns(uint, uint) {
require(_uId > 0);
require(contributorList[_uId].active);
require(!refundUserIds[_uId]);
require(minTotalUsdAmountInCents > 10000);
require(bonusPercent > 20 && bonusPercent < 50);
uint bonusToken = 0;
uint uId = _uId;
uint beforeBonusToken = receivedPreSaleBonus[uId];
if (beforeBonusToken > 0) {
contributorList[uId].totalToken -= beforeBonusToken;
contributorList[uId].tokenBonus -= beforeBonusToken;
receivedPreSaleBonus[uId] = 0;
}
if (contributorList[uId].usdAbsRaisedInCents >= minTotalUsdAmountInCents) {
if (maxPayTime > 0) {
for (uint i = 0; i < contributorPayIds[uId].length; i++) {
PaymentData memory _payment = contributorList[uId].paymentInfo[contributorPayIds[uId][i]];
if (!refundPayIds[contributorPayIds[uId][i]] && _payment.bonusPercent == 0 && _payment.time < maxPayTime) {
bonusToken += _payment.tokenWithoutBonus.mul(bonusPercent).div(100);
}
}
} else {
bonusToken = contributorList[uId].tokenWithoutBonus.mul(bonusPercent).div(100);
}
if (bonusToken > 0) {
contributorList[uId].totalToken += bonusToken;
contributorList[uId].tokenBonus += bonusToken;
receivedPreSaleBonus[uId] = bonusToken;
emit GotPreSaleBonus(contributorList[uId].mainWallet);
}
}
return (beforeBonusToken, bonusToken);
}
/**
* @dev add user and wallet to whitelist
*/
function addWhiteList(uint uId, address addr) public onlyMultiOwnersType(1) returns(bool success) {
require(addr != address(0), "1");
require(uId > 0, "2");
require(!refundUserIds[uId]);
if (contributorIds[addr] > 0 && contributorIds[addr] != uId) {
success = false;
revert("3");
}
if (contributorList[uId].active != true) {
contributorList[uId].active = true;
contributorIndexes[nextContributorIndex] = uId;
nextContributorIndex++;
contributorList[uId].mainWallet = addr;
}
if (inArray(contributorList[uId].wallet, addr) != true && contributorList[uId].wallet.length < 3) {
contributorList[uId].wallet.push(addr);
contributorIds[addr] = uId;
emit WhitelistAddressAdded(addr);
success = true;
} else {
success = false;
}
}
/**
* @dev remove user wallet from whitelist
*/
function removeWhiteList(uint uId, address addr) public onlyMultiOwnersType(2) returns(bool success) {
require(contributorList[uId].active, "1");
require(addr != address(0), "2");
require(uId > 0, "3");
require(inArray(contributorList[uId].wallet, addr));
if (contributorPayIds[uId].length > 0 || contributorList[uId].mainWallet == addr) {
success = false;
revert("5");
}
contributorList[uId].wallet = removeValueFromArray(contributorList[uId].wallet, addr);
delete contributorIds[addr];
emit WhitelistAddressRemoved(addr);
success = true;
}
/**
* @dev Change contributor mainWallet
*/
function changeMainWallet(uint uId, address addr) public onlyMultiOwnersType(3) returns(bool) {
require(supportChangeMainWallet);
require(addr != address(0));
require(uId > 0);
require(contributorList[uId].active);
require(!refundUserIds[uId]);
require(inArray(contributorList[uId].wallet, addr));
contributorList[uId].mainWallet = addr;
emit ChangeMainWallet(addr);
return true;
}
/**
* @dev Change the right to change mainWallet
*/
function changeSupportChangeMainWallet(bool support) public onlyMultiOwnersType(21) returns(bool) {
supportChangeMainWallet = support;
return supportChangeMainWallet;
}
/**
* @dev Returns all contributor info by uId
*/
function getContributionInfoById(uint _uId) public onlyMultiOwnersType(4) view returns(
bool active,
string payInCurrency,
uint totalToken,
uint tokenWithoutBonus,
uint tokenBonus,
uint usdAbsRaisedInCents,
uint[] paymentInfoIds,
address mainWallet,
address[] wallet,
uint preSaleReceivedBonus,
bool receivedCoins,
bool refund
)
{
uint uId = _uId;
return getContributionInfo(contributorList[uId].mainWallet);
}
/**
* @dev Returns all contributor info by address
*/
function getContributionInfo(address _addr)
public
view
returns(
bool active,
string payInCurrency,
uint totalToken,
uint tokenWithoutBonus,
uint tokenBonus,
uint usdAbsRaisedInCents,
uint[] paymentInfoIds,
address mainWallet,
address[] wallet,
uint preSaleReceivedBonus,
bool receivedCoins,
bool refund
)
{
address addr = _addr;
StorageData memory storData = contributorList[contributorIds[addr]];
(preSaleReceivedBonus, receivedCoins, refund) = getInfoAdditionl(addr);
return(
storData.active,
(contributorPayIds[contributorIds[addr]].length > 0 ? getContributorPayInCurrency(contributorIds[addr]) : "[]"),
storData.totalToken,
storData.tokenWithoutBonus,
storData.tokenBonus,
storData.usdAbsRaisedInCents,
contributorPayIds[contributorIds[addr]],
storData.mainWallet,
storData.wallet,
preSaleReceivedBonus,
receivedCoins,
refund
);
}
/**
* @dev Returns contributor id by address
*/
function getContributorId(address addr) public onlyMultiOwnersType(5) view returns(uint) {
return contributorIds[addr];
}
/**
* @dev Returns contributors address by uId
*/
function getContributorAddressById(uint uId) public onlyMultiOwnersType(6) view returns(address) {
require(uId > 0);
require(contributorList[uId].active);
return contributorList[uId].mainWallet;
}
/**
* @dev Check wallet exists by address
*/
function checkWalletExists(address addr) public view returns(bool result) {
result = false;
if (contributorList[contributorIds[addr]].wallet.length > 0) {
result = inArray(contributorList[contributorIds[addr]].wallet, addr);
}
}
/**
* @dev Check userId is exists
*/
function checkUserIdExists(uint uId) public onlyMultiOwnersType(8) view returns(bool) {
return contributorList[uId].active;
}
/**
* @dev Add payment by address
*/
function addPayment(
address _addr,
string pType,
uint _value,
uint usdAmount,
uint currencyUSD,
uint tokenWithoutBonus,
uint tokenBonus,
uint bonusPercent,
uint payId
)
public
onlyMultiOwnersType(9)
returns(bool)
{
require(_value > 0);
require(usdAmount > 0);
require(tokenWithoutBonus > 0);
require(bytes(pType).length > 0);
assert((payId == 0 && stringsEqual(pType, "ETH")) || (payId > 0 && !payIds[payId]));
address addr = _addr;
uint uId = contributorIds[addr];
assert(addr != address(0));
assert(checkWalletExists(addr));
assert(uId > 0);
assert(contributorList[uId].active);
assert(!refundUserIds[uId]);
assert(!receivedCoin[uId]);
if (payId == 0) {
payId = genId(addr, _value, 0);
}
bytes32 _pType = stringToBytes32(pType);
PaymentData memory userPayment;
uint totalToken = tokenWithoutBonus.add(tokenBonus);
//userPayment.payId = payId;
userPayment.time = block.timestamp;
userPayment.pType = _pType;
userPayment.currencyUSD = currencyUSD;
userPayment.payValue = _value;
userPayment.totalToken = totalToken;
userPayment.tokenWithoutBonus = tokenWithoutBonus;
userPayment.tokenBonus = tokenBonus;
userPayment.bonusPercent = bonusPercent;
userPayment.usdAbsRaisedInCents = usdAmount;
if (!inArray(currencyTicker, _pType)) {
currencyTicker.push(_pType);
}
if (payId > 0) {
payIds[payId] = true;
}
contributorList[uId].usdAbsRaisedInCents += usdAmount;
contributorList[uId].totalToken += totalToken;
contributorList[uId].tokenWithoutBonus += tokenWithoutBonus;
contributorList[uId].tokenBonus += tokenBonus;
contributorList[uId].payInCurrency[_pType] += _value;
contributorList[uId].paymentInfo[payId] = userPayment;
contributorPayIds[uId].push(payId);
emit AddPayment(addr);
return true;
}
/**
* @dev Add payment by uId
*/
function addPayment(
uint uId,
string pType,
uint _value,
uint usdAmount,
uint currencyUSD,
uint tokenWithoutBonus,
uint tokenBonus,
uint bonusPercent,
uint payId
)
public
returns(bool)
{
require(contributorList[uId].active);
require(contributorList[uId].mainWallet != address(0));
return addPayment(contributorList[uId].mainWallet, pType, _value, usdAmount, currencyUSD, tokenWithoutBonus, tokenBonus, bonusPercent, payId);
}
/**
* @dev Edit user payment info
*/
function editPaymentByUserId(
uint uId,
uint payId,
uint _payValue,
uint _usdAmount,
uint _currencyUSD,
uint _totalToken,
uint _tokenWithoutBonus,
uint _tokenBonus,
uint _bonusPercent
)
public
onlyMultiOwnersType(10)
returns(bool)
{
require(contributorList[uId].active);
require(inArray(contributorPayIds[uId], payId));
require(!refundPayIds[payId]);
require(!refundUserIds[uId]);
require(!receivedCoin[uId]);
PaymentData memory oldPayment = contributorList[uId].paymentInfo[payId];
contributorList[uId].usdAbsRaisedInCents -= oldPayment.usdAbsRaisedInCents;
contributorList[uId].totalToken -= oldPayment.totalToken;
contributorList[uId].tokenWithoutBonus -= oldPayment.tokenWithoutBonus;
contributorList[uId].tokenBonus -= oldPayment.tokenBonus;
contributorList[uId].payInCurrency[oldPayment.pType] -= oldPayment.payValue;
contributorList[uId].paymentInfo[payId] = PaymentData(
oldPayment.time,
oldPayment.pType,
_currencyUSD,
_payValue,
_totalToken,
_tokenWithoutBonus,
_tokenBonus,
_bonusPercent,
_usdAmount
);
contributorList[uId].usdAbsRaisedInCents += _usdAmount;
contributorList[uId].totalToken += _totalToken;
contributorList[uId].tokenWithoutBonus += _tokenWithoutBonus;
contributorList[uId].tokenBonus += _tokenBonus;
contributorList[uId].payInCurrency[oldPayment.pType] += _payValue;
emit EditUserPayments(contributorList[uId].mainWallet, payId);
return true;
}
/**
* @dev Refund user payment
*/
function refundPaymentByUserId(uint uId, uint payId) public onlyMultiOwnersType(20) returns(bool) {
require(contributorList[uId].active);
require(inArray(contributorPayIds[uId], payId));
require(!refundPayIds[payId]);
require(!refundUserIds[uId]);
require(!receivedCoin[uId]);
PaymentData memory oldPayment = contributorList[uId].paymentInfo[payId];
assert(oldPayment.pType != stringToBytes32("ETH"));
contributorList[uId].usdAbsRaisedInCents -= oldPayment.usdAbsRaisedInCents;
contributorList[uId].totalToken -= oldPayment.totalToken;
contributorList[uId].tokenWithoutBonus -= oldPayment.tokenWithoutBonus;
contributorList[uId].tokenBonus -= oldPayment.tokenBonus;
contributorList[uId].payInCurrency[oldPayment.pType] -= oldPayment.payValue;
refundPayIds[payId] = true;
emit RefundPayment(contributorList[uId].mainWallet, payId);
return true;
}
/**
* @dev Reutrns user payment info by uId and paymentId
*/
function getUserPaymentById(uint _uId, uint _payId) public onlyMultiOwnersType(11) view returns(
uint time,
bytes32 pType,
uint currencyUSD,
uint bonusPercent,
uint payValue,
uint totalToken,
uint tokenBonus,
uint tokenWithoutBonus,
uint usdAbsRaisedInCents,
bool refund
)
{
uint uId = _uId;
uint payId = _payId;
require(contributorList[uId].active);
require(inArray(contributorPayIds[uId], payId));
PaymentData memory payment = contributorList[uId].paymentInfo[payId];
return (
payment.time,
payment.pType,
payment.currencyUSD,
payment.bonusPercent,
payment.payValue,
payment.totalToken,
payment.tokenBonus,
payment.tokenWithoutBonus,
payment.usdAbsRaisedInCents,
refundPayIds[payId] ? true : false
);
}
/**
* @dev Reutrns user payment info by address and payment id
*/
function getUserPayment(address addr, uint _payId) public view returns(
uint time,
string pType,
uint currencyUSD,
uint bonusPercent,
uint payValue,
uint totalToken,
uint tokenBonus,
uint tokenWithoutBonus,
uint usdAbsRaisedInCents,
bool refund
)
{
address _addr = addr;
require(contributorList[contributorIds[_addr]].active);
require(inArray(contributorPayIds[contributorIds[_addr]], _payId));
uint payId = _payId;
PaymentData memory payment = contributorList[contributorIds[_addr]].paymentInfo[payId];
return (
payment.time,
bytes32ToString(payment.pType),
payment.currencyUSD,
payment.bonusPercent,
payment.payValue,
payment.totalToken,
payment.tokenBonus,
payment.tokenWithoutBonus,
payment.usdAbsRaisedInCents,
refundPayIds[payId] ? true : false
);
}
/**
* @dev Returns payment in ETH from address
*/
function getEthPaymentContributor(address addr) public view returns(uint) {
return contributorList[contributorIds[addr]].payInCurrency[stringToBytes32("ETH")];
}
/**
* @dev Returns SHPC from address
*/
function getTotalCoin(address addr) public view returns(uint) {
return contributorList[contributorIds[addr]].totalToken;
}
/**
* @dev Check user get pre sale bonus by address
*/
function checkPreSaleReceivedBonus(address addr) public view returns(bool) {
return receivedPreSaleBonus[contributorIds[addr]] > 0 ? true : false;
}
/**
* @dev Check payment refund by payment id
*/
function checkPaymentRefund(uint payId) public view returns(bool) {
return refundPayIds[payId];
}
/**
* @dev Check user refund by address
*/
function checkRefund(address addr) public view returns(bool) {
return refundUserIds[contributorIds[addr]];
}
/**
* @dev Set start number generate payment id when user pay in eth
*/
function setStartGenId(uint startId) public onlyMultiOwnersType(14) {
require(startId > 0);
startGenId = startId;
}
/**
* @dev Set contributer got SHPC
*/
function setReceivedCoin(uint uId) public onlyMultiOwnersType(15) returns(bool) {
require(contributorList[uId].active);
require(!refundUserIds[uId]);
require(!receivedCoin[uId]);
receivedCoin[uId] = true;
emit ReceivedCoin(contributorList[uId].mainWallet);
return true;
}
/**
* @dev Set contributer got refund ETH
*/
function setRefund(uint uId) public onlyMultiOwnersType(16) returns(bool) {
require(contributorList[uId].active);
require(!refundUserIds[uId]);
require(!receivedCoin[uId]);
refundUserIds[uId] = true;
emit Refund(contributorList[uId].mainWallet);
return true;
}
/**
* @dev Check contributor got SHPC
*/
function checkReceivedCoins(address addr) public view returns(bool) {
return receivedCoin[contributorIds[addr]];
}
/**
* @dev Check contributor got ETH
*/
function checkReceivedEth(address addr) public view returns(bool) {
return refundUserIds[contributorIds[addr]];
}
/**
* @dev Returns all contributor currency amount in json
*/
function getContributorPayInCurrency(uint uId) private view returns(string) {
require(uId > 0);
require(contributorList[uId].active);
string memory payInCurrency = "{";
for (uint i = 0; i < currencyTicker.length; i++) {
payInCurrency = strConcat(payInCurrency, strConcat("\"", bytes32ToString(currencyTicker[i]), "\":\""), uint2str(contributorList[uId].payInCurrency[currencyTicker[i]]), (i+1 < currencyTicker.length) ? "\"," : "\"}");
}
return payInCurrency;
}
/**
* @dev Check receives presale bonud by uId
*/
function checkPreSaleReceivedBonus(uint uId) private view returns(bool) {
return receivedPreSaleBonus[uId] > 0 ? true : false;
}
/**
* @dev Check refund by uId
*/
function checkRefund(uint uId) private view returns(bool) {
return refundUserIds[uId];
}
/**
* @dev Check received SHPC by uI
*/
function checkReceivedCoins(uint id) private view returns(bool) {
return receivedCoin[id];
}
/**
* @dev Check received eth by uId
*/
function checkReceivedEth(uint id) private view returns(bool) {
return refundUserIds[id];
}
/**
* @dev Returns new uniq payment id
*/
function genId(address addr, uint ammount, uint rand) private view returns(uint) {
uint id = startGenId + uint8(keccak256(abi.encodePacked(addr, blockhash(block.number), ammount, rand))) + contributorPayIds[contributorIds[addr]].length;
if (!payIds[id]) {
return id;
} else {
return genId(addr, ammount, id);
}
}
/**
* @dev Returns payment in ETH from uid
*/
function getEthPaymentContributor(uint uId) private view returns(uint) {
return contributorList[uId].payInCurrency[stringToBytes32("ETH")];
}
/**
* @dev Returns adittional info by contributor address
*/
function getInfoAdditionl(address addr) private view returns(uint, bool, bool) {
return(receivedPreSaleBonus[contributorIds[addr]], receivedCoin[contributorIds[addr]], refundUserIds[contributorIds[addr]]);
}
/**
* @dev Returns payments info by userId in json
*/
function getArrayjsonPaymentInfo(uint uId) private view returns (string) {
string memory _array = "{";
for (uint i = 0; i < contributorPayIds[uId].length; i++) {
_array = strConcat(_array, getJsonPaymentInfo(contributorList[uId].paymentInfo[contributorPayIds[uId][i]], contributorPayIds[uId][i]), (i+1 == contributorPayIds[uId].length) ? "}" : ",");
}
return _array;
}
/**
* @dev Returns payment info by payment data in json
*/
function getJsonPaymentInfo(PaymentData memory _obj, uint payId) private view returns (string) {
return strConcat(
strConcat("\"", uint2str(payId), "\":{", strConcat("\"", "time", "\":"), uint2str(_obj.time)),
strConcat(",\"pType\":\"", bytes32ToString(_obj.pType), "\",\"currencyUSD\":", uint2str(_obj.currencyUSD), ",\"payValue\":\""),
strConcat(uint2str(_obj.payValue), "\",\"totalToken\":\"", uint2str(_obj.totalToken), "\",\"tokenWithoutBonus\":\"", uint2str(_obj.tokenWithoutBonus)),
strConcat("\",\"tokenBonus\":\"", uint2str(_obj.tokenBonus), "\",\"bonusPercent\":", uint2str(_obj.bonusPercent)),
strConcat(",\"usdAbsRaisedInCents\":\"", uint2str(_obj.usdAbsRaisedInCents), "\",\"refund\":\"", (refundPayIds[payId] ? "1" : "0"), "\"}")
);
}
/**
* @dev Check if value contains array
*/
function inArray(address[] _array, address _value) private pure returns(bool result) {
if (_array.length == 0 || _value == address(0)) {
return false;
}
result = false;
for (uint i = 0; i < _array.length; i++) {
if (_array[i] == _value) {
result = true;
return true;
}
}
}
/**
* @dev Check if value contains array
*/
function inArray(uint[] _array, uint _value) private pure returns(bool result) {
if (_array.length == 0 || _value == 0) {
return false;
}
result = false;
for (uint i = 0; i < _array.length; i++) {
if (_array[i] == _value) {
result = true;
return true;
}
}
}
/**
* @dev Check if value contains array
*/
function inArray(bytes32[] _array, bytes32 _value) private pure returns(bool result) {
if (_array.length == 0 || _value.length == 0) {
return false;
}
result = false;
for (uint i = 0; i < _array.length; i++) {
if (_array[i] == _value) {
result = true;
return true;
}
}
}
/**
* @dev Remove value from arary
*/
function removeValueFromArray(address[] _array, address _value) private pure returns(address[]) {
address[] memory arrayNew = new address[](_array.length-1);
if (arrayNew.length == 0) {
return arrayNew;
}
uint i1 = 0;
for (uint i = 0; i < _array.length; i++) {
if (_array[i] != _value) {
arrayNew[i1++] = _array[i];
}
}
return arrayNew;
}
}
pragma solidity ^0.4.22;
import "./BasicToken.sol";
import "./ERC20.sol";
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* @dev https://github.com/ethereum/EIPs/issues/20
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*/
contract StandardToken is ERC20, BasicToken {
mapping (address => mapping (address => uint256)) internal allowed;
/**
* @dev Transfer tokens from one address to another
* @param _from address The address which you want to send tokens from
* @param _to address The address which you want to transfer to
* @param _value uint256 the amount of tokens to be transferred
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
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;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
*
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param _spender The address which will spend the funds.
* @param _value The amount of tokens to be spent.
*/
function approve(address _spender, uint256 _value) public returns (bool) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param _owner address The address which owns the funds.
* @param _spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address _owner, address _spender) public view returns (uint256) {
return allowed[_owner][_spender];
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
*
* approve should be called when allowed[_spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* @param _spender The address which will spend the funds.
* @param _addedValue The amount of tokens to increase the allowance by.
*/
function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
*
* approve should be called when allowed[_spender] == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* @param _spender The address which will spend the funds.
* @param _subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
uint oldValue = allowed[msg.sender][_spender];
if (_subtractedValue > oldValue) {
allowed[msg.sender][_spender] = 0;
} else {
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
}
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
}
pragma solidity ^0.4.24;
/**
* @title String
* @dev ConcatenationString, uintToString, stringsEqual, stringToBytes32, bytes32ToString
*/
contract String {
function strConcat(string _a, string _b, string _c, string _d, string _e) internal pure returns (string memory) {
bytes memory _ba = bytes(_a);
bytes memory _bb = bytes(_b);
bytes memory _bc = bytes(_c);
bytes memory _bd = bytes(_d);
bytes memory _be = bytes(_e);
bytes memory abcde = bytes(new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length));
uint k = 0;
uint i;
for (i = 0; i < _ba.length; i++) {
abcde[k++] = _ba[i];
}
for (i = 0; i < _bb.length; i++) {
abcde[k++] = _bb[i];
}
for (i = 0; i < _bc.length; i++) {
abcde[k++] = _bc[i];
}
for (i = 0; i < _bd.length; i++) {
abcde[k++] = _bd[i];
}
for (i = 0; i < _be.length; i++) {
abcde[k++] = _be[i];
}
return string(abcde);
}
function strConcat(string _a, string _b, string _c, string _d) internal pure returns(string) {
return strConcat(_a, _b, _c, _d, "");
}
function strConcat(string _a, string _b, string _c) internal pure returns(string) {
return strConcat(_a, _b, _c, "", "");
}
function strConcat(string _a, string _b) internal pure returns(string) {
return strConcat(_a, _b, "", "", "");
}
function uint2str(uint i) internal pure returns(string) {
if (i == 0) {
return "0";
}
uint j = i;
uint length;
while (j != 0) {
length++;
j /= 10;
}
bytes memory bstr = new bytes(length);
uint k = length - 1;
while (i != 0) {
bstr[k--] = byte(uint8(48 + i % 10));
i /= 10;
}
return string(bstr);
}
function stringsEqual(string memory _a, string memory _b) internal pure returns(bool) {
bytes memory a = bytes(_a);
bytes memory b = bytes(_b);
if (a.length != b.length)
return false;
for (uint i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}
function stringToBytes32(string memory source) internal pure returns(bytes32 result) {
bytes memory _tmp = bytes(source);
if (_tmp.length == 0) {
return 0x0;
}
assembly {
result := mload(add(source, 32))
}
}
function bytes32ToString(bytes32 x) internal pure returns (string) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
uint j;
for (j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
function inArray(string[] _array, string _value) internal pure returns(bool result) {
if (_array.length == 0 || bytes(_value).length == 0) {
return false;
}
result = false;
for (uint i = 0; i < _array.length; i++) {
if (stringsEqual(_array[i],_value)) {
result = true;
return true;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment