What is BlockBits?
BlockBits DApp is not just another crowdfunding platform, it’s the innovation that sets the standard of what the ICO market urgently needs to become: safe investments and legitimate projects. For the first time investors can decide if they keep backing a project or take their money back.
The platform provides innovative mechanisms such as safe funding vaults and secure milestone based payments and is designed to become fully independent, maintained and governed by its token holders. Blockbits is launched through the very code submitted here as MVP.
Welcome to the smart company of the future! Never tired, no bias just code, autonomous platform distributed throughout the blockchain, mutable only with its community approval, always ready for the innovative ideas of tomorrow!
Open Source
Everything is provided under the MIT License unless stated otherwise.
/*
* @name Application Entity Contract
* @package BlockBitsIO
* @author Micky Socaci
Contains the main company Entity Contract code deployed and linked to the Gateway Interface.
*/
pragma solidity ^0.4.17;
import "./GatewayInterface.sol";
import "./Entity/Proposals.sol";
import "./Entity/Funding.sol";
import "./Entity/Meetings.sol";
import "./Entity/Milestones.sol";
import "./Entity/BountyManager.sol";
import "./Entity/TokenManager.sol";
import "./Entity/FundingManager.sol";
import "./Entity/ListingContract.sol";
import "./Entity/NewsContract.sol";
contract ApplicationEntity {
/* Source Code Url */
bytes32 sourceCodeUrl;
/* Entity initialised or not */
bool public _initialized = false;
/* Entity locked or not */
bool public _locked = false;
/* Current Entity State */
uint8 public CurrentEntityState;
/* Available Entity State */
mapping (bytes32 => uint8) public EntityStates;
/* GatewayInterface address */
address public GatewayInterfaceAddress;
/* Parent Entity Instance */
GatewayInterface GatewayInterfaceEntity;
/* Asset Entities */
Proposals public ProposalsEntity;
Funding public FundingEntity;
Milestones public MilestonesEntity;
Meetings public MeetingsEntity;
BountyManager public BountyManagerEntity;
TokenManager public TokenManagerEntity;
ListingContract public ListingContractEntity;
FundingManager public FundingManagerEntity;
NewsContract public NewsContractEntity;
/* Asset Collection */
mapping (bytes32 => address) public AssetCollection;
mapping (uint8 => bytes32) public AssetCollectionIdToName;
uint8 public AssetCollectionNum = 0;
event EventAppEntityReady ( address indexed _address );
event EventAppEntityCodeUpgradeProposal ( address indexed _address, bytes32 indexed _sourceCodeUrl );
event EventAppEntityInitAsset ( bytes32 indexed _name, address indexed _address );
event EventAppEntityInitAssetsToThis ( uint8 indexed _assetNum );
event EventAppEntityAssetsToNewApplication ( address indexed _address );
event EventAppEntityLocked ( address indexed _address );
address public deployerAddress;
function ApplicationEntity() public {
deployerAddress = msg.sender;
setEntityStates();
CurrentEntityState = getEntityState("NEW");
}
function setEntityStates() internal {
// ApplicationEntity States
EntityStates["__IGNORED__"] = 0;
EntityStates["NEW"] = 1;
EntityStates["WAITING"] = 2;
EntityStates["IN_FUNDING"] = 3;
EntityStates["IN_DEVELOPMENT"] = 5;
EntityStates["IN_CODE_UPGRADE"] = 50;
EntityStates["UPGRADED"] = 100;
EntityStates["IN_GLOBAL_CASHBACK"] = 150;
EntityStates["LOCKED"] = 200;
EntityStates["DEVELOPMENT_COMPLETE"] = 250;
}
function getEntityState(bytes32 name) public view returns (uint8) {
return EntityStates[name];
}
/*
* Initialize Application and it's assets
* If gateway is freshly deployed, just link
* else, create a voting proposal that needs to be accepted for the linking
*
* @param address _newAddress
* @param bytes32 _sourceCodeUrl
*
* @modifiers requireNoParent, requireNotInitialised
*/
function linkToGateway(
address _GatewayInterfaceAddress,
bytes32 _sourceCodeUrl
)
external
requireNoParent
requireNotInitialised
onlyDeployer
{
GatewayInterfaceAddress = _GatewayInterfaceAddress;
sourceCodeUrl = _sourceCodeUrl;
// init gateway entity and set app address
GatewayInterfaceEntity = GatewayInterface(GatewayInterfaceAddress);
GatewayInterfaceEntity.requestCodeUpgrade( address(this), sourceCodeUrl );
}
function setUpgradeState(uint8 state) public onlyGatewayInterface {
CurrentEntityState = state;
}
/*
For the sake of simplicity, and solidity warnings about "unknown gas usage" do this.. instead of sending
an array of addresses
*/
function addAssetProposals(address _assetAddresses) external requireNotInitialised onlyDeployer {
ProposalsEntity = Proposals(_assetAddresses);
assetInitialized("Proposals", _assetAddresses);
}
function addAssetFunding(address _assetAddresses) external requireNotInitialised onlyDeployer {
FundingEntity = Funding(_assetAddresses);
assetInitialized("Funding", _assetAddresses);
}
function addAssetMilestones(address _assetAddresses) external requireNotInitialised onlyDeployer {
MilestonesEntity = Milestones(_assetAddresses);
assetInitialized("Milestones", _assetAddresses);
}
function addAssetMeetings(address _assetAddresses) external requireNotInitialised onlyDeployer {
MeetingsEntity = Meetings(_assetAddresses);
assetInitialized("Meetings", _assetAddresses);
}
function addAssetBountyManager(address _assetAddresses) external requireNotInitialised onlyDeployer {
BountyManagerEntity = BountyManager(_assetAddresses);
assetInitialized("BountyManager", _assetAddresses);
}
function addAssetTokenManager(address _assetAddresses) external requireNotInitialised onlyDeployer {
TokenManagerEntity = TokenManager(_assetAddresses);
assetInitialized("TokenManager", _assetAddresses);
}
function addAssetFundingManager(address _assetAddresses) external requireNotInitialised onlyDeployer {
FundingManagerEntity = FundingManager(_assetAddresses);
assetInitialized("FundingManager", _assetAddresses);
}
function addAssetListingContract(address _assetAddresses) external requireNotInitialised onlyDeployer {
ListingContractEntity = ListingContract(_assetAddresses);
assetInitialized("ListingContract", _assetAddresses);
}
function addAssetNewsContract(address _assetAddresses) external requireNotInitialised onlyDeployer {
NewsContractEntity = NewsContract(_assetAddresses);
assetInitialized("NewsContract", _assetAddresses);
}
function assetInitialized(bytes32 name, address _assetAddresses) internal {
if(AssetCollection[name] == 0x0) {
AssetCollectionIdToName[AssetCollectionNum] = name;
AssetCollection[name] = _assetAddresses;
AssetCollectionNum++;
} else {
// just replace
AssetCollection[name] = _assetAddresses;
}
EventAppEntityInitAsset(name, _assetAddresses);
}
function getAssetAddressByName(bytes32 _name) public view returns (address) {
return AssetCollection[_name];
}
/* Application Bylaws mapping */
mapping (bytes32 => uint256) public BylawsUint256;
mapping (bytes32 => bytes32) public BylawsBytes32;
function setBylawUint256(bytes32 name, uint256 value) public requireNotInitialised onlyDeployer {
BylawsUint256[name] = value;
}
function getBylawUint256(bytes32 name) public view requireInitialised returns (uint256) {
return BylawsUint256[name];
}
function setBylawBytes32(bytes32 name, bytes32 value) public requireNotInitialised onlyDeployer {
BylawsBytes32[name] = value;
}
function getBylawBytes32(bytes32 name) public view requireInitialised returns (bytes32) {
return BylawsBytes32[name];
}
function initialize() external requireNotInitialised onlyGatewayInterface returns (bool) {
_initialized = true;
EventAppEntityReady( address(this) );
return true;
}
function getParentAddress() external view returns(address) {
return GatewayInterfaceAddress;
}
function createCodeUpgradeProposal(
address _newAddress,
bytes32 _sourceCodeUrl
)
external
requireInitialised
onlyGatewayInterface
returns (uint256)
{
// proposals create new.. code upgrade proposal
EventAppEntityCodeUpgradeProposal ( _newAddress, _sourceCodeUrl );
// return true;
return ProposalsEntity.addCodeUpgradeProposal(_newAddress, _sourceCodeUrl);
}
/*
* Only a proposal can update the ApplicationEntity Contract address
*
* @param address _newAddress
* @modifiers onlyProposalsAsset
*/
function acceptCodeUpgradeProposal(address _newAddress) external onlyProposalsAsset {
GatewayInterfaceEntity.approveCodeUpgrade( _newAddress );
}
function initializeAssetsToThisApplication() external onlyGatewayInterface returns (bool) {
for(uint8 i = 0; i < AssetCollectionNum; i++ ) {
bytes32 _name = AssetCollectionIdToName[i];
address current = AssetCollection[_name];
if(current != address(0x0)) {
if(!current.call(bytes4(keccak256("setInitialOwnerAndName(bytes32)")), _name) ) {
revert();
}
} else {
revert();
}
}
EventAppEntityInitAssetsToThis( AssetCollectionNum );
return true;
}
function transferAssetsToNewApplication(address _newAddress) external onlyGatewayInterface returns (bool){
for(uint8 i = 0; i < AssetCollectionNum; i++ ) {
bytes32 _name = AssetCollectionIdToName[i];
address current = AssetCollection[_name];
if(current != address(0x0)) {
if(!current.call(bytes4(keccak256("transferToNewOwner(address)")), _newAddress) ) {
revert();
}
} else {
revert();
}
}
EventAppEntityAssetsToNewApplication ( _newAddress );
return true;
}
/*
* Only the gateway interface can lock current app after a successful code upgrade proposal
*
* @modifiers onlyGatewayInterface
*/
function lock() external onlyGatewayInterface returns (bool) {
_locked = true;
CurrentEntityState = getEntityState("UPGRADED");
EventAppEntityLocked(address(this));
return true;
}
/*
DUMMY METHOD, to be replaced in a future Code Upgrade with a check to determine if sender should be able to initiate a code upgrade
specifically used after milestone development completes
*/
address testAddressAllowUpgradeFrom;
function canInitiateCodeUpgrade(address _sender) public view returns(bool) {
// suppress warning
if(testAddressAllowUpgradeFrom != 0x0 && testAddressAllowUpgradeFrom == _sender) {
return true;
}
return false;
}
/*
* Throws if called by any other entity except GatewayInterface
*/
modifier onlyGatewayInterface() {
require(GatewayInterfaceAddress != address(0) && msg.sender == GatewayInterfaceAddress);
_;
}
/*
* Throws if called by any other entity except Proposals Asset Contract
*/
modifier onlyProposalsAsset() {
require(msg.sender == address(ProposalsEntity));
_;
}
modifier requireNoParent() {
require(GatewayInterfaceAddress == address(0x0));
_;
}
modifier requireNotInitialised() {
require(_initialized == false && _locked == false);
_;
}
modifier requireInitialised() {
require(_initialized == true && _locked == false);
_;
}
modifier onlyDeployer() {
require(msg.sender == deployerAddress);
_;
}
event DebugApplicationRequiredChanges( uint8 indexed _current, uint8 indexed _required );
event EventApplicationEntityProcessor(uint8 indexed _current, uint8 indexed _required);
function doStateChanges() public {
if(!_locked) {
// process assets first so we can initialize them from NEW to WAITING
AssetProcessor();
var (returnedCurrentEntityState, EntityStateRequired) = getRequiredStateChanges();
bool callAgain = false;
DebugApplicationRequiredChanges( returnedCurrentEntityState, EntityStateRequired );
if(EntityStateRequired != getEntityState("__IGNORED__") ) {
EntityProcessor(EntityStateRequired);
callAgain = true;
}
} else {
revert();
}
}
function hasRequiredStateChanges() public view returns (bool) {
bool hasChanges = false;
if(!_locked) {
var (returnedCurrentEntityState, EntityStateRequired) = getRequiredStateChanges();
// suppress unused local variable warning
returnedCurrentEntityState = 0;
if(EntityStateRequired != getEntityState("__IGNORED__") ) {
hasChanges = true;
}
if(anyAssetHasChanges()) {
hasChanges = true;
}
}
return hasChanges;
}
function anyAssetHasChanges() public view returns (bool) {
if( FundingEntity.hasRequiredStateChanges() ) {
return true;
}
if( FundingManagerEntity.hasRequiredStateChanges() ) {
return true;
}
if( MilestonesEntity.hasRequiredStateChanges() ) {
return true;
}
if( ProposalsEntity.hasRequiredStateChanges() ) {
return true;
}
return extendedAnyAssetHasChanges();
}
// use this when extending "has changes"
function extendedAnyAssetHasChanges() internal view returns (bool) {
if(_initialized) {}
return false;
}
// use this when extending "asset state processor"
function extendedAssetProcessor() internal {
// does not exist, but we check anyway to bypass compier warning about function state mutability
if ( CurrentEntityState == 255 ) {
ProposalsEntity.process();
}
}
// view methods decide if changes are to be made
// in case of tasks, we do them in the Processors.
function AssetProcessor() internal {
if ( CurrentEntityState == getEntityState("NEW") ) {
// move all assets that have states to "WAITING"
if(FundingEntity.hasRequiredStateChanges()) {
FundingEntity.doStateChanges();
}
if(FundingManagerEntity.hasRequiredStateChanges()) {
FundingManagerEntity.doStateChanges();
}
if( MilestonesEntity.hasRequiredStateChanges() ) {
MilestonesEntity.doStateChanges();
}
} else if ( CurrentEntityState == getEntityState("WAITING") ) {
if( FundingEntity.hasRequiredStateChanges() ) {
FundingEntity.doStateChanges();
}
}
else if ( CurrentEntityState == getEntityState("IN_FUNDING") ) {
if( FundingEntity.hasRequiredStateChanges() ) {
FundingEntity.doStateChanges();
}
if( FundingManagerEntity.hasRequiredStateChanges() ) {
FundingManagerEntity.doStateChanges();
}
}
else if ( CurrentEntityState == getEntityState("IN_DEVELOPMENT") ) {
if( FundingManagerEntity.hasRequiredStateChanges() ) {
FundingManagerEntity.doStateChanges();
}
if(MilestonesEntity.hasRequiredStateChanges()) {
MilestonesEntity.doStateChanges();
}
if(ProposalsEntity.hasRequiredStateChanges()) {
ProposalsEntity.process();
}
}
else if ( CurrentEntityState == getEntityState("DEVELOPMENT_COMPLETE") ) {
if(ProposalsEntity.hasRequiredStateChanges()) {
ProposalsEntity.process();
}
}
extendedAssetProcessor();
}
function EntityProcessor(uint8 EntityStateRequired) internal {
EventApplicationEntityProcessor( CurrentEntityState, EntityStateRequired );
// Update our Entity State
CurrentEntityState = EntityStateRequired;
// Do State Specific Updates
if ( EntityStateRequired == getEntityState("IN_FUNDING") ) {
// run Funding state changer
// doStateChanges
}
}
/*
* Method: Get Entity Required State Changes
*
* @access public
* @type method
*
* @return ( uint8 CurrentEntityState, uint8 EntityStateRequired )
*/
function getRequiredStateChanges() public view returns (uint8, uint8) {
uint8 EntityStateRequired = getEntityState("__IGNORED__");
if( CurrentEntityState == getEntityState("NEW") ) {
// general so we know we initialized
EntityStateRequired = getEntityState("WAITING");
} else if ( CurrentEntityState == getEntityState("WAITING") ) {
// Funding Started
if( FundingEntity.CurrentEntityState() == FundingEntity.getEntityState("IN_PROGRESS") ) {
EntityStateRequired = getEntityState("IN_FUNDING");
}
} else if ( CurrentEntityState == getEntityState("IN_FUNDING") ) {
if(FundingEntity.CurrentEntityState() == FundingEntity.getEntityState("SUCCESSFUL_FINAL")) {
// SUCCESSFUL_FINAL means FUNDING was successful, and FundingManager has finished distributing tokens and ether
EntityStateRequired = getEntityState("IN_DEVELOPMENT");
} else if(FundingEntity.CurrentEntityState() == FundingEntity.getEntityState("FAILED_FINAL")) {
// Funding failed..
EntityStateRequired = getEntityState("IN_GLOBAL_CASHBACK");
}
} else if ( CurrentEntityState == getEntityState("IN_DEVELOPMENT") ) {
if(MilestonesEntity.CurrentEntityState() == MilestonesEntity.getEntityState("DEVELOPMENT_COMPLETE")) {
// check if we finished developing all milestones .. and if so move state to complete.
EntityStateRequired = getEntityState("DEVELOPMENT_COMPLETE");
}
if(MilestonesEntity.CurrentEntityState() == MilestonesEntity.getEntityState("DEADLINE_MEETING_TIME_FAILED")) {
EntityStateRequired = getEntityState("IN_GLOBAL_CASHBACK");
}
}
return (CurrentEntityState, EntityStateRequired);
}
function getTimestamp() view public returns (uint256) {
return now;
}
Compiling ./contracts/Algorithms/TokenSCADAGeneric.sol...
Compiling ./contracts/ApplicationAsset.sol...
Compiling ./contracts/ApplicationEntity.sol...
Compiling ./contracts/ApplicationEntityABI.sol...
Compiling ./contracts/ApplicationEntitySecond.sol...
Compiling ./contracts/Entity/BountyManager.sol...
Compiling ./contracts/Entity/Funding.sol...
Compiling ./contracts/Entity/FundingManager.sol...
Compiling ./contracts/Entity/FundingVault.sol...
Compiling ./contracts/Entity/ListingContract.sol...
Compiling ./contracts/Entity/Meetings.sol...
Compiling ./contracts/Entity/Milestones.sol...
Compiling ./contracts/Entity/NewsContract.sol...
Compiling ./contracts/Entity/Proposals.sol...
Compiling ./contracts/Entity/Token.sol...
Compiling ./contracts/Entity/TokenManager.sol...
Compiling ./contracts/Entity/UpgradeTestAsset.sol...
Compiling ./contracts/GatewayInterface.sol...
Compiling ./contracts/Inputs/FundingInputDirect.sol...
Compiling ./contracts/Inputs/FundingInputGeneral.sol...
Compiling ./contracts/Inputs/FundingInputMilestone.sol...
Compiling ./contracts/zeppelin/math/SafeMath.sol...
Compiling ./contracts/zeppelin/token/BasicToken.sol...
Compiling ./contracts/zeppelin/token/ERC20.sol...
Compiling ./contracts/zeppelin/token/ERC20Basic.sol...
Compiling ./contracts/zeppelin/token/StandardToken.sol...
Compiling ./test/helpers/ExecutionTarget.sol...
Compiling ./test/helpers/SolidityAccountUtils.sol...
Compiling ./test/mocks/EmptyStub.sol...
Compiling ./test/mocks/GenericCaller.sol...
Compiling ./test/mocks/SafeMathMock.sol...
Compiling ./test/mocks/SampleRecipientSuccess.sol...
Compiling ./test/mocks/SampleRecipientThrow.sol...
Compiling ./test/mocks/TestApplicationAsset.sol...
Compiling ./test/mocks/TestApplicationEntity.sol...
Compiling ./test/mocks/TestApplicationEntityABI.sol...
Compiling ./test/mocks/TestApplicationEntityBad.sol...
Compiling ./test/mocks/TestApplicationEntitySecond.sol...
Compiling ./test/mocks/TestBountyManager.sol...
Compiling ./test/mocks/TestERC20Caller.sol...
Compiling ./test/mocks/TestFunding.sol...
Compiling ./test/mocks/TestFundingInputMock.sol...
Compiling ./test/mocks/TestFundingManager.sol...
Compiling ./test/mocks/TestFundingVault.sol...
Compiling ./test/mocks/TestGatewayInterface.sol...
Compiling ./test/mocks/TestListingContract.sol...
Compiling ./test/mocks/TestMeetings.sol...
Compiling ./test/mocks/TestMilestones.sol...
Compiling ./test/mocks/TestNewsContract.sol...
Compiling ./test/mocks/TestProposals.sol...
Compiling ./test/mocks/TestToken.sol...
Compiling ./test/mocks/TestTokenManager.sol...
Compiling ./test/mocks/TestTokenSCADA1Market.sol...
Compiling ./test/mocks/TestUpgradeTestAsset.sol..
---------------------------------------------------------------- Running test collections [28]. ---------------------------------------------------------------- Contract: SafeMath ✓ multiplies correctly (68ms) ✓ adds correctly (46ms) ✓ subtracts correctly (45ms) ✓ should throw an error if subtraction result would be negative ✓ should throw an error on addition overflow ✓ should throw an error on multiplication overflow Contract: ERC20 Token ✓ creation: in contract settings should match constructor parameters (175ms) ✓ creation: should create a correct initial balance for the creator ✓ creation: test correct setting of vanity information (89ms) ✓ creation: should succeed in creating over 2^256 - 1 (max) tokens (76ms) ✓ transfers: ether transfer should be reversed. ✓ transfers: should transfer 10000 to accounts[1] with accounts[0] having 10000 (46ms) ✓ transfers: should fail when trying to transfer total amount +1 to accounts[1] with accounts[0] having total amount (56ms) ✓ transfers: should handle zero-transfers normally (46ms) ✓ transfers: should throw if receiver address is 0x0 ✓ transferFrom: should throw if receiver address is 0x0 (44ms) ✓ approvals: msg.sender should approve 100 to accounts[1] (50ms) ✓ approvals: msg.sender approves accounts[1] of 100 & withdraws 20 once. (214ms) ✓ approvals: msg.sender approves accounts[1] of 100 & withdraws 20 twice. (207ms) ✓ approvals: msg.sender approves accounts[1] of 100 & withdraws 50 & 60 (2nd tx should fail) (202ms) ✓ approvals: attempt withdrawal from account with no allowance (should fail) (45ms) ✓ approvals: allow accounts[1] 100 to withdraw from accounts[0]. Withdraw 60 and then approve 0 & attempt transfer. (69ms) ✓ approvals: approve max (2^256 - 1) (44ms) ✓ approvals: msg.sender approves accounts[1] of max (2^256 - 1) & withdraws 20 (147ms) ✓ allowance: should start with zero ✓ allowance: should increase by 50 then decrease by 10 (100ms) ✓ allowance: should be set to zero if decrease value is higher than existing (61ms) ✓ events: should fire Transfer event properly ✓ events: should fire Transfer event normally on a zero transfer ✓ events: should fire Approval event properly Contract: Gateway Interface ✓ initializes with empty properties requestCodeUpgrade() ✓ throws if address is empty ( 0x0 ) ✓ throws if calling object misses the initialize() method ✓ throws if current Application cannot initialize Assets properly (73ms) ✓ links Application if valid (57ms) ✓ creates "Upgrade Proposal" if a previous Application is already linked (325ms) approveCodeUpgrade() ✓ throws if sender is not current Application ✓ works if sender is current Application (254ms) ✓ throws if current Application cannot transfer assets to new application (191ms) ✓ throws if current Application cannot initialize new application (322ms) ✓ throws if current Application cannot lock itself after transferring assets (308ms) misc for extra coverage ✓ getNewsContractAddress returns actual linked NewsContract Asset address ✓ getListingContractAddress returns actual linked ListingContract Asset address Contract: Application Assets setInitialOwnerAndName() ✓ works if linking an asset for the first time (63ms) ✓ throws if already owned applyAndLockSettings() ✓ works if called by deployer account and asset is not locked already (65ms) ✓ throws if called before initialization ✓ throws if called when settings are already applied (49ms) ✓ throws if not called by deployer's account getApplicationAssetAddressByName() ✓ works if asset is initialized and owned by an application (66ms) ✓ works if asset has settings and they are applied (99ms) ✓ throws if asset name does not exist in the app's mapping (63ms) transferToNewOwner() ✓ works if current caller is owner and requested address is not 0x0 (88ms) ✓ throws if called when internal owner address is invalid ✓ throws if owned and called by other address ✓ throws if new address is 0x0 Application Bylaws in Application Asset ✓ getAppBylawBytes32 returns correct value set by project settings (47ms) ✓ getAppBylawUint256 returns correct value set by project settings (50ms) Contract: Application Entity ✓ initializes with empty properties (42ms) ✓ initializes with deployer address properly (66ms) setBylawBytes32() ✓ sets and returns a bylaw bytes32 if not initialized (141ms) ✓ throws if if application is already initialized (73ms) getBylawBytes32() ✓ throws if application is not initialized ✓ returns correct value set by setBylawBytes32 if application is initialized (83ms) setBylawUint256() ✓ sets and returns a bylaw uint256 if not initialized (132ms) ✓ throws if if application is already initialized (66ms) application bylaws validation ✓ sets and returns all string and uint256 bylaws (931ms) getBylawUint256() ✓ throws if application is not initialized ✓ returns correct value set by setBylaw if application is initialized (79ms) initialize() ✓ throws if called when already initialized (47ms) ✓ throws if called with owner missing ( gateway ) ✓ works if owner is set, and it's the one calling (57ms) initializeAssetsToThisApplication() ✓ throws if not an asset (74ms) ✓ throws if any asset has a 0x0 address (52ms) ✓ throws if caller is not gateway acceptCodeUpgradeProposal() ✓ throws if caller is not Proposals Asset (72ms) lock() ✓ throws if sender is not gateway ✓ works if sender is gateway (59ms) linkToGateway() ✓ throws if called when owner already exists ✓ throws if called when already initialized ✓ will emit EventAppEntityReady on initial linking (38ms) ✓ will emit EventNewProposalCreated if a previous ApplicationEntity is already linked (269ms) addAsset[AssetName]() ✓ throws if called when already initialized (62ms) ✓ throws if called by any other address than initial deployer (44ms) ✓ linking an asset will emit EventAppEntityInitAsset event (51ms) ✓ linking all assets will emit the same number of EventAppEntityInitAsset events (311ms) ✓ linking an asset, then linking the same asset again, will replace it in mapping (150ms) Contract: Application Entity Second initializeNewAssetToThisApplication() ✓ throws if not an asset (97ms) ✓ throws if name does not match the asset (78ms) ✓ throws if caller is not the deployer (54ms) ✓ works if caller is the deployer, and asset was already added (66ms) Contract: Gateway and Application Integration ✓ initial deployment (74ms) ✓ first linking (104ms) Application upgrades ✓ first upgrade (297ms) ✓ second upgrade (635ms) ✓ throws if an upgrade request is received from an account that does not pass validCodeUpgradeInitiator check (85ms) ✓ mock: works if an upgrade request is received and current ApplicationEntity canInitiateCodeUpgrade allows it (192ms) Contract: TokenManager Asset addTokenSettingsAndInit() ✓ properly sets up the tokens if initialized (78ms) ✓ properly sets up the Token SCADA (92ms) getTokenSCADARequiresHardCap() ✓ returns boolean value stored in SCADA Contract (69ms) Contract: ListingContract Asset setManagerAddress() ✓ throws if caller is not deployer ✓ works if caller is applicationEntity (60ms) addItem() ✓ throws if addItem caller is not applicationEntity ✓ works if caller is applicationEntity (110ms) ✓ works if caller is manager address (119ms) getNewsContractAddress() ✓ throws if the child does not actually exist ✓ throws if the child itemAddress is invalid (96ms) ✓ returns a news contract address if the child is an actual ApplicationEntity (491ms) delistChild() ✓ throws if called by any address other than Proposals Asset (39ms) ✓ works if called by proposals asset, resulting in a child with status == false (91ms) Contract: NewsContract Asset addItem() ✓ throws if called by anyone else but the deployer address ✓ works if called by deployer address (75ms) addInternalMessage() ✓ throws if called by anyone else but the Application address ✓ works if called by Application address (59ms) Contract: Funding Vault ✓ initializes with empty properties (86ms) ✓ addPayment throws if not initialized initialize() ✓ throws if called when already initialized ✓ works if settings are correct and has not been initialized before (125ms) addPayment() ✓ FUNDING_DIRECT_METHOD - works with correct settings and caller (155ms) ✓ FUNDING_MILESTONE_METHOD - works with correct settings and caller (156ms) ✓ throws if msg.value is missing ✓ throws if payment method does not exist ✓ throws if called by other address than manager (funding contract) ✓ handles multiple payments, irregardless of funding method provided (62ms) Contract: Bounty Manager ✓ token balance matches bylaws Before Funding ended ✓ throws if sendBounty is called (60ms) After Funding ended ✓ throws if sendBounty is called by anyone else but deployer (55ms) ✓ throws if sendBounty amount is higher than remaining value (45ms) ✓ works if sendBounty is called by deployer and value is lower than remaining (43ms) Contract: Funding Asset ✓ deploys with no Funding Stages ✓ deploys with no multiSigOutputAddress ✓ deploys with no Funding Inputs (91ms) ✓ has Funding Inputs once initialized (41ms) addSettings() ✓ throws if called when settings are locked (54ms) ✓ throws if global soft cap is greater than global hard cap ✓ properly sets up the funding settings (87ms) first funding stage ✓ successfully creates a funding stage with proper settings (54ms) ✓ throws if end time is before or equal to start time ✓ throws if token selling percentage is higher than 100% SCADA Disallows Record Hard Cap, Requires Globals ✓ throws if soft cap exists (44ms) ✓ throws if hard cap exists ✓ works if hard cap and soft cap is 0 (57ms) when at least 1 funding stage already exists ✓ successfully creates the second funding stage with proper settings (55ms) ✓ throws if new funding stage start time overlaps existing stage ✓ throws if new funding stage + existing stage sell more than 100% of tokens funding stages added, asset initialized ✓ has correct Funding Inputs after ApplicationEntity grabs asset ownership and initializes it receivePayment() ✓ throws if called directly in the Funding contract ✓ throws if caller is not funding asset ✓ throws if _payment_method is not allowed (75ms) canAcceptPayment() ✓ returns false if CurrentEntityState is not IN_PROGRESS CurrentEntityState is IN_PROGRESS ✓ returns false if ETH value is 0 ✓ returns false if ETH value is smaller than minimum entry (316ms) ✓ returns false if any State changes are required (359ms) Funding State: IN_PROGRESS Funding Input: All ✓ has correct FundingAssetAddress ✓ throws if msg.value is missing ✓ throws if FundingAssetAddress is not set (51ms) ✓ throws if FundingAsset is not pointing to a Contract Funding Input: Direct ✓ has correct type id = 1 ↓ Direct Payment: GAS USAGE: 2481748 ✓ accepts payments using fallback () method and stores in valut's direct pool (197ms) ↓ First Direct Payment: GAS USAGE: 2481748 ↓ Second Direct Payment: GAS USAGE: 209805 ✓ accepts second payment from same investor (272ms) ✓ accepts second payment from same investor using both payment methods ( Direct & Milestone ) (280ms) Funding Input: Milestone ✓ has correct type id = 2 ↓ Milestone Payment: GAS USAGE: 2481797 ✓ accepts payments using fallback () method and stores in valut's milestone pool (198ms) Contract: Funding Asset - States ✓ starts with state as New and requires a change to WAITING if current time is before any funding stage (211ms) ✓ handles ENTITY state change from NEW to WAITING when funding does not start yet (494ms) ✓ starts with state as New and has correct Token Balance once in WAITING state (427ms) ✓ handles ENTITY state change from NEW or WAITING to IN_PROGRESS when funding time start has passed (339ms) ✓ is in IN_PROGRESS, receives payments, pre_ico time passes, should Require change to COOLDOWN (609ms) ✓ handles ENTITY state change from IN_PROGRESS to COOLDOWN when funding period time start has passed (619ms) ✓ is in COOLDOWN, ico start time passes, should Require change to IN_PROGRESS (705ms) ✓ handles ENTITY state change from COOLDOWN to IN_PROGRESS when next funding period time start has passed (795ms) ✓ is IN_PROGRESS, ico end time passes, should Require change to FUNDING_ENDED (935ms) handles ENTITY state change from IN_PROGRESS when last funding period time end has passed ✓ to FAILED when payments did not reach soft cap (1033ms) ✓ to SUCCESSFUL when payments reached soft cap (972ms) handles ENTITY state change from IN_PROGRESS when Hard Cap is Reached ✓ to SUCCESSFUL when payments reached hard cap in first funding stage (pre-ico) (1737ms) ✓ to SUCCESSFUL when payments reached hard cap in last funding stage (ico) (1597ms) FundingManager Tasks ✓ handles ENTITY state change from FAILED to FAILED_FINAL after FundingManager Task Process finished (2595ms) ✓ handles ENTITY state change from SUCCESSFUL to SUCCESSFUL_FINAL after FundingManager Task Process finished (8163ms) misc for extra coverage ✓ isFundingStageUpdateAllowed returns false if not allowed (340ms) ✓ should run doStateChanges even if no changes are required (134ms) Contract: FundingManager Asset ✓ receivePayment() throws if caller is not funding asset FundingEndedProcessVaultList() ✓ vaultNum has correct number of payments ✓ throws if Funding State is not "FUNDING_ENDED" ✓ Funding State is "FUNDING_ENDED" (2326ms) states ✓ starts with state as New and requires a change to WAITING (76ms) ✓ handles ENTITY state change from NEW to WAITING (883ms) ✓ handles ENTITY state change from NEW or WAITING to FUNDING_FAILED_DONE when funding state is FAILED (4313ms) ✓ setVaultCountPerProcess throws if value is not higher than 0 ✓ setVaultCountPerProcess properly sets value Funding ends, has payments, but does not reach Soft Cap ✓ handles ENTITY state change to FUNDING_FAILED_DONE, and processes all vaults (4071ms) Funding ends, has payments, and Soft Cap is reached ✓ handles ENTITY state change to FUNDING_SUCCESSFUL_DONE, and processes all vaults (4332ms) Contract: FundingManager Asset Successful funding - Token distribution Milestone Payments only ✓ SoftCap reached in pre-ico, 1 payment, 1 payment in pre-ico, 0 payments in ico (4917ms) ✓ SoftCap reached in ico, 1 payment, 1 account, 0 payments in pre-ico, 1 payment in ico (4151ms) ✓ SoftCap reached in pre-ico, 2 payments, 1 account, 1 payment in pre-ico, 1 payment in ico (5742ms) ✓ SoftCap reached in ico, 2 payments, 1 account, 1 payment in pre-ico, 1 payment in ico (5768ms) ✓ SoftCap reached in pre-ico, 2 payments, 2 accounts, 1 payment in pre-ico (account 1), 1 payment in ico (account 2) (5913ms) ✓ SoftCap reached in ico, 2 payments, 2 accounts, 1 payment in pre-ico (account 1), 1 payment in ico (account 2) (5989ms) Mixed Direct and Milestone Payments ✓ SoftCap reached in pre-ico, 4 payments, 2 accounts, 2 payment in pre-ico (account 1/2), 2 payment in ico (account 1/2) (6023ms) misc for extra coverage ✓ SCADA - initCacheForVariables() throws if called by other than FundingManager (3142ms) ✓ should run doStateChanges even if no changes are required (1118ms) ✓ SCADA - getTokenFraction() should run 0 if my amount is 0 (3124ms) ✓ SCADA - getUnsoldTokenFraction() should run 0 if my amount is 0 (3086ms) Contract: Milestones Asset - Settings NOT Locked ✓ starts with state as New and requires a change to WAITING if current time is before development start (230ms) addRecord() ✓ works if settings are not already locked (38ms) ✓ throws if settings are locked (167ms) Contract: Milestones Asset - Settings Locked ✓ isRecordUpdateAllowed should return false (213ms) states ✓ throws if trying to set Meeting time after it was already set. (3471ms) ✓ throws if now is @ expiry time and trying to set Meeting time at expiry time. (2284ms) ✓ handles ENTITY state change from WAITING to WAITING_MEETING_TIME when current time is after development start (2567ms) ✓ handles ENTITY state change from WAITING_MEETING_TIME to DEADLINE_MEETING_TIME_FAILED when current time is after milestone end, and meeting time was not set (3083ms) ✓ handles ENTITY state change from WAITING_MEETING_TIME to DEADLINE_MEETING_TIME_YES when current time is after milestone end, and meeting time was set (3435ms) ✓ handles ENTITY state change from DEADLINE_MEETING_TIME_YES to VOTING_IN_PROGRESS when current time is after meeting time (4653ms) Contract: Proposals Asset ✓ setVoteCountPerProcess throws if value is not higher than 0 ✓ setVoteCountPerProcess properly sets value Contract: Proposals Asset - Settings Locked ✓ Asset deploys and initialises properly proposal creation type 1 - IN_DEVELOPMENT_CODE_UPGRADE - Voting Type - Milestone ✓ throws if called by any address other than ApplicationEntity ✓ creates the proposal if called by the current ApplicationEntity (199ms) type 2 - EMERGENCY_FUND_RELEASE - Voting Type - Milestone ✓ throws if called by any address other than deployer ✓ creates the proposal if called by the current deployer (144ms) type 3 - MILESTONE_POSTPONING - Voting Type - Milestone ✓ throws if called by any address other than deployer ✓ throws if duration is not higher than min postponing bylaw ✓ throws if duration is higher than max postponing bylaw ✓ creates the proposal if called by the current deployer with correct duration (149ms) type 4 - MILESTONE_DEADLINE - Voting Type - Milestone ✓ throws if called by any address other than MilestoneAsset ✓ creates the proposal if called by the current MilestoneAsset (147ms) type 5 - PROJECT_DELISTING - Voting Type - Tokens ✓ throws if called by an address that does not hold any tokens. ( none in wallet / none in vault ) ✓ throws if child application is beyond FUNDING_STARTED state. (866ms) ✓ creates the proposal if called by a token holder, (tokens locked in vault) (153ms) ✓ creates the proposal if called by a token holder, (tokens locked in vault) (158ms) ✓ creates the proposal if called by a token holder, (tokens in wallet) (148ms) misc for extra coverage ✓ getRequiredStateChanges() ✓ hasRequiredStateChanges() ✓ process() throws if called by any other than ApplicationEntity ✓ getMyVote() ✓ getProposalState() ✓ getBylawsMilestoneMinPostponing() (51ms) ✓ getBylawsMilestoneMaxPostponing() (44ms) ✓ getVotingPower() for non existent investor (40ms) Contract: Proposals Asset - Type 1 - IN_DEVELOPMENT_CODE_UPGRADE ✓ current proposal matches IN_DEVELOPMENT_CODE_UPGRADE settings (2982ms) ✓ proposal closes as VOTING_RESULT_YES when time expires and no votes are registered (3295ms) ✓ second application has all assets added, and more. Proposal closes as VOTING_RESULT_YES, state change results in assets getting transferred. (4644ms) ✓ VOTE NO @ Milestone 3 - Proposal processed. Investor uses CashBack, validate balances, can continue with next milestones (52025ms) Contract: Proposals Asset - Type 2 - EMERGENCY_FUND_RELEASE ✓ current proposal matches EMERGENCY_FUND_RELEASE settings (135ms) ✓ throws if EMERGENCY_FUND_RELEASE proposal was already created once Proposal Created - Voting Started ✓ throws if trying to vote on a non existing proposal (38ms) ✓ throws if trying to vote on a the proposal while having no stake in it ✓ Registers a valid vote if voter has a stake in the proposal, does not close voting if stake is lower than 50% (220ms) ✓ Registers a valid vote if voter has a stake in the proposal, closes voting if stake is higher than 50% (236ms) ✓ first vote NO stake below 50%, second vote YES above 50%, closes as VOTING_RESULT_YES (370ms) ✓ first vote NO stake below 50%, second vote NO above 50%, closes as VOTING_RESULT_NO (201ms) ✓ YES Vote, Annuls and registers a new valid vote if voter already voted, has a stake in the proposal, and proposal is not closed (349ms) ✓ NO Vote, Annuls and registers a new valid vote if voter already voted, has a stake in the proposal, and proposal is not closed (329ms) ✓ While more than 1 proposal is active, properly re-indexes active proposals once one is closed (430ms) Voting Successful - Processed before voting expiry time ✓ throws if trying to vote on a the proposal that has already been finalised ✓ FundingManagerAsset state processed, releases ether to owner, tokens to investors, validates balances (3619ms) Voting Successful - Voting time expired ✓ FundingManagerAsset state processed, releases ether to owner, tokens to investors, validates balances (4437ms) Contract: Proposals Asset - Type 3 - MILESTONE_POSTPONING ✓ current proposal matches MILESTONE_POSTPONING settings (158ms) ✓ throws if MILESTONE_POSTPONING proposal was already created once Proposal Created - Voting Started ✓ throws if trying to vote on a non existing proposal ✓ throws if trying to vote on a the proposal while having no stake in it ✓ Registers a valid vote if voter has a stake in the proposal, does not close voting if stake is lower than 50% (214ms) ✓ Registers a valid vote if voter has a stake in the proposal, closes voting if stake is higher than 50% (234ms) ✓ first vote NO stake below 50%, second vote YES above 50%, closes as VOTING_RESULT_YES (375ms) ✓ first vote NO stake below 50%, second vote NO above 50%, closes as VOTING_RESULT_NO (213ms) ✓ YES Vote, Annuls and registers a new valid vote if voter already voted, has a stake in the proposal, and proposal is not closed (368ms) ✓ NO Vote, Annuls and registers a new valid vote if voter already voted, has a stake in the proposal, and proposal is not closed (338ms) ✓ While more than 1 proposal is active, properly re-indexes active proposals once one is closed (415ms) Voting Successful - Processed before voting expiry time ✓ throws if trying to vote on a the proposal that has already been finalised ✓ MilestoneAsset state processed, record time_end increased (1317ms) Voting Successful - Voting time expired ✓ MilestoneAsset state processed, record time_end increased (2606ms) Contract: Proposals Asset - Type 4 - MILESTONE_DEADLINE ✓ current proposal matches MILESTONE_DEADLINE settings (148ms) ✓ throws if MILESTONE_DEADLINE proposal was already created once Proposal Created - Voting Started ✓ throws if trying to vote on a non existing proposal ✓ throws if trying to vote on a the proposal while having no stake in it ✓ Registers a valid vote if voter has a stake in the proposal (249ms) ✓ YES Vote, Annuls and registers a new valid vote if voter already voted, has a stake in the proposal, and proposal is not closed (346ms) ✓ NO Vote, Annuls and registers a new valid vote if voter already voted, has a stake in the proposal, and proposal is not closed (337ms) ✓ While more than 1 proposal is active, properly re-indexes active proposals once one is closed (7987ms) Voting Successful - Voting time expired ✓ FundingManagerAsset state processed, releases ether to owner, tokens to investors, validates balances (6787ms) Contract: Proposals Asset - Type 5 - PROJECT_DELISTING ✓ current proposal matches PROJECT_DELISTING settings (132ms) ✓ throws if PROJECT_DELISTING proposal was already created once Proposal Created - Voting Started ✓ throws if trying to vote on a non existing proposal ✓ throws if trying to vote on a the proposal while having no stake in it ✓ Registers a valid vote if voter has a stake in the proposal, does not require state changes if stake is lower than 50% (245ms) ✓ Registers multiple votes and requires state changes if stake is higher than 50% (347ms) ✓ Registers multiple YES votes, after processing closes as VOTING_RESULT_YES (1438ms) ✓ Registers multiple NO votes, after processing closes as VOTING_RESULT_NO (1456ms) ✓ Registers multiple MIXED votes ( most YES ), some change vote, after processing closes as VOTING_RESULT_YES (1553ms) ✓ Registers multiple MIXED votes ( most NO ), some change vote, after processing closes as VOTING_RESULT_NO (1581ms) Voting Successful - Processed before voting expiry time ✓ throws if trying to vote on a the proposal that has already been finalised (1345ms) ✓ ApplicationEntity state processed, ListingContract delists project (1337ms) Voting Successful - Voting time expired ✓ ApplicationEntity state processed, ListingContract delists project (1285ms) Contract: Proposals Asset - Type 6 - AFTER_COMPLETE_CODE_UPGRADE ✓ current proposal matches AFTER_COMPLETE_CODE_UPGRADE settings (859ms) ✓ DEVELOPMENT_COMPLETE, Upgrade to second app, request upgrade to third - Proposal processed. (2453ms) Contract: Project COMPLETION ✓ Development started, processes all milestones, and after last one sets application into DEVELOPMENT_COMPLETE state, validates balances each step (44197ms) Contract: CashBack Scenario Testing Platform Funding Failed - Cashback Type 1 - Funding processed ✓ Funding Vaults allow all investors to CashBack (232ms) ✓ throws if CashBack is requested by other address than vault owner (investor) (86ms) ✓ Requesting CashBack transfers all locked ether back to the investor, validates balances and gas usage (217ms) Platform Funding Failed - Cashback Type 1 - Funding not processed ✓ Funding Vaults allow all investors to CashBack (573ms) ✓ throws if CashBack is requested by other address than vault owner (investor) (168ms) ✓ Requesting CashBack transfers all locked ether back to the investor, validates balances and gas usage (249ms) ✓ Once processed Funding Vaults do not allow CashBack (3716ms) ✓ If not processed in time, and CashBack is active, throws if trying to process (1191ms) Platform Funding Successful - Cashback Type 2 - Owner Missing in Action Cashback ✓ Funding Vaults allow all investors to CashBack (1395ms) ✓ MIA @ Milestone 1 - Requesting CashBack transfers all locked ether back to the investor, and locked tokens to platform owner, validates balances and gas usage (1403ms) ✓ MIA @ Milestone 3 - CashBack transfers all locked ether back to the investor, and locked tokens to platform owner, validates balances and gas usage (19096ms) ✓ MIA @ Milestone LAST - CashBack transfers all locked ether back to the investor, and locked tokens to platform owner, validates balances and gas usage (40726ms) Platform Funding Successful - Cashback Type 3 - Milestone Release ✓ Proposal processed. Funding Vault allows the investor to CashBack if majority voted NO and investor also voted NO (10921ms) ✓ VOTE NO @ Milestone 1 - Proposal processed. Investor uses CashBack, validate balances (1601ms) ✓ VOTE NO @ Milestone 1 - Proposal processed. Investor uses CashBack, validate balances, can continue with next milestones (48234ms) ✓ VOTE NO @ Milestone 3 - Proposal processed. Investor uses CashBack, validate balances, can continue with next milestones (48125ms) ✓ VOTE NO @ Milestone 3 - Proposal processed. Investor does not use CashBack, validate balances, can continue with next milestones (48182ms) ✓ VOTE NO @ Milestone LAST - Proposal processed. Investor uses CashBack, validate balances (41244ms) ✓ All investors VOTE NO and cashback at @ Milestone 3, Milestone releases now require 0 votes, automatically finalise as successful (42136ms) 314 passing (18m)
Features for everyone
- Decentralized open-source application
- Fair market token sale
- Democratic voting process
- Milestone driven development
- In contract revenue stream
- Trustless operations
- Risk indicators and analysis
- Auction based Token Buyback
- Token holder discounts
- Investor platform moderation
- Funding Vaults with escrow until delivery
- 3 Cash Back programs
- Project Creation Wizard
- Collaboration features
- Custom distribution algorithms
- Bounty portal & distribution tools
- Code upgrades & token holder voting
- Low fees - 1% of ETH Revenue
- Technical Documentation
- Functional Diagrams
- Deployment Strategies
- MIT Licensed Source Code
- Upgradeable Application Design
- Community provided and voted Code Upgrades
Token sale
General Settings | |
Token Symbol | BBX |
Total Supply | * See FAQ |
Accepted Currency | ETH Only |
Sale Soft Cap | 5000 ETH |
Sale Hard Cap | 35000 ETH |
1. PRE-ICO | |
Start | 4th of Feb 2018 |
End | 28th of Feb 2018 |
1 ETH | 9800 BBX |
Hard Cap | 7000 ETH |
Raised | 5.2594 ETH |
2. ICO | |
Start | 10th of March 2018 |
End | 1st of May 2018 |
1 ETH | 7000 BBX |
Hard Cap | 35000 ETH *incl PRE-ICO |
Remaining | 34658.6306 ETH |
Funding Methods
Token Release | After Funding |
Development Control | No |
Platform Control | Yes |
Minimum Entry | none |
Token Release | % After Each Milestone |
Development Control | Yes |
Platform Control | Yes |
Minimum Entry | none |
Funding And Token Distribution
Distribution
* Bounty pool tokens are released upon funding completion.
Milestone Funding Distribution | |
Milestone Name | Percentage |
Minimalistic Platform | 20% |
3rd Party Launch Functionality | 20% |
Code Upgrade Tools and Token Buyback | 10% |
Basic Risk indicators and Collaboration tools | 15% |
Advanced functionality | 15% |
Token Holder Upgrades | 10% |
Full Decentralization | 10% |
Roadmap
Documentation
- Technical Documentation
- Functional Diagrams
- Deployment Strategy and Flows
- Live Documentation
Code
- Backend Application MVP
- 300+ Unit and Integration Tests
Tools
- Bounty Portal
- Bounty Program Tools
- Mobile Applications
Offering
- Platform identity - Logo and Design
- Campaign Ofering Whitepaper
- Campaign Landing Page
Redesign
- Reverting to Standard Token Sale
- BlockBits Info Flow Diagrams
- New Explainer Video
- Explainer Articles
Start
- Announcements
- Funding Campaign Launch
- AMA interviews
- Press releases
PRE ICO
- 4th of February 2018
- 28th of February 2018
ICO
- 10th March 2018
- 1st May 2018
Allocation
- 2nd of May 2018
- Direct Funding Pool - Token unlock
- Bounty Portal Pool - Token unlock
Start
- 5th of May 2018
Platform
- Estimated Duration: 90 days
- Team expansion
- Swarm / IPFS Storage
- Platform Web Application
- Campaign Page
- Campaign Listing and filtering
- My Profile
- MainNet / TestNet Testing environments
- Deployment Tools
- Application State Processing Daemon
- Minimum required functionality in order for token holders to be able to validate and vote on proposals.
Functionality
- Estimated Duration: 180 days
- Platform Web Application
- Campaign Page improvements
- Campaign Listing and filtering improvements
- Project Creation Wizard - v1
- BlockChain Application Deployer
- Platform - Revenue Stream Storage Contract
- Mobile Application Update
- Minimum required functionality to allow 3rd party projects to launch through the platform and allow token holders to participate in funding events that include discount programs.
and Token Buyback
- Estimated Duration: 90 days
- Campaign Page
- Code Upgrade Tools with in platform code diff viewer
- Token Buyback functionality that uses funds in Revenue Stream Storage
- Minimum required functionality to allow Code Upgrades to be processed in order to enable Token Buyback for the main platform and launched children projects.
and Collaboration tools
- Estimated Duration: 90 days
- Campaign Page
- Campaign Risk indications and analysis
- Campaign listing and filtering based on risk indicators and scoring
- Project Creation Wizard - v2
- Collaboration Tools
- New Discount programs
- New Funding algorithms
- Basic Risk analysis and indicators for projects and Collaboration tools for the Creation Wizard.
functionality
- Estimated Duration: 90 days
- Project Creation Wizard - v3
- Funding Auction Bidding
- Campaign Page
- Advanced Risk indications and analysis
- Advanced functionality for project creation, risk analysis and indicators for project page details.
Upgrades
- Estimated Duration: 90 days
- Token holder initiated Code Upgrades that get paid from the Revenue Stream Storage Contract
- Allows token holders to propose upgrades and get paid for them.
Decentralization
- Estimated Duration: 90 days
- Full Decentralization Support
- ENS Ownership & ENS annual renewal payments
- Storage Ownership with renewal
- Project gets prepared for completion, where no one owns it.