Merge branch 'release/1.2.0'

This commit is contained in:
David E. Perez Negron Rocha 2020-05-09 22:49:52 -05:00
commit 3d723163e8
20 changed files with 38832 additions and 4 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
package-lock.json
/node_modules

26
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,26 @@
image: node:12.16.3
before_script:
- npm install -g ganache-cli
- npm install -g truffle@5.1.3
- npm i @openzeppelin/contracts@2.4.0
stages:
- build
- test
build:
stage: build
script:
- truffle compile
tags:
- docker
test:
stage: test
script:
- ./run-rpc.sh &
- truffle test
tags:
- docker

View File

@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found. the "copyright" line and a pointer to where the full notice is found.
DCC DCC
Copyright (C) 2018 NH-DEVs Copyright (C) 2018 NEETSEC INTERNATIONAL INC.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode: notice like this when it starts in an interactive mode:
DCC Copyright (C) 2018 NH-DEVs DCC Copyright (C) 2018 NEETSEC INTERNATIONAL INC.
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.

186
README.md
View File

@ -1,3 +1,185 @@
# DCC Decentralized Carbon Credits ERC20
===
![build](https://gitlab.com/deca-currency/dcc/badges/develop/pipeline.svg)
[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/deca-currency/community)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
Decentralized Carbon Credits in an ERC20 by neetsec Decentralized Carbon Credits in an ERC20 by Neetsec
## Table of Contents
[[_TOC_]]
## DECA Project Tree
```sh
|-- LICENSE
|-- README.md
|-- contracts
|-- build
| |-- contracts
| |-- Context.json
| |-- DECA.json
| |-- ERC20.json
| |-- IERC20.json
| |-- Migrations.json
| |-- Ownable.json
| `-- SafeMath.json
| |-- DECA.sol
| `-- Migrations.sol
|-- migrations
| |-- 1_initial_migration.js
| `-- 2_deploy_contracts.js
|-- package.json
|-- run-rpc.sh
|-- test
| `-- DECA.js
|-- truffle.js
|-- .gitignore
|-- .gitlab-ci.yml
```
## Requirements
* Node.js >= 12
* @openzeppelin/contracts = 2.4.0
#### Global install
* ganache-cli >= 6.9.1
* truffle = 5.1.3
## Instalation
**Download and install Node.js v12.x and npm.**
* Node.js
**Using Ubuntu**
```sh
$ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
$ sudo apt-get install -y nodejs
```
**Using Debian, as root**
```sh
$ curl -sL https://deb.nodesource.com/setup_12.x | bash -
$ apt-get install -y nodejs
```
**Clone the repo**
```sh
$ git clone https://gitlab.com/deca-currency/dcc.git
$ cd dcc
```
**Install the dependencies**
```sh
$ npm install
```
**Install ganache-cli**
```sh
$ sudo npm install -g ganache-cli
```
**Install truffle**
```sh
$ sudo npm install -g truffle@5.1.3
```
## Testing the Smart Contract:
- can see the test in pipelines or you can run it locally
#### Running locally
- open shell and execute "./run-rpc.sh" (remember change /usr/local/bin/ganache-cli to your path)
```sh
$ ./run-rpc.sh
```
- open second shell, and execute
```sh
$ truffle tests
```
## Class Diagram ERC20 Token generated with [sol2uml](https://github.com/naddison36/sol2uml)
<p align="center">
<img src="uml/diagram.png" width="720" />
</p>
## Specification
### Methods
Apart from the [ERC20 standard](https://eips.ethereum.org/EIPS/eip-20) methods that our token complies, we introduce some
improvements, either for security or others that match DECA specific requirements.
**Notes:**
* The following specifications use syntax from Solidity (0.5.12)
#### owner
Returns the address of the current owner.
```sh
function owner() public view returns (address payable)
```
#### isOwner
Returns true if the caller is the current owner.
```sh
function isOwner() public view returns (bool)
```
#### transferOwnership
Can only be called by the current owner.
```sh
function transferOwnership(address payable newOwner) public onlyOwner
```
#### updateCCDBAddress
Updates the official orbitDB address for carbon credits.
Can Only be updated by the current owner
```sh
function updateCCDBAddress(string memory newCCDBAddress) public onlyOwner
```
#### transferAnyERC20Token
Owner can transfer out any accidentally sent ERC20 tokens
```sh
function transferAnyERC20Token(address payable tokenAddress, uint tokens) public onlyOwner returns (bool success)
```
#### getETH
Close down the ICO and claim the Ether.
```sh
function getETH() public onlyOwner { require(now >= endDate); owner().transfer(address(this).balance); }
```
## DECA Promotion Dates
Now, based on the total Ethereums we got by the ICO (ETHTS)
and considering our promodates which are:
| PROMO | TIME (weeks) | DECA TOKENS PER ETH |
|--------|--------------|---------------------|
| preICO | 1 | 300 |
| Bonus1 | 2 | 275 |
| Bonus2 | 3 | 250 |
| ICO | 5 | 225 |

View File

@ -0,0 +1,595 @@
{
"contractName": "Context",
"abi": [
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
}
],
"metadata": "{\"compiler\":{\"version\":\"0.5.12+commit.7709ece9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/GSN/Context.sol\":\"Context\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/GSN/Context.sol\":{\"keccak256\":\"0x90a3995645af7562d84b9d69363ffa5ae7217714ab61e951bf7bc450f40e4061\",\"urls\":[\"bzz-raw://216ef9d6b614db4eb46970b4e84903f2534a45572dd30a79f0041f1a5830f436\",\"dweb:/ipfs/QmNPrJ4MWKUAWzKXpUqeyKRUfosaoANZAqXgvepdrCwZAG\"]}},\"version\":1}",
"bytecode": "0x",
"deployedBytecode": "0x",
"sourceMap": "",
"deployedSourceMap": "",
"source": "pragma solidity ^0.5.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\ncontract Context {\n // Empty internal constructor, to prevent people from mistakenly deploying\n // an instance of this contract, which should be used via inheritance.\n constructor () internal { }\n // solhint-disable-previous-line no-empty-blocks\n\n function _msgSender() internal view returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n",
"sourcePath": "@openzeppelin/contracts/GSN/Context.sol",
"ast": {
"absolutePath": "@openzeppelin/contracts/GSN/Context.sol",
"exportedSymbols": {
"Context": [
417
]
},
"id": 418,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 392,
"literals": [
"solidity",
"^",
"0.5",
".0"
],
"nodeType": "PragmaDirective",
"src": "0:23:2"
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 417,
"linearizedBaseContracts": [
417
],
"name": "Context",
"nodeType": "ContractDefinition",
"nodes": [
{
"body": {
"id": 395,
"nodeType": "Block",
"src": "726:3:2",
"statements": []
},
"documentation": null,
"id": 396,
"implemented": true,
"kind": "constructor",
"modifiers": [],
"name": "",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 393,
"nodeType": "ParameterList",
"parameters": [],
"src": "714:2:2"
},
"returnParameters": {
"id": 394,
"nodeType": "ParameterList",
"parameters": [],
"src": "726:0:2"
},
"scope": 417,
"src": "702:27:2",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "internal"
},
{
"body": {
"id": 404,
"nodeType": "Block",
"src": "850:34:2",
"statements": [
{
"expression": {
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 401,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1093,
"src": "867:3:2",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 402,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "sender",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "867:10:2",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"functionReturnParameters": 400,
"id": 403,
"nodeType": "Return",
"src": "860:17:2"
}
]
},
"documentation": null,
"id": 405,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "_msgSender",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 397,
"nodeType": "ParameterList",
"parameters": [],
"src": "807:2:2"
},
"returnParameters": {
"id": 400,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 399,
"name": "",
"nodeType": "VariableDeclaration",
"scope": 405,
"src": "833:15:2",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
},
"typeName": {
"id": 398,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "833:15:2",
"stateMutability": "payable",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"value": null,
"visibility": "internal"
}
],
"src": "832:17:2"
},
"scope": 417,
"src": "788:96:2",
"stateMutability": "view",
"superFunction": null,
"visibility": "internal"
},
{
"body": {
"id": 415,
"nodeType": "Block",
"src": "947:165:2",
"statements": [
{
"expression": {
"argumentTypes": null,
"id": 410,
"name": "this",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1107,
"src": "957:4:2",
"typeDescriptions": {
"typeIdentifier": "t_contract$_Context_$417",
"typeString": "contract Context"
}
},
"id": 411,
"nodeType": "ExpressionStatement",
"src": "957:4:2"
},
{
"expression": {
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 412,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1093,
"src": "1097:3:2",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 413,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "data",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "1097:8:2",
"typeDescriptions": {
"typeIdentifier": "t_bytes_calldata_ptr",
"typeString": "bytes calldata"
}
},
"functionReturnParameters": 409,
"id": 414,
"nodeType": "Return",
"src": "1090:15:2"
}
]
},
"documentation": null,
"id": 416,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "_msgData",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 406,
"nodeType": "ParameterList",
"parameters": [],
"src": "907:2:2"
},
"returnParameters": {
"id": 409,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 408,
"name": "",
"nodeType": "VariableDeclaration",
"scope": 416,
"src": "933:12:2",
"stateVariable": false,
"storageLocation": "memory",
"typeDescriptions": {
"typeIdentifier": "t_bytes_memory_ptr",
"typeString": "bytes"
},
"typeName": {
"id": 407,
"name": "bytes",
"nodeType": "ElementaryTypeName",
"src": "933:5:2",
"typeDescriptions": {
"typeIdentifier": "t_bytes_storage_ptr",
"typeString": "bytes"
}
},
"value": null,
"visibility": "internal"
}
],
"src": "932:14:2"
},
"scope": 417,
"src": "890:222:2",
"stateMutability": "view",
"superFunction": null,
"visibility": "internal"
}
],
"scope": 418,
"src": "525:589:2"
}
],
"src": "0:1115:2"
},
"legacyAST": {
"absolutePath": "@openzeppelin/contracts/GSN/Context.sol",
"exportedSymbols": {
"Context": [
417
]
},
"id": 418,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 392,
"literals": [
"solidity",
"^",
"0.5",
".0"
],
"nodeType": "PragmaDirective",
"src": "0:23:2"
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 417,
"linearizedBaseContracts": [
417
],
"name": "Context",
"nodeType": "ContractDefinition",
"nodes": [
{
"body": {
"id": 395,
"nodeType": "Block",
"src": "726:3:2",
"statements": []
},
"documentation": null,
"id": 396,
"implemented": true,
"kind": "constructor",
"modifiers": [],
"name": "",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 393,
"nodeType": "ParameterList",
"parameters": [],
"src": "714:2:2"
},
"returnParameters": {
"id": 394,
"nodeType": "ParameterList",
"parameters": [],
"src": "726:0:2"
},
"scope": 417,
"src": "702:27:2",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "internal"
},
{
"body": {
"id": 404,
"nodeType": "Block",
"src": "850:34:2",
"statements": [
{
"expression": {
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 401,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1093,
"src": "867:3:2",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 402,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "sender",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "867:10:2",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"functionReturnParameters": 400,
"id": 403,
"nodeType": "Return",
"src": "860:17:2"
}
]
},
"documentation": null,
"id": 405,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "_msgSender",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 397,
"nodeType": "ParameterList",
"parameters": [],
"src": "807:2:2"
},
"returnParameters": {
"id": 400,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 399,
"name": "",
"nodeType": "VariableDeclaration",
"scope": 405,
"src": "833:15:2",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
},
"typeName": {
"id": 398,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "833:15:2",
"stateMutability": "payable",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"value": null,
"visibility": "internal"
}
],
"src": "832:17:2"
},
"scope": 417,
"src": "788:96:2",
"stateMutability": "view",
"superFunction": null,
"visibility": "internal"
},
{
"body": {
"id": 415,
"nodeType": "Block",
"src": "947:165:2",
"statements": [
{
"expression": {
"argumentTypes": null,
"id": 410,
"name": "this",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1107,
"src": "957:4:2",
"typeDescriptions": {
"typeIdentifier": "t_contract$_Context_$417",
"typeString": "contract Context"
}
},
"id": 411,
"nodeType": "ExpressionStatement",
"src": "957:4:2"
},
{
"expression": {
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 412,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1093,
"src": "1097:3:2",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 413,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "data",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "1097:8:2",
"typeDescriptions": {
"typeIdentifier": "t_bytes_calldata_ptr",
"typeString": "bytes calldata"
}
},
"functionReturnParameters": 409,
"id": 414,
"nodeType": "Return",
"src": "1090:15:2"
}
]
},
"documentation": null,
"id": 416,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "_msgData",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 406,
"nodeType": "ParameterList",
"parameters": [],
"src": "907:2:2"
},
"returnParameters": {
"id": 409,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 408,
"name": "",
"nodeType": "VariableDeclaration",
"scope": 416,
"src": "933:12:2",
"stateVariable": false,
"storageLocation": "memory",
"typeDescriptions": {
"typeIdentifier": "t_bytes_memory_ptr",
"typeString": "bytes"
},
"typeName": {
"id": 407,
"name": "bytes",
"nodeType": "ElementaryTypeName",
"src": "933:5:2",
"typeDescriptions": {
"typeIdentifier": "t_bytes_storage_ptr",
"typeString": "bytes"
}
},
"value": null,
"visibility": "internal"
}
],
"src": "932:14:2"
},
"scope": 417,
"src": "890:222:2",
"stateMutability": "view",
"superFunction": null,
"visibility": "internal"
}
],
"scope": 418,
"src": "525:589:2"
}
],
"src": "0:1115:2"
},
"compiler": {
"name": "solc",
"version": "0.5.12+commit.7709ece9.Emscripten.clang"
},
"networks": {},
"schemaVersion": "3.0.19",
"updatedAt": "2020-02-18T05:14:13.973Z",
"devdoc": {
"methods": {}
},
"userdoc": {
"methods": {}
}
}

9146
build/contracts/DECA.json Normal file

File diff suppressed because one or more lines are too long

11382
build/contracts/ERC20.json Normal file

File diff suppressed because one or more lines are too long

1906
build/contracts/IERC20.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

8709
build/contracts/Ownable.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

169
contracts/DECA.sol Normal file
View File

@ -0,0 +1,169 @@
pragma solidity 0.5.12;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
// ----------------------------------------------------------------------------
// 'DECA' DEcentralized CArbon tokens - ITDE (initial token distribution event)
//
// Deployed to : ------
// Network : Ropsten
// Symbol : DECA
// Name : DEcentralized CArbon tokens
// Total supply: Gazillion
// Decimals : 18
//
// Designed and wrote by D. Perez Negron <david@neetsec.com> A.K.A p1r0
// Test and Migrations to truffle by vitaliykuzmich
// ----------------------------------------------------------------------------
/**
* @dev The reason using this instead of openzeppelin, because owner are not 'payable'
*/
contract Ownable is Context {
address payable private _owner;
using SafeMath for uint256;
string public _CCDBAddress;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
_owner = _msgSender();
emit OwnershipTransferred(address(0), _owner);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address payable) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address payable newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address payable newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
/**
*Function that updates the official orbitDB address for carbon credits.
*Can Only be updated by the current owner
*/
function updateCCDBAddress(string memory newCCDBAddress) public onlyOwner {
_CCDBAddress = newCCDBAddress;
}
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
contract DECA is ERC20, Ownable {
using SafeMath for uint256;
string constant public symbol = "DECA";
string constant public name = "DEcentralized CArbon tokens";
uint8 constant public decimals = 18;
//for testing change weeks for hours...
uint public preICOEnds = now + 1 weeks;
uint public bonus1Ends = now + 3 weeks;
uint public bonus2Ends = now + 6 weeks;
uint public endDate = now + 11 weeks;
bool private _pause = false;
modifier notPaused() {
require(!_pause, "crowdsale on pause");
_;
}
function getPause() view public returns (bool){
return _pause;
}
function setPause(bool p) external onlyOwner {
_pause = p;
}
// ------------------------------------------------------------------------
// 100 DECA Tokens per 1 ETH
// ------------------------------------------------------------------------
function() notPaused external payable {
require(now <= endDate);
uint tokens;
uint toOwner;
uint toSender;
uint divBy;
divBy = 40;
//2.5% extra printed to be 2% of the marketcap, please see README.md
if (now <= preICOEnds) {
tokens = msg.value * 300;
} else if (now > preICOEnds && now <= bonus1Ends) {
tokens = msg.value * 275;
} else if (now > bonus1Ends && now <= bonus2Ends) {
tokens = msg.value * 250;
} else {
tokens = msg.value * 225;
}
toOwner = tokens.div(divBy);
//created 2.5% extra to the contract owner to approach 2% total marketcap
toSender = tokens;
//tokens that goes to the sender
_mint(owner(), toOwner);
_mint(msg.sender, toSender);
}
//Close down the ICO and claim the Ether.
function getETH() public onlyOwner {
require(now >= endDate);
// transfer the ETH balance in the contract to the owner
owner().transfer(address(this).balance);
}
// ------------------------------------------------------------------------
// Owner can transfer out any accidentally sent ERC20 tokens
// ------------------------------------------------------------------------
function transferAnyERC20Token(address payable tokenAddress, uint tokens) public onlyOwner returns (bool success) {
return IERC20(tokenAddress).transfer(owner(), tokens);
}
}

24
contracts/Migrations.sol Normal file
View File

@ -0,0 +1,24 @@
pragma solidity 0.5.12;
//pragma solidity 0.5.16;
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);
}
}

View File

@ -0,0 +1,6 @@
const Migrations = artifacts.require("Migrations");
module.exports = function (deployer) {
deployer.deploy(Migrations);
};

View File

@ -0,0 +1,8 @@
const DECA = artifacts.require("DECA");
module.exports = function (deployer) {
module.exports = function (deployer) {
deployer.deploy(DECA, {
gas: 6712390
});
};
};

23
package.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "carbon-token",
"version": "1.2.0",
"description": "",
"main": "truffle-config.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@openzeppelin/contracts": "^2.4.0",
"truffle": "^5.1.3"
},
"devDependencies": {
"web3": "^1.2.4"
}
}

81
run-rpc.sh Executable file
View File

@ -0,0 +1,81 @@
#!/bin/bash
# We define 10 accounts with balance 1M ether, needed for high-value tests.
accounts=(
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501202,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501203,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501204,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501205,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501206,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501207,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501208,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501209,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501210,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501211,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501212,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501213,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501214,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501215,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501216,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501217,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501218,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501219,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501220,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501221,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501222,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501223,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501224,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501225,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501226,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501227,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501228,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501229,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501230,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501231,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501232,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501233,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501234,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501235,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501236,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501237,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501238,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501239,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501230,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501240,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501241,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501242,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501243,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501244,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501245,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501246,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501247,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501248,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501249,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501250,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501251,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501252,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501253,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501254,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501255,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501256,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501257,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501258,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501259,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501350,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501351,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501352,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501353,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501354,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501355,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501356,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501357,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501358,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
--account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501359,999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
)
/usr/local/bin/ganache-cli "${accounts[@]}" --gasPrice 1

265
test/DECA.js Normal file
View File

@ -0,0 +1,265 @@
const DECA = artifacts.require('./DECA.sol')
// fix legacy web3 bugs
web3.toAsciiOriginal = web3.toAscii;
web3.toAscii = function (input) {
return web3.toAsciiOriginal(input).replace(/\u0000/g, '')
}
let accCounter = 0;
function increaseTime(duration) {
const id = Date.now()
return new Promise((resolve, reject) => {
web3.currentProvider.send({
jsonrpc: '2.0',
method: 'evm_increaseTime',
params: [duration],
id: id,
}, err1 => {
if (err1) return reject(err1)
web3.currentProvider.send({
jsonrpc: '2.0',
method: 'evm_mine',
id: id + 1,
}, (err2, res) => {
return err2 ? reject(err2) : resolve(res)
})
})
})
}
function latestTime() {
return web3.eth.getBlock('latest').timestamp;
}
//bypass testrpc bug
async function getHighBalance() {
var accounts = await web3.eth.getAccounts();
var acc = accounts[accCounter];
console.dir(acc)
var b = await web3.eth.getBalance(acc);
console.dir(b)
let high = {
"address": acc,
"balance": b
}
accCounter++;
return high;
}
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)
}
};
contract('DECA', function (accs) {
beforeEach(async function () {
this.creator = await getHighBalance();
this.deca = await DECA.new({
from: this.creator.address,
gas: 6712390
})
}),
describe('check pause', function () {
it('should get/set pause', async function () {
let p = await this.deca.getPause.call();
assert.equal(false, p, "pause should be disabled")
await this.deca.setPause(true, {from: this.creator.address, gas: 6712390})
p = await this.deca.getPause.call();
assert.equal(true, p, "pause should be enabled")
})
it('should fail on pay', async function () {
await this.deca.setPause(true, {from: this.creator.address, gas: 6712390})
let wasErr = false;
try {
let rs = await web3.eth.sendTransaction({
from: this.creator.address,
to: this.deca.address,
value: 225,
gas: 6712390
});
} catch (err) {
wasErr = true;
}
await this.deca.setPause(false, {from: this.creator.address, gas: 6712390})
wasErr = false;
try {
let rs = await web3.eth.sendTransaction({
from: this.creator.address,
to: this.deca.address,
value: 225,
gas: 6712390
});
} catch (err) {
wasErr = true;
}
assert.equal(false, wasErr, "pause should work")
})
it('check intruder pause', async function () {
var sender = await getHighBalance();
await increaseTime(duration.days(1))
await web3.eth.sendTransaction({
from: sender.address,
to: this.deca.address,
value: 1,
gas: 6712390
});
let wasErr = false;
try {
await this.deca.setPause(true, {from: sender.address, gas: 6712390})
} catch (err) {
wasErr = true;
}
assert.equal(true, wasErr, "only owner could pause")
let own = await this.deca.owner();
assert.equal(this.creator.address, own, "owner does not match")
})
})
describe('check crowdsale dates', function () {
it('check preICOEnds', async function () {
var sender = await getHighBalance();
await increaseTime(duration.days(1))
await web3.eth.sendTransaction({
from: sender.address,
to: this.deca.address,
value: 1,
gas: 6712390
});
let bonus2Ends = await this.deca.balanceOf.call(sender.address)
assert.equal(bonus2Ends.toString(10), '300', "preICOEnds wrong token balance")
})
it('check bonus1Ends', async function () {
var sender = await getHighBalance();
await increaseTime(duration.days(7) + duration.hours(1))
await web3.eth.sendTransaction({
from: sender.address,
to: this.deca.address,
value: 1,
gas: 6712390
});
let bonus2Ends = await this.deca.balanceOf.call(sender.address)
assert.equal(bonus2Ends.toString(10), '275', "bonus1Ends wrong token balance")
})
it('check bonus2Ends', async function () {
var sender = await getHighBalance();
await increaseTime(duration.weeks(3) + duration.hours(1))
await web3.eth.sendTransaction({
from: sender.address,
to: this.deca.address,
value: 1,
gas: 6712390
});
let bonus2Ends = await this.deca.balanceOf.call(sender.address)
assert.equal(bonus2Ends.toString(10), '250', "bonus2Ends wrong token balance")
})
it('check endDate', async function () {
await increaseTime(duration.weeks(11) + duration.hours(1))
let wasErr = false;
try {
let rs = await web3.eth.sendTransaction({
from: this.creator.address,
to: this.deca.address,
value: 225,
gas: 6712390
});
} catch (err) {
wasErr = true;
}
assert.equal(true, wasErr, "crowdsale should be stopped")
})
})
describe('transferAnyERC20Token', async function () {
it('check transfer from external', async function () {
var sender = await getHighBalance();
await web3.eth.sendTransaction({
from: sender.address,
to: this.deca.address,
value: 1,
gas: 6712390
});
let decaBalance = await this.deca.balanceOf.call(this.deca.address)
await this.deca.transfer(this.deca.address, 10, {from: sender.address, gas: 6712390})
decaBalance = await this.deca.balanceOf.call(this.deca.address)
assert.equal(decaBalance.toString(10), '10', " contract should have balance")
let wasErr = false;
try {
let ok = await this.deca.transferAnyERC20Token(this.deca.address, 10, {
from: this.creator.address,
gas: 6712390
})
assert.equal(true, ok, "transferAnyERC20Token should return positive result")
} catch (err) {
console.dir(err)
wasErr = true;
}
assert.equal(true, wasErr, "transferAnyERC20Token should proces without error")
})
})
// SOMEHOW THIS FUNCTIONS TEST WORKED IN ROPSTEN
// describe('check payout', async function () {
// it.only('check getETH', async function () {
// let decaBalance = await web3.eth.getBalance(this.deca.address);
// assert.equal(decaBalance.toString(10), '0', " wrong contract balance")
// var sender = await getHighBalance();
// await web3.eth.sendTransaction({
// from: sender.address,
// to: this.deca.address,
// value: 1000,
// gas: 6712390
// });
// decaBalance = await web3.eth.getBalance(this.deca.address);
// assert.equal(decaBalance.toString(10), '1000', " wrong contract balance")
// let senderTokenBalance = await this.deca.balanceOf.call(sender.address)
// assert.equal(senderTokenBalance.toString(10), '200000', " wrong sender balance")
// await increaseTime(duration.weeks(12));
// let wasErr = false;
// try {
// await this.deca.getETH({from: this.creator.address, gas: 6712390})
// } catch (err) {
// console.dir(err)
// wasErr = true;
// }
// assert.equal(false, wasErr, "getETH not possible to test because of bug in truffle, check status of bug: https://github.com/trufflesuite/truffle/issues/2811")
// decaBalance = await web3.eth.getBalance(this.deca.address);
// assert.equal(decaBalance.toString(10), '0', " balance of the DECA expected to be empty")
//
//
// })
// })
})

16
truffle.js Normal file
View File

@ -0,0 +1,16 @@
module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*",
gas: 6712390
},
ropsten: {
network_id: 3,
host: "localhost",
port: 8545,
gas: 2900000
}
}
};

BIN
uml/diagram.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB