Skip to content

Commit

Permalink
All tests are passed
Browse files Browse the repository at this point in the history
  • Loading branch information
nkrivenko committed Apr 20, 2018
0 parents commit d06818b
Show file tree
Hide file tree
Showing 22 changed files with 4,319 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": [ "es2015", "stage-2", "stage-3" ]
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build/*
node_modules/*
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## MONORETO ITO PROJECT

The project uses:
1. Ethereum blockchain as a base of infrastructure
2. Truffle for testing
3. OpenZeppelin contracts as a base of source code
92 changes: 92 additions & 0 deletions contracts/BaseMonoretoCrowdsale.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
pragma solidity ^0.4.19;

import "zeppelin-solidity/contracts/crowdsale/distribution/RefundableCrowdsale.sol";
import "zeppelin-solidity/contracts/crowdsale/validation/CappedCrowdsale.sol";
import "zeppelin-solidity/contracts/crowdsale/emission/MintedCrowdsale.sol";

import "./MonoretoToken.sol";

/**
* @title Base contract for Monoreto PreICO and ICO
*/
contract BaseMonoretoCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale {

uint256 public usdEth;
uint256 public usdMnr;
uint256 public tokensPurchased;
uint256 public tokenTarget;

/**
* @dev USDMNR must be set as actual_value * CENT_DECIMALS
* @dev example: value 0.2$ per token must be set as 0.2 * CENT_DECIMALS
*/
uint256 public constant CENT_DECIMALS = 100000;

// original contract owner, needed for transfering the ownership of token back after the end of crowdsale
address internal deployer;

function BaseMonoretoCrowdsale(uint256 _tokenTarget, uint256 _usdEth, uint256 _usdMnr) public
{
require(_tokenTarget > 0);
require(_usdEth > 0);
require(_usdMnr > 0);

tokenTarget = _tokenTarget;
usdEth = _usdEth;
usdMnr = _usdMnr;

deployer = msg.sender;
}

event UsdEthRateChanged(address indexed changerAddress, uint256 UsdEthRate);
event UsdMnrRateChanged(address indexed changerAddress, uint256 UsdMnrRate);

function setUsdEth(uint256 _usdEth) external onlyOwner {
rate = _usdEth.mul(CENT_DECIMALS).div(usdMnr);
usdEth = _usdEth;
UsdEthRateChanged(msg.sender, _usdEth);
}

function setUsdMnr(uint256 _usdMnr) external onlyOwner {
rate = usdEth.mul(CENT_DECIMALS).div(_usdMnr);
usdMnr = _usdMnr;
UsdMnrRateChanged(msg.sender, _usdMnr);
}

// If amount of wei sent is less than the threshold, revert.
uint256 private constant THRESHOLD = 100 finney;

function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
require(tokensPurchased + _getTokenAmount(_weiAmount) <= tokenTarget);
require(_weiAmount >= THRESHOLD);
super._preValidatePurchase(_beneficiary, _weiAmount);
}

function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
return _weiAmount.mul(usdEth).mul(CENT_DECIMALS).div(usdMnr);
}

function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
super._deliverTokens(_beneficiary, _tokenAmount);
tokensPurchased = tokensPurchased.add(_tokenAmount);
}

function hasClosed() public view returns (bool) {
return super.hasClosed() || capReached();
}

/**
* @dev overriden template method from FinalizableCrowdsale.
* Returns the ownership of token to the original owner.
* The child contract should call super.finalization()
* AFTER executing its own finalizing actions.
*/
function finalization() internal {
super.finalization();

MonoretoToken castToken = MonoretoToken(token);
castToken.transferOwnership(deployer);
}

}

23 changes: 23 additions & 0 deletions contracts/Migrations.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pragma solidity ^0.4.17;

contract Migrations {
address public owner;
uint public last_completed_migration;

modifier restricted() {
if (msg.sender == owner) _;
}

function Migrations() public {
owner = msg.sender;
}

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);
}
}
95 changes: 95 additions & 0 deletions contracts/MonoretoIco.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
pragma solidity ^0.4.19;

import "./BaseMonoretoCrowdsale.sol";

contract MonoretoIco is BaseMonoretoCrowdsale {

address public bountyWallet;
address public teamWallet;

function MonoretoIco(uint256 _openTime, uint256 _closeTime, uint256 _usdEth, uint256 _usdMnr, uint256 _goal, uint256 _cap, uint256 _tokensTarget, address _ownerWallet, MonoretoToken _token) public
BaseMonoretoCrowdsale(_tokensTarget, _usdEth, _usdMnr)
CappedCrowdsale(_cap)
RefundableCrowdsale(_goal)
FinalizableCrowdsale()
TimedCrowdsale(_openTime, _closeTime)
Crowdsale(1, _ownerWallet, _token) {
require(_goal <= _cap);
rate = _usdEth.mul(CENT_DECIMALS).div(_usdMnr);
}

uint256[] public bonusTimes;
uint256[] public bonusTimesPercents;

function getBonusTimes() external view returns(uint256[]) {
return bonusTimes;
}

function getBonusTimesPercents() external view returns(uint256[]) {
return bonusTimesPercents;
}

function setAdditionalWallets(address _teamWallet, address _bountyWallet) public onlyOwner {
require(_teamWallet != address(0));
require(_bountyWallet != address(0));

teamWallet = _teamWallet;
bountyWallet = _bountyWallet;
}

bool private bonusesSet = false;

function setBonusTimes(uint256[] times, uint256[] values) external onlyOwner onlyWhileOpen {
require(times.length == values.length);

for (uint256 i = 0; i < times.length - 1; i++) {
require(times[i] < times[i + 1]);
}

bonusTimes = times;
bonusTimesPercents = values;

bonusesSet = true;
}

function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
super._preValidatePurchase(_beneficiary, _weiAmount);
require(bonusesSet);
}

function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
return _weiAmount.mul(usdEth).mul(CENT_DECIMALS).mul(computeBonusValueInPercents()).div(100).div(usdMnr);
}

/**
* @dev computes the bonus percent corresponding the current time
* bonuses must be set, of course.
*/
function computeBonusValueInPercents() private constant returns(uint256) {
for (uint i = 0; i < bonusTimes.length; i++) {
if (now.sub(openingTime) <= bonusTimes[i]) return bonusTimesPercents[i];
}

return 100;
}

function finalization() internal {
require(teamWallet != address(0));
require(bountyWallet != address(0));

MonoretoToken castToken = MonoretoToken(token);

if (goalReached()) {
uint256 tokenSupply = castToken.cap();

castToken.mint(wallet, tokenSupply.mul(23).div(100));
castToken.mint(teamWallet, tokenSupply.mul(11).div(100));
castToken.mint(bountyWallet, tokenSupply.mul(3).div(100));
}

castToken.finishMinting();

super.finalization();
}
}

28 changes: 28 additions & 0 deletions contracts/MonoretoPreIco.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
pragma solidity ^0.4.19;

import "./BaseMonoretoCrowdsale.sol";

contract MonoretoPreIco is BaseMonoretoCrowdsale {

function MonoretoPreIco(uint256 _openTime, uint256 _closeTime, uint256 _goal, uint256 _cap, uint256 _centWeiRate, uint256 _centMnrRate, uint256 _tokenTarget, address _ownerWallet, MonoretoToken _token) public
BaseMonoretoCrowdsale(_tokenTarget, _centWeiRate, _centMnrRate)
CappedCrowdsale(_cap)
RefundableCrowdsale(_goal)
FinalizableCrowdsale()
TimedCrowdsale(_openTime, _closeTime)
Crowdsale(_centWeiRate.mul(CENT_DECIMALS).div(_centMnrRate), _ownerWallet, _token)
{
require(_goal <= _cap);
}

/**
* @dev Pre-ICO finalization. Cap must be adjusted after pre-ico.
*/
function finalization() internal {
MonoretoToken castToken = MonoretoToken(token);
castToken.adjustCap();

super.finalization();
}
}

30 changes: 30 additions & 0 deletions contracts/MonoretoToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
pragma solidity ^0.4.19;

import "zeppelin-solidity/contracts/token/ERC20/CappedToken.sol";

/**
* @title Token for Monoreto ICO
* @dev Monoreto ICO needs an ERC20 token
*/
contract MonoretoToken is CappedToken {
string public constant name = "Monoreto Token";
string public constant symbol = "MNR";
uint8 public constant decimals = 18;

uint8 private constant percentToAdjust = 6;

function MonoretoToken(uint256 _cap) public
CappedToken(_cap) {

}

bool public capAdjusted = false;

function adjustCap() public onlyOwner {
require(!capAdjusted);
cap = totalSupply().mul(100).div(percentToAdjust);

capAdjusted = true;
}
}

5 changes: 5 additions & 0 deletions migrations/1_initial_migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var Migrations = artifacts.require("./Migrations.sol");

module.exports = function(deployer) {
deployer.deploy(Migrations);
};
42 changes: 42 additions & 0 deletions migrations/2_crowdsale_migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//var MonoretoCrowdsale = artifacts.require("./MonoretoCrowdsale.sol");
// var MonoretoToken = artifacts.require("./MonoretoToken.sol");

const duration = {
seconds: function(val) { return val},
minutes: function(val) { return val * this.seconds(60) },
hours: function(val) { return val * this.minutes(60) },
days: function(val) { return val * this.hours(24) },
weeks: function(val) { return val * this.days(7) },
years: function(val) { return val * this.days(365)}
};

module.exports = function(deployer, network, accounts) {

var startTime = web3.eth.getBlock(web3.eth.blockNumber).timestamp + duration.minutes(1);
var endTime = startTime + duration.minutes(5);
var rate = new web3.BigNumber(1e15);
var goal = new web3.BigNumber(web3.toWei("1", "finney"));
var cap = new web3.BigNumber(web3.toWei("10", "ether"));
var wallet = accounts[1];

if (network == "rinkeby") {
startTime = web3.eth.getBlock(web3.eth.blockNumber).timestamp + duration.minutes(1);
endTime = startTime + duration.minutes(5);
rate = new web3.BigNumber(1e15);
goal = new web3.BigNumber(web3.toWei("1", "finney"));
cap = new web3.BigNumber(web3.toWei("10", "ether"));
wallet = accounts[1];
} else if (network == "live") {
startTime = web3.eth.getBlock(web3.eth.blockNumber).timestamp + duration.minutes(1);
endTime = startTime + duration.days(30);
rate = new web3.BigNumber(1e15);
goal = new web3.BigNumber(web3.toWei("1", "finney"));
cap = new web3.BigNumber(web3.toWei("10", "ether"));
wallet = accounts[1];
}

// deployer.deploy(MonoretoToken, { overwrite: false });
/*deployer.deploy(MonoretoCrowdsale, startTime, endTime, rate, goal, cap, wallet).then(function(instance) {
// instance.setBonusTimes();
});*/
};
Loading

0 comments on commit d06818b

Please sign in to comment.