mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
449 lines
19 KiB
Solidity
449 lines
19 KiB
Solidity
pragma solidity >=0.0;
|
|
|
|
import "./module.sol";
|
|
import "./announcementTypes.sol";
|
|
import "./multiOwner.sol";
|
|
|
|
import "./publisher.sol";
|
|
import "./token.sol";
|
|
import "./provider.sol";
|
|
import "./schelling.sol";
|
|
import "./premium.sol";
|
|
import "./ico.sol";
|
|
|
|
contract abstractModule {
|
|
function connectModule() external returns (bool success) {}
|
|
function disconnectModule() external returns (bool success) {}
|
|
function replaceModule(address addr) external returns (bool success) {}
|
|
function disableModule(bool forever) external returns (bool success) {}
|
|
function isActive() public view returns (bool success) {}
|
|
function replaceModuleHandler(address newHandler) external returns (bool success) {}
|
|
function transferEvent(address from, address to, uint256 value) external returns (bool success) {}
|
|
function newSchellingRoundEvent(uint256 roundID, uint256 reward) external returns (bool success) {}
|
|
}
|
|
|
|
contract moduleHandler is multiOwner, announcementTypes {
|
|
|
|
struct modules_s {
|
|
address payable addr;
|
|
bytes32 name;
|
|
bool schellingEvent;
|
|
bool transferEvent;
|
|
}
|
|
|
|
modules_s[] public modules;
|
|
address public foundationAddress;
|
|
uint256 debugModeUntil = block.number + 1000000;
|
|
|
|
|
|
constructor(address[] memory newOwners) multiOwner(newOwners) {}
|
|
function load(address payable foundation, bool forReplace, address payable Token, address payable Premium, address payable Publisher, address payable Schelling, address payable Provider) public {
|
|
/*
|
|
Loading modulest to ModuleHandler.
|
|
|
|
This module can be called only once and only by the owner, if every single module and its database are already put on the blockchain.
|
|
If forReaplace is true, than the ModuleHandler will be replaced. Before the publishing of its replace, the new contract must be already on the blockchain.
|
|
|
|
@foundation Address of foundation.
|
|
@forReplace Is it for replace or not. If not, it will be connected to the module.
|
|
@Token address of token.
|
|
@Publisher address of publisher.
|
|
@Schelling address of Schelling.
|
|
@Provider address of provider
|
|
*/
|
|
require( owners[msg.sender] );
|
|
require( modules.length == 0 );
|
|
foundationAddress = foundation;
|
|
addModule( modules_s(Token, keccak256('Token'), false, false), ! forReplace);
|
|
addModule( modules_s(Premium, keccak256('Premium'), false, false), ! forReplace);
|
|
addModule( modules_s(Publisher, keccak256('Publisher'), false, true), ! forReplace);
|
|
addModule( modules_s(Schelling, keccak256('Schelling'), false, true), ! forReplace);
|
|
addModule( modules_s(Provider, keccak256('Provider'), true, true), ! forReplace);
|
|
}
|
|
function addModule(modules_s memory input, bool call) internal {
|
|
/*
|
|
Inside function for registration of the modules in the database.
|
|
If the call is false, won't happen any direct call.
|
|
|
|
@input _Structure of module.
|
|
@call Is connect to the module or not.
|
|
*/
|
|
if ( call ) { require( abstractModule(input.addr).connectModule() ); }
|
|
(bool success, bool found, uint256 id) = getModuleIDByAddress(input.addr);
|
|
require( success && ! found );
|
|
(success, found, id) = getModuleIDByHash(input.name);
|
|
require( success && ! found );
|
|
(success, found, id) = getModuleIDByAddress(address(0x00));
|
|
require( success );
|
|
if ( ! found ) {
|
|
id = modules.length;
|
|
modules.push();
|
|
}
|
|
modules[id] = input;
|
|
}
|
|
function getModuleAddressByName(string memory name) public view returns( bool success, bool found, address addr ) {
|
|
/*
|
|
Search by name for module. The result is an Ethereum address.
|
|
|
|
@name Name of module.
|
|
@addr Address of module.
|
|
@found Is there any result.
|
|
@success Was the transaction successful or not.
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByName(name);
|
|
if ( _success && _found ) { return (true, true, modules[_id].addr); }
|
|
return (true, false, address(0x00));
|
|
}
|
|
function getModuleIDByHash(bytes32 hashOfName) public view returns( bool success, bool found, uint256 id ) {
|
|
/*
|
|
Search by hash of name in the module array. The result is an index array.
|
|
|
|
@name Name of module.
|
|
@id Index of module.
|
|
@found Was there any result or not.
|
|
*/
|
|
for ( uint256 a=0 ; a<modules.length ; a++ ) {
|
|
if ( modules[a].name == hashOfName ) {
|
|
return (true, true, a);
|
|
}
|
|
}
|
|
return (true, false, 0);
|
|
}
|
|
function getModuleIDByName(string memory name) public view returns( bool success, bool found, uint256 id ) {
|
|
/*
|
|
Search by name for module. The result is an index array.
|
|
|
|
@name Name of module.
|
|
@id Index of module.
|
|
@found Was there any result or not.
|
|
*/
|
|
bytes32 _name = keccak256(bytes(name));
|
|
for ( uint256 a=0 ; a<modules.length ; a++ ) {
|
|
if ( modules[a].name == _name ) {
|
|
return (true, true, a);
|
|
}
|
|
}
|
|
return (true, false, 0);
|
|
}
|
|
function getModuleIDByAddress(address addr) public view returns( bool success, bool found, uint256 id ) {
|
|
/*
|
|
Search by ethereum address for module. The result is an index array.
|
|
|
|
@name Name of module.
|
|
@id Index of module.
|
|
@found Was there any result or not.
|
|
*/
|
|
for ( uint256 a=0 ; a<modules.length ; a++ ) {
|
|
if ( modules[a].addr == addr ) {
|
|
return (true, true, a);
|
|
}
|
|
}
|
|
return (true, false, 0);
|
|
}
|
|
function replaceModule(string calldata name, address payable addr, bool callCallback) external returns (bool success) {
|
|
/*
|
|
Module replace, can be called only by the Publisher contract.
|
|
|
|
@name Name of module.
|
|
@addr Address of module.
|
|
@bool Was there any result or not.
|
|
@callCallback Call the replaceable module to confirm replacement or not.
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success );
|
|
if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) {
|
|
require( block.number < debugModeUntil );
|
|
if ( ! insertAndCheckDo(calcDoHash("replaceModule", keccak256(abi.encodePacked(name, addr, callCallback)))) ) {
|
|
return true;
|
|
}
|
|
}
|
|
(_success, _found, _id) = getModuleIDByName(name);
|
|
require( _success && _found );
|
|
if ( callCallback ) {
|
|
require( abstractModule(modules[_id].addr).replaceModule(addr) );
|
|
}
|
|
require( abstractModule(addr).connectModule() );
|
|
modules[_id].addr = addr;
|
|
return true;
|
|
}
|
|
|
|
function callReplaceCallback(string calldata moduleName, address newModule) external returns (bool success) {
|
|
require( block.number < debugModeUntil );
|
|
if ( ! insertAndCheckDo(calcDoHash("callReplaceCallback", keccak256(abi.encodePacked(moduleName, newModule)))) ) {
|
|
return true;
|
|
}
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByName(moduleName);
|
|
require( _success);
|
|
require( abstractModule(modules[_id].addr).replaceModule(newModule) );
|
|
return true;
|
|
}
|
|
|
|
function newModule(string calldata name, address payable addr, bool schellingEvent, bool transferEvent) external returns (bool success) {
|
|
/*
|
|
Adding new module to the database. Can be called only by the Publisher contract.
|
|
|
|
@name Name of module.
|
|
@addr Address of module.
|
|
@schellingEvent Gets it new Schelling round notification?
|
|
@transferEvent Gets it new transaction notification?
|
|
@bool Was there any result or not.
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success );
|
|
if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) {
|
|
require( block.number < debugModeUntil );
|
|
if ( ! insertAndCheckDo(calcDoHash("newModule", keccak256(abi.encodePacked(name, addr, schellingEvent, transferEvent)))) ) {
|
|
return true;
|
|
}
|
|
}
|
|
addModule( modules_s(addr, keccak256(bytes(name)), schellingEvent, transferEvent), true);
|
|
return true;
|
|
}
|
|
function dropModule(string calldata name, bool callCallback) external returns (bool success) {
|
|
/*
|
|
Deleting module from the database. Can be called only by the Publisher contract.
|
|
|
|
@name Name of module to delete.
|
|
@bool Was the function successful?
|
|
@callCallback Call the replaceable module to confirm replacement or not.
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success );
|
|
if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) {
|
|
require( block.number < debugModeUntil );
|
|
if ( ! insertAndCheckDo(calcDoHash("replaceModule", keccak256(abi.encodePacked(name, callCallback)))) ) {
|
|
return true;
|
|
}
|
|
}
|
|
(_success, _found, _id) = getModuleIDByName(name);
|
|
require( _success && _found );
|
|
if( callCallback ) {
|
|
abstractModule(modules[_id].addr).disableModule(true);
|
|
}
|
|
delete modules[_id];
|
|
return true;
|
|
}
|
|
|
|
function callDisableCallback(string calldata moduleName) external returns (bool success) {
|
|
require( block.number < debugModeUntil );
|
|
if ( ! insertAndCheckDo(calcDoHash("callDisableCallback", keccak256(bytes(moduleName)))) ) {
|
|
return true;
|
|
}
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByName(moduleName);
|
|
require( _success);
|
|
require( abstractModule(modules[_id].addr).disableModule(true) );
|
|
return true;
|
|
}
|
|
|
|
function broadcastTransfer(address from, address to, uint256 value) external returns (bool success) {
|
|
/*
|
|
Announcing transactions for the modules.
|
|
|
|
Can be called only by the token module.
|
|
Only the configured modules get notifications.( transferEvent )
|
|
|
|
@from from who.
|
|
@to to who.
|
|
@value amount.
|
|
@bool Was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success && _found && modules[_id].name == keccak256('Token') );
|
|
for ( uint256 a=0 ; a<modules.length ; a++ ) {
|
|
if ( modules[a].transferEvent && abstractModule(modules[a].addr).isActive() ) {
|
|
require( abstractModule(modules[a].addr).transferEvent(from, to, value) );
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
function broadcastSchellingRound(uint256 roundID, uint256 reward) external returns (bool success) {
|
|
/*
|
|
Announcing new Schelling round for the modules.
|
|
Can be called only by the Schelling module.
|
|
Only the configured modules get notifications( schellingEvent ).
|
|
|
|
@roundID Number of Schelling round.
|
|
@reward Coin emission in this Schelling round.
|
|
@bool Was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success && _found && modules[_id].name == keccak256('Schelling') );
|
|
for ( uint256 a=0 ; a<modules.length ; a++ ) {
|
|
if ( modules[a].schellingEvent && abstractModule(modules[a].addr).isActive() ) {
|
|
require( abstractModule(modules[a].addr).newSchellingRoundEvent(roundID, reward) );
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
function replaceModuleHandler(address newHandler) external returns (bool success) {
|
|
/*
|
|
Replacing ModuleHandler.
|
|
|
|
Can be called only by the publisher.
|
|
Every module will be informed about the ModuleHandler replacement.
|
|
|
|
@newHandler Address of the new ModuleHandler.
|
|
@bool Was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success );
|
|
if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) {
|
|
require( block.number < debugModeUntil );
|
|
if ( ! insertAndCheckDo(calcDoHash("replaceModuleHandler", keccak256(abi.encodePacked(newHandler)))) ) {
|
|
return true;
|
|
}
|
|
}
|
|
for ( uint256 a=0 ; a<modules.length ; a++ ) {
|
|
require( abstractModule(modules[a].addr).replaceModuleHandler(newHandler) );
|
|
}
|
|
return true;
|
|
}
|
|
function balanceOf(address owner) public view returns (bool success, uint256 value) {
|
|
/*
|
|
Query of token balance.
|
|
|
|
@owner address
|
|
@value balance.
|
|
@success was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByName('Token');
|
|
require( _success && _found );
|
|
return (true, token(modules[_id].addr).balanceOf(owner));
|
|
}
|
|
function totalSupply() public view returns (bool success, uint256 value) {
|
|
/*
|
|
Query of the whole token amount.
|
|
|
|
@value amount.
|
|
@success was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByName('Token');
|
|
require( _success && _found );
|
|
return (true, token(modules[_id].addr).totalSupply());
|
|
}
|
|
function isICO() public view returns (bool success, bool ico) {
|
|
/*
|
|
Query of ICO state
|
|
|
|
@ico Is ICO in progress?.
|
|
@success was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByName('Token');
|
|
require( _success && _found );
|
|
return (true, token(modules[_id].addr).isICO());
|
|
}
|
|
function getCurrentSchellingRoundID() public view returns (bool success, uint256 round) {
|
|
/*
|
|
Query of number of the actual Schelling round.
|
|
|
|
@round Schelling round.
|
|
@success was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByName('Schelling');
|
|
require( _success && _found );
|
|
return (true, schelling(modules[_id].addr).getCurrentSchellingRoundID());
|
|
}
|
|
function mint(address to, uint256 value) external returns (bool success) {
|
|
/*
|
|
Token emission request. Can be called only by the provider.
|
|
|
|
@to Place of new token
|
|
@value Token amount
|
|
|
|
@success Was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success && _found && modules[_id].name == keccak256('Provider') );
|
|
(_success, _found, _id) = getModuleIDByName('Token');
|
|
require( _success && _found );
|
|
require( token(modules[_id].addr).mint(to, value) );
|
|
return true;
|
|
}
|
|
function transfer(address from, address to, uint256 value, bool fee) external returns (bool success) {
|
|
/*
|
|
Token transaction request. Can be called only by a module.
|
|
|
|
@from from who.
|
|
@to To who.
|
|
@value Token amount.
|
|
@fee Transaction fee will be charged or not?
|
|
@success Was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success && _found );
|
|
(_success, _found, _id) = getModuleIDByName('Token');
|
|
require( _success && _found );
|
|
require( token(modules[_id].addr).transferFromByModule(from, to, value, fee) );
|
|
return true;
|
|
}
|
|
function processTransactionFee(address from, uint256 value) external returns (bool success) {
|
|
/*
|
|
Token transaction fee. Can be called only by the provider.
|
|
|
|
@from From who.
|
|
@value Token amount.
|
|
@success Was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success && _found && modules[_id].name == keccak256('Provider') );
|
|
(_success, _found, _id) = getModuleIDByName('Token');
|
|
require( _success && _found );
|
|
require( token(modules[_id].addr).processTransactionFee(from, value) );
|
|
return true;
|
|
}
|
|
function burn(address from, uint256 value) external returns (bool success) {
|
|
/*
|
|
Token burn. Can be called only by Schelling.
|
|
|
|
@from From who.
|
|
@value Token amount.
|
|
@success Was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success && _found && modules[_id].name == keccak256('Schelling') );
|
|
(_success, _found, _id) = getModuleIDByName('Token');
|
|
require( _success && _found );
|
|
require( token(modules[_id].addr).burn(from, value) );
|
|
return true;
|
|
}
|
|
function configureModule(string calldata moduleName, announcementType aType, uint256 value) external returns (bool success) {
|
|
/*
|
|
Changing configuration of a module. Can be called only by Publisher or while debug mode by owners.
|
|
|
|
@moduleName Module name which will be configured
|
|
@aType Type of variable (announcementType).
|
|
@value New value
|
|
@success Was the function successful?
|
|
*/
|
|
(bool _success, bool _found, uint256 _id) = getModuleIDByAddress(msg.sender);
|
|
require( _success );
|
|
if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) {
|
|
require( block.number < debugModeUntil );
|
|
if ( ! insertAndCheckDo(calcDoHash("configureModule", keccak256(abi.encodePacked(moduleName, aType, value)))) ) {
|
|
return true;
|
|
}
|
|
}
|
|
(_success, _found, _id) = getModuleIDByName(moduleName);
|
|
require( _success && _found );
|
|
require( schelling(modules[_id].addr).configure(aType, value) );
|
|
return true;
|
|
}
|
|
function freezing(bool forever) external {
|
|
/*
|
|
Freezing CORION Platform. Can be called only by the owner.
|
|
Freeze can not be recalled!
|
|
|
|
@forever Is it forever or not?
|
|
*/
|
|
require( owners[msg.sender] );
|
|
if ( forever ) {
|
|
if ( ! insertAndCheckDo(calcDoHash("freezing", keccak256(abi.encodePacked(forever)))) ) {
|
|
return;
|
|
}
|
|
}
|
|
for ( uint256 a=0 ; a<modules.length ; a++ ) {
|
|
require( abstractModule(modules[a].addr).disableModule(forever) );
|
|
}
|
|
}
|
|
}
|