Created
September 11, 2018 16:18
-
-
Save drandreaskrueger/ae3027daa95492465f4c37940de40de7 to your computer and use it in GitHub Desktop.
ordered concatenation of all 20 solidity contracts at https://github.com/energywebfoundation/ew-origin/tree/master/contracts on 2018 September 11th (Latest commit b724754 on Jul 31)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// ordered concatenation of all 20 solidity contracts at | |
// https://github.com/energywebfoundation/ew-origin/tree/master/contracts | |
// on 2018 September 11th (Latest commit b724754 on Jul 31) | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Simon Jentzsch, [email protected] | |
contract Owned { | |
/// @dev `owner` is the only address that can call a function with this | |
modifier onlyOwner { require (msg.sender == owner); _; } | |
event LogChangeOwner(address _newOwner); | |
address public owner; | |
/// @notice The Constructor assigns the message sender to be `owner` | |
function Owned(address _initOwner) public { owner = _initOwner;} | |
/// @notice `owner` can step down and assign some other address to this role | |
/// @param _newOwner The address of the new owner. 0x0 can be used to create | |
function changeOwner (address _newOwner) public onlyOwner { | |
require(_newOwner != address(0)); | |
owner = _newOwner; | |
LogChangeOwner(_newOwner); | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title this contracts provides those functions that both consuming and producing assets share | |
contract AssetGeneralDefinition is Owned { | |
struct GeneralInformation { | |
address smartMeter; | |
address owner; | |
uint operationalSince; | |
uint lastSmartMeterReadWh; | |
bool active; | |
bytes32 lastSmartMeterReadFileHash; | |
uint lastMeterReadReceived; | |
bool exists; | |
} | |
/// @notice function to set all the location Informations for an asset, gets called internally | |
/// @param _loc the storage location of the location informations | |
/// @param _country The country where the asset is located | |
/// @param _region The region / state where the asset is located | |
/// @param _zip The zip-code of the region where the asset is located | |
/// @param _city The city where the asset is located | |
/// @param _street The streetname where the asset is located | |
/// @param _houseNumber the housenumber where the asset is located | |
/// @param _gpsLatitude The gps-latitude | |
/// @param _gpsLongitude The gps-longitude | |
function initLocationInternal( | |
LocationDefinition.Location storage _loc, | |
bytes32 _country, | |
bytes32 _region, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _street, | |
bytes32 _houseNumber, | |
bytes32 _gpsLatitude, | |
bytes32 _gpsLongitude | |
) | |
internal | |
{ | |
_loc.country = _country; | |
_loc.region = _region; | |
_loc.zip = _zip; | |
_loc.city = _city; | |
_loc.street = _street; | |
_loc.houseNumber = _houseNumber; | |
_loc.gpsLatitude = _gpsLatitude; | |
_loc.gpsLongitude = _gpsLongitude; | |
_loc.exists = true; | |
} | |
/// @notice internal function to set the general information | |
/// @param _gi storage location of the general information | |
/// @param _smartMeter smartMeter-address | |
/// @param _owner owner-of the asset | |
/// @param _operationalSince operatinal since that timestamp | |
/// @param _lastSmartMeterReadWh the last meterreading in Wh | |
/// @param _active flag if the asset is active | |
/// @param _lastSmartMeterReadFileHash the last filehash | |
function setGeneralInformationInternal( | |
GeneralInformation storage _gi, | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
uint _lastSmartMeterReadWh, | |
bool _active, | |
bytes32 _lastSmartMeterReadFileHash | |
) | |
internal | |
{ | |
_gi.smartMeter = _smartMeter; | |
_gi.owner = _owner; | |
_gi.operationalSince = _operationalSince; | |
_gi.lastSmartMeterReadWh = _lastSmartMeterReadWh; | |
_gi.active = _active; | |
_gi.lastSmartMeterReadFileHash = _lastSmartMeterReadFileHash; | |
_gi.lastMeterReadReceived = 0; | |
_gi.exists = true; | |
} | |
/// @notice function to get the informations about the location of a struct | |
/// @param _loc storage location of the locationInformations | |
/// @return country, region, zip, city, street, houseNumber, gpsLatitude, gpsLongitude | |
function getAssetLocationInternal(LocationDefinition.Location memory _loc) | |
internal | |
pure | |
returns( | |
bytes32 country, | |
bytes32 region, | |
bytes32 zip, | |
bytes32 city, | |
bytes32 street, | |
bytes32 houseNumber, | |
bytes32 gpsLatitude, | |
bytes32 gpsLongitude | |
) | |
{ | |
country = _loc.country; | |
region = _loc.region; | |
zip = _loc.zip; | |
city = _loc.city; | |
street = _loc.street; | |
houseNumber = _loc.houseNumber; | |
gpsLatitude = _loc.gpsLatitude; | |
gpsLongitude = _loc.gpsLongitude; | |
return (country, region, zip, city, street, houseNumber, gpsLatitude, gpsLongitude); | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title this interface defines the functions that both consuming and producing assets are sharing | |
interface AssetDbInterface { | |
function getActive(uint _assetId) external view returns(bool); | |
function getExistStatus(uint _assetId) external view returns (bool general, bool location, bool asset); | |
function createAsset() external returns (uint); | |
function initLocation(uint _assetId, bytes32 _country, bytes32 _region, bytes32 _zip, bytes32 _city, bytes32 _street, bytes32 _houseNumber, bytes32 _gpsLatitude, bytes32 _gpsLongitude) external; | |
function setActive(uint _assetId, bool _active) external; | |
function setAssetExistStatus(uint _assetId, bool _exist) external; | |
function setCapacityWh(uint _assetId, uint _capacityWh) external; | |
function setLastSmartMeterReadDate(uint _assetId, uint _timestamp) external; | |
function setLastSmartMeterReadFileHash(uint _assetId, bytes32 _lastSmartMeterReadFileHash) external; | |
function setSmartMeter(uint _assetId, address _smartMeter) external; | |
function getAssetListLength() external view returns (uint); | |
function getAssetLocation(uint _assetId) external view returns(bytes32 country, bytes32 region, bytes32 zip, bytes32 city, bytes32 street, bytes32 houseNumber, bytes32 gpsLatitude, bytes32 gpsLongitude); | |
function getLastSmartMeterRead(uint _assetId) external returns (uint); | |
function getLastSmartMeterReadDate(uint _assetId) external returns(uint); | |
function getLastSmartMeterReadFileHash(uint _assetId) external view returns(bytes32); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
pragma solidity ^0.4.18; | |
/// @title The Database contract for the Asset Registration | |
/// @notice This contract only provides getter and setter methods | |
contract AssetConsumingRegistryDB is Owned, AssetGeneralDefinition, AssetDbInterface { | |
struct ConsumingProperties { | |
uint capacityWh; | |
bool maxCapacitySet; | |
uint certificatesUsedForWh; | |
} | |
struct Asset { | |
GeneralInformation general; | |
ConsumingProperties consumingProps; | |
LocationDefinition.Location location; | |
bool exists; | |
} | |
/// @notice An array containing all registerd assets | |
Asset[] private assets; | |
/// @dev empty structs for initializing, used to avoid compile warnings | |
GeneralInformation generalEmpty; | |
LocationDefinition.Location locationEmpty; | |
ConsumingProperties consumingEmpty; | |
/// @notice Constructor | |
/// @param _owner The owner of the contract | |
function AssetConsumingRegistryDB(address _owner) | |
public | |
Owned(_owner) | |
{ | |
} | |
/// @notice function to create a new empty asset | |
/// @return returns the array-position and thus the index / identifier of this new asset | |
function createAsset() | |
external | |
onlyOwner | |
returns (uint _assetId) | |
{ | |
_assetId = assets.length; | |
assets.push(AssetConsumingRegistryDB.Asset({ | |
general: generalEmpty, | |
consumingProps: consumingEmpty, | |
location: locationEmpty, | |
exists: false | |
})); | |
} | |
/// @notice Sets the general information for an asset | |
/// @param _assetId The index / identifier for that asset | |
/// @param _smartMeter The address of the smart meter | |
/// @param _owner The address of the asset owner | |
/// @param _operationalSince The timestamp since the asset is operational | |
/// @param _capacityWh The capacity in Wh of the asset | |
/// @param _lastSmartMeterReadWh The smart meter read in Wh | |
/// @param _certificatesUsedForWh The amount of Wh used to issue certificates | |
/// @param _active true if active | |
/// @param _lastSmartMeterReadFileHash The last meter read file hash | |
function initGeneral ( | |
uint _assetId, | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
uint _capacityWh, | |
bool _maxCapacitySet, | |
uint _lastSmartMeterReadWh, | |
uint _certificatesUsedForWh, | |
bool _active, | |
bytes32 _lastSmartMeterReadFileHash | |
) | |
onlyOwner | |
external | |
{ | |
Asset storage a = assets[_assetId]; | |
GeneralInformation storage gi = a.general; // just want to doublecheck, gi is a pointer to the storage, right? | |
ConsumingProperties storage cp = a.consumingProps; | |
setGeneralInformationInternal(gi, _smartMeter, _owner, _operationalSince,_lastSmartMeterReadWh, _active, _lastSmartMeterReadFileHash); | |
cp.certificatesUsedForWh = _certificatesUsedForWh; | |
cp.capacityWh = _capacityWh; | |
cp.maxCapacitySet = _maxCapacitySet; | |
} | |
/// @notice function to set all the location Informations for an asset | |
/// @param _assetId The identifier / index of an asset | |
/// @param _country The country where the asset is located | |
/// @param _region The region / state where the asset is located | |
/// @param _zip The zip-code of the region where the asset is located | |
/// @param _city The city where the asset is located | |
/// @param _street The streetname where the asset is located | |
/// @param _houseNumber the housenumber where the asset is located | |
/// @param _gpsLatitude The gps-latitude | |
/// @param _gpsLongitude The gps-longitude | |
function initLocation( | |
uint _assetId, | |
bytes32 _country, | |
bytes32 _region, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _street, | |
bytes32 _houseNumber, | |
bytes32 _gpsLatitude, | |
bytes32 _gpsLongitude | |
) | |
onlyOwner | |
external | |
{ | |
LocationDefinition.Location storage loc = assets[_assetId].location; | |
initLocationInternal(loc, _country, _region, _zip, _city, _street, _houseNumber, _gpsLatitude, _gpsLongitude); | |
} | |
/// @notice Sets if an entry in the asset registry is active | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _active true if active | |
function setActive(uint _assetId, bool _active) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.active = _active; | |
} | |
/// @notice function to set the existing status of an asset | |
/// @param _assetId The index position / identifier of an asset | |
/// @param _exist flag if the asset should exist | |
function setAssetExistStatus(uint _assetId, bool _exist) | |
external | |
onlyOwner | |
{ | |
assets[_assetId].exists = _exist; | |
} | |
/// @notice Sets the capacity in Wh of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _capacityWh The capacity in Wh | |
function setCapacityWh(uint _assetId, uint _capacityWh) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].consumingProps.capacityWh = _capacityWh; | |
} | |
/// @notice Sets amount of Wh used to issue certificates belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _certificatesUsedForWh The amount of Wh used to issue certificates | |
function setCertificatesUsedForWh(uint _assetId, uint _certificatesUsedForWh) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].consumingProps.certificatesUsedForWh = _certificatesUsedForWh; | |
} | |
/// @notice Sets a timestamp for the last meterreading | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @param _timestamp new UNIX-timestamp | |
function setLastSmartMeterReadDate(uint _assetId, uint _timestamp) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.lastMeterReadReceived = _timestamp; | |
} | |
/// @notice Sets last meter read file hash | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _lastSmartMeterReadFileHash Last meter read file hash | |
function setLastSmartMeterReadFileHash(uint _assetId, bytes32 _lastSmartMeterReadFileHash) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.lastSmartMeterReadFileHash = _lastSmartMeterReadFileHash; | |
} | |
/// @notice Sets the last smart meter read in Wh of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _lastSmartMeterReadWh The smart meter read in Wh | |
function setLastSmartMeterReadWh(uint _assetId, uint _lastSmartMeterReadWh) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.lastSmartMeterReadWh = _lastSmartMeterReadWh; | |
} | |
/// @notice Sets the location-country of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @param _country the new country | |
function setLocationCountry(uint _assetId, bytes32 _country) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].location.country = _country; | |
} | |
/// @notice Sets the location-region of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @param _region the new region | |
function setLocationRegion(uint _assetId, bytes32 _region) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].location.region = _region; | |
} | |
/// @notice Sets the operational since field of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _operationalSince The timestamp since the asset is operational | |
function setOperationalSince(uint _assetId, uint _operationalSince) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.operationalSince = _operationalSince; | |
} | |
/// @notice Sets the owner of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _owner The new owner | |
function setOwner(uint _assetId, address _owner) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.owner = _owner; | |
} | |
/// @notice Sets the smart meter address belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _smartMeter The new smart meter address | |
function setSmartMeter(uint _assetId, address _smartMeter) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.smartMeter = _smartMeter; | |
} | |
/// @notice Sets multiple information of a meterreading | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _newMeterRead the new meterreading | |
/// @param _lastSmartMeterReadFileHash the filehash belonging to that reading | |
/// @param _timestamp the timestamp of that reading | |
function setSmartMeterReadData(uint _assetId, uint _newMeterRead, bytes32 _lastSmartMeterReadFileHash, uint _timestamp) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.lastSmartMeterReadWh = _newMeterRead; | |
assets[_assetId].general.lastSmartMeterReadFileHash = _lastSmartMeterReadFileHash; | |
assets[_assetId].general.lastMeterReadReceived = _timestamp; | |
} | |
/// @notice Gets if an entry in the asset registry is active | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return true if asset is active | |
function getActive(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(bool) | |
{ | |
return assets[_assetId].general.active; | |
} | |
/// @notice Gets the general information of an asset | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return general information of an asset | |
function getAssetGeneral(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns( | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
uint _capacityWh, | |
bool _maxCapacitySet, | |
uint _lastSmartMeterReadWh, | |
uint _certificatesUsedForWh, | |
bool _active, | |
bytes32 _lastSmartMeterReadFileHash | |
) | |
{ | |
Asset storage asset = assets[_assetId]; | |
GeneralInformation memory gi = asset.general; | |
ConsumingProperties memory cp = asset.consumingProps; | |
_smartMeter = gi.smartMeter; | |
_owner = gi.owner; | |
_operationalSince = gi.operationalSince; | |
_capacityWh = cp.capacityWh; | |
_maxCapacitySet = cp.maxCapacitySet; | |
_lastSmartMeterReadWh = gi.lastSmartMeterReadWh; | |
_certificatesUsedForWh = cp.certificatesUsedForWh; | |
_active = gi.active; | |
_lastSmartMeterReadFileHash = gi.lastSmartMeterReadFileHash; | |
} | |
/// @notice function to get the amount of assets | |
/// @return amount of assets | |
function getAssetListLength() | |
onlyOwner | |
external | |
view | |
returns (uint) | |
{ | |
return assets.length; | |
} | |
/// @notice function to get the informations about the location of a struct | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return country, region, zip, city, street, houseNumber, gpsLatitude, gpsLongitude | |
function getAssetLocation(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns( | |
bytes32 country, | |
bytes32 region, | |
bytes32 zip, | |
bytes32 city, | |
bytes32 street, | |
bytes32 houseNumber, | |
bytes32 gpsLatitude, | |
bytes32 gpsLongitude | |
) | |
{ | |
LocationDefinition.Location memory loc = assets[_assetId].location; | |
return getAssetLocationInternal(loc); | |
} | |
/// @notice Gets the capacity in Wh of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the capacity in Wh | |
function getCapacityWh(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].consumingProps.capacityWh; | |
} | |
/// @notice Gets amount of Wh used to issue certificates belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the amount of Wh used to issue certificates | |
function getCertificatesUsedForWh(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].consumingProps.certificatesUsedForWh; | |
} | |
/// @notice gets the consuming properties of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @return the consuming properteis | |
function getConsumingProperies(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns ( | |
uint _capacityWh, | |
bool _maxCapacitySet, | |
uint _certificatesUsedForWh | |
) | |
{ | |
ConsumingProperties memory c = assets[_assetId].consumingProps; | |
_capacityWh = c.capacityWh; | |
_maxCapacitySet = c.maxCapacitySet; | |
_certificatesUsedForWh = c.certificatesUsedForWh; | |
} | |
/// @notice function the retrieve the existing status of the general information, the location information and the asset itself | |
/// @param _assetId The index position / identifier of the asset | |
/// @return existing status of the general informaiton, existing status of the location informaiton and where the asset-structs exists | |
function getExistStatus(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns (bool general, bool location, bool asset) | |
{ | |
Asset memory a = assets[_assetId]; | |
return(a.general.exists, a.location.exists, a.exists); | |
} | |
/// @notice function to retrieve the last smartmeter-reading of an asset | |
/// @param _assetId the asset-id | |
/// @return the last smartmeter-reading | |
function getLastSmartMeterRead(uint _assetId) | |
onlyOwner | |
external | |
returns (uint) | |
{ | |
return assets[_assetId].general.lastSmartMeterReadWh; | |
} | |
/// @notice function to retrieve the timestamp of the last smartmeter-reading | |
/// @param _assetId the asset-id | |
/// @return the timestamp of the last smartmeter-reading | |
function getLastSmartMeterReadDate(uint _assetId) | |
onlyOwner | |
external | |
returns(uint) | |
{ | |
return assets[_assetId].general.lastMeterReadReceived; | |
} | |
/// @notice Gets last smart merter read file hash | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return last smart merter read file hash | |
function getLastSmartMeterReadFileHash(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(bytes32) | |
{ | |
return assets[_assetId].general.lastSmartMeterReadFileHash; | |
} | |
/// @notice Gets the last smart merter read in Wh of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the last loged smart meter read in Wh | |
function getLastSmartMeterReadWh(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].general.lastSmartMeterReadWh; | |
} | |
/// @notice Gets the location country of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @return country where the asset is based | |
function getLocationCountry(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(bytes32) | |
{ | |
return assets[_assetId].location.country; | |
} | |
/// @notice Gets the location region of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @return region of the country where the asset is based | |
function getLocationRegion(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(bytes32) | |
{ | |
return assets[_assetId].location.region; | |
} | |
/// @notice Gets the operational since field of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return date when the asset went into production | |
function getOperationalSince(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].general.operationalSince; | |
} | |
/// @notice Gets the owner of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the owner address | |
function getOwner(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(address) | |
{ | |
return assets[_assetId].general.owner; | |
} | |
/// @notice Gets the smart meter address belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the smart meter address | |
function getSmartMeter(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(address) | |
{ | |
return assets[_assetId].general.smartMeter; | |
} | |
}// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @notice contract for managing the rights and roles | |
contract RoleManagement { | |
/// @notice central registry contract | |
CoO public cooContract; | |
/// @notice all possible available roles | |
/* | |
no role: 0x0...0000000 | |
TopAdmin: 0x0...------1 | |
UserAdmin: 0x0...-----1- | |
AssetAdmin: 0x0...----1-- | |
AgreementAdmin: 0x0...---1--- | |
AssetManager: 0x0...--1---- | |
Trader: 0x0...-1----- | |
Matcher: 0x0...1----- | |
*/ | |
enum Role{ | |
TopAdmin, | |
UserAdmin, | |
AssetAdmin, | |
AgreementAdmin, | |
AssetManager, | |
Trader, | |
Matcher | |
} | |
/// @notice modifier for checking if an user is allowed to execute the intended action | |
modifier onlyRole (RoleManagement.Role _role) { | |
require (isRole(_role, msg.sender)); | |
_; | |
} | |
modifier onlyAccount(address accountAddress) { | |
require(msg.sender == accountAddress); | |
_; | |
} | |
modifier userExists(address _user){ | |
require(RolesInterface(cooContract.userRegistry()).doesUserExist(_user)); | |
_; | |
} | |
modifier userHasRole(RoleManagement.Role _role, address _user){ | |
require (isRole(_role, _user)); | |
_; | |
} | |
/// @notice constructor | |
/// @param _cooContract CoO.sol-registry contract | |
function RoleManagement (CoO _cooContract) public { | |
cooContract = _cooContract; | |
} | |
/// @notice funciton for comparing the role and the needed rights of an user | |
/// @param _role role of a user | |
/// @param _caller the address calling that function | |
/// @return whether the user has the corresponding rights for the intended action | |
function isRole(RoleManagement.Role _role, address _caller) public view returns (bool) { | |
require(uint(_role) <= 7); | |
if (cooContract.owner() == _caller) { | |
return true; | |
} | |
/// @dev reading the rights for the user from the userDB-contract | |
uint rights = RolesInterface(cooContract.userRegistry()).getRolesRights(_caller); | |
/// @dev converting the used enum to the corresponding bitmask | |
uint role = uint(2) ** uint(_role); | |
/// @dev comparing rights and roles, if the result is not 0 the user has the right (bitwise comparison) | |
/// we also don't have to check for a potential overflow here, because the used enum will prevent using roles that do not exist | |
return (rights & role != 0); | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title this interface defines the required update-function that every updatable-contract has to implement | |
interface Updatable { | |
function update(address _newLogic) external; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title Contract for storing the current logic-contracts-addresses for the certificate of origin | |
contract AssetLogic is RoleManagement, Updatable { | |
event LogAssetCreated(address sender, uint indexed _assetId); | |
event LogAssetFullyInitialized(uint indexed _assetId); | |
event LogAssetSetActive(uint indexed _assetId); | |
event LogAssetSetInactive(uint indexed _assetId); | |
AssetDbInterface public db; | |
modifier isInitialized { | |
require(address(db) != 0x0); | |
_; | |
} | |
/// @notice Constructor | |
/// @param _cooContract The address of the coo contract | |
function AssetLogic(CoO _cooContract) | |
public | |
RoleManagement(_cooContract) | |
{ | |
} | |
/// @notice function to create a new empty asset, triggers event with created AssetID. To actually create an Asset the functions initGeneral and initLocations have to be called | |
function createAsset() | |
external | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
isInitialized | |
{ | |
uint assetId = db.createAsset(); | |
LogAssetCreated(msg.sender, assetId); | |
} | |
/// @notice function toinizialize the database, can only be called once | |
/// @param _dbAddress address of the database contract | |
function init(address _dbAddress) | |
public | |
onlyRole(RoleManagement.Role.TopAdmin) | |
{ | |
require(address(db) == 0x0); | |
db = AssetDbInterface(_dbAddress); | |
} | |
/// @notice Sets the location information of an asset in the database | |
/// @param _assetId the The index / identifier of an asset | |
/// @param _country The country where the asset is located | |
/// @param _region The region where the asset is located | |
/// @param _zip The zip coe where the asset is located | |
/// @param _city The city where the asset is located | |
/// @param _street The street where the asset is located | |
/// @param _houseNumber The house number where the asset is located | |
/// @param _gpsLatitude The gps-latitude of the asset | |
/// @param _gpsLongitude The gps-longitude of the asset | |
function initLocation ( | |
uint _assetId, | |
bytes32 _country, | |
bytes32 _region, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _street, | |
bytes32 _houseNumber, | |
bytes32 _gpsLatitude, | |
bytes32 _gpsLongitude | |
) | |
external | |
isInitialized | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
{ | |
db.initLocation(_assetId, _country, _region, _zip, _city, _street, _houseNumber, _gpsLatitude, _gpsLongitude); | |
updateAssetExistStatus(_assetId); | |
} | |
/// @notice Sets active to false | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _active flag if the asset is asset or not | |
function setActive(uint _assetId, bool _active) | |
external | |
isInitialized | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
{ | |
db.setActive(_assetId, _active); | |
if (_active) { | |
LogAssetSetActive(_assetId); | |
} else { | |
LogAssetSetInactive(_assetId); | |
} | |
} | |
/// @notice Updates the logic contract | |
/// @param _newLogic Address of the new logic contract | |
function update(address _newLogic) | |
external | |
onlyAccount(address(cooContract)) | |
{ | |
Owned(db).changeOwner(_newLogic); | |
} | |
/// @notice gets the active flag on an asset | |
/// @param _assetId the assetId | |
/// @return the active flag | |
function getActive(uint _assetId) | |
external | |
view | |
returns (bool) | |
{ | |
return db.getActive(_assetId); | |
} | |
/// @notice Gets the last filehash of the smart reader | |
/// @param _assetId the assetId | |
/// @return the alst smartmeterread-filehash | |
function getLastSmartMeterReadFileHash(uint _assetId) | |
external | |
view | |
returns (bytes32 datalog) | |
{ | |
return db.getLastSmartMeterReadFileHash(_assetId); | |
} | |
/// @notice Function to get the amount of all assets | |
/// @dev needed to iterate though all the asset | |
/// @return the amount of all assets | |
function getAssetListLength() | |
external | |
view | |
returns (uint) | |
{ | |
return db.getAssetListLength(); | |
} | |
/// @notice Funtion to get the informaiton of the location of an asset | |
/// @param _assetId The identifier / index of the asset | |
/// @return country, region, zip-code, city, street, houseNumber, gpsLatitude, gpsLongitude | |
function getAssetLocation(uint _assetId) | |
external | |
view | |
returns( | |
bytes32 country, | |
bytes32 region, | |
bytes32 zip, | |
bytes32 city, | |
bytes32 street, | |
bytes32 houseNumber, | |
bytes32 gpsLatitude, | |
bytes32 gpsLongitude | |
) | |
{ | |
return db.getAssetLocation(_assetId); | |
} | |
/// @notice Changes the address of a smart meter belonging to an asset | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _newSmartMeter The address of the new smart meter | |
function updateSmartMeter(uint _assetId, address _newSmartMeter) | |
external | |
isInitialized | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
{ | |
db.setSmartMeter(_assetId, _newSmartMeter); | |
} | |
/// @notice Checks if a fully Asset-struct is created, enabled if asset all information are there | |
/// @dev only for internal use | |
/// @param _assetId the The index / identifier of an asset | |
function updateAssetExistStatus(uint _assetId) | |
internal | |
{ | |
var (general, location, asset) = db.getExistStatus(_assetId); | |
if(general && location && !asset) { | |
db.setAssetExistStatus(_assetId,true); | |
LogAssetFullyInitialized(_assetId); | |
db.setLastSmartMeterReadDate(_assetId, now); | |
} | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
/// @title The logic contract for the asset registration | |
/// @notice This contract provides the logic that determines how the data is stored | |
/// @dev Needs a valid AssetProducingRegistryDB contract to function correctly | |
contract AssetConsumingRegistryLogic is AssetLogic { | |
event LogNewMeterRead( | |
uint indexed _assetId, | |
bytes32 indexed _fileHash, | |
uint _oldMeterRead, | |
uint _newMeterRead, | |
uint _certificatesUsedForWh, | |
bool _smartMeterDown | |
); | |
/// @notice Constructor | |
/// @param _cooContract The address of the coo contract | |
function AssetConsumingRegistryLogic(CoO _cooContract) | |
public | |
AssetLogic(_cooContract) | |
{ | |
} | |
/// @notice Sets the general information of an asset in the database | |
/// @param _assetId the The index / identifier of an asset | |
/// @param _smartMeter The address of the smart meter | |
/// @param _owner The address of the asset owner | |
/// @param _operationalSince The timestamp since the asset is operational | |
/// @param _capacityWh The capacity in Wh of the asset | |
/// @param _maxCapacitySet flag whether there should be a max capacity | |
/// @param _active true if active | |
function initGeneral ( | |
uint _assetId, | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
uint _capacityWh, | |
bool _maxCapacitySet, | |
bool _active | |
) | |
external | |
isInitialized | |
userHasRole(RoleManagement.Role.AssetManager, _owner) | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
{ | |
AssetConsumingRegistryDB(db).initGeneral(_assetId, _smartMeter, _owner, _operationalSince, _capacityWh, _maxCapacitySet, 0, 0, _active, 0x0); | |
updateAssetExistStatus(_assetId); | |
} | |
/// @notice Logs meter read | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _newMeterRead The current meter read of the asset | |
/// @param _lastSmartMeterReadFileHash Last meter read file hash | |
/// @param _smartMeterDown flag whether the smartmeter was down | |
/// @dev The client needs to check if the blockgas limit could be reached and if so the log should be splitted | |
function saveSmartMeterRead(uint _assetId, uint _newMeterRead, bytes32 _lastSmartMeterReadFileHash, bool _smartMeterDown) | |
external | |
isInitialized | |
onlyAccount(AssetConsumingRegistryDB((db)).getSmartMeter(_assetId)) | |
{ | |
require(db.getActive(_assetId)); | |
uint oldMeterRead = AssetConsumingRegistryDB((db)).getLastSmartMeterReadWh(_assetId); | |
LogNewMeterRead(_assetId, _lastSmartMeterReadFileHash, oldMeterRead, _newMeterRead, AssetConsumingRegistryDB((db)).getCertificatesUsedForWh(_assetId), _smartMeterDown); | |
/// @dev need to check if new meter read is higher then the old one | |
AssetConsumingRegistryDB((db)).setSmartMeterReadData(_assetId, _newMeterRead, _lastSmartMeterReadFileHash, now); | |
} | |
/// @notice Gets an asset | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return general information of an asset | |
function getAssetGeneral(uint _assetId) | |
external | |
view | |
returns ( | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
uint _capacityWh, | |
bool _maxCapacitySet, | |
uint _lastSmartMeterReadWh, | |
uint _certificatesUsedForWh, | |
bool _active, | |
bytes32 _lastSmartMeterReadFileHash | |
) | |
{ | |
return AssetConsumingRegistryDB(address(db)).getAssetGeneral(_assetId); | |
} | |
/// @notice gets the consuming properties of an asset | |
/// @param _assetId the assetId | |
/// @return retuns capacity, maxCapacitySet-falg and certificatesUsedForWh | |
function getConsumingProperies(uint _assetId) | |
external | |
view | |
returns ( | |
uint capacityWh, | |
bool maxCapacitySet, | |
uint certificatesUsedForWh | |
) | |
{ | |
(capacityWh, maxCapacitySet, certificatesUsedForWh) = AssetConsumingRegistryDB(address(db)).getConsumingProperies(_assetId); | |
} | |
/// @notice sets the consumption for a period (in Wh) | |
/// @param _assetId assetId | |
/// @param _consumed the amount of energy consumed | |
function setConsumptionForPeriode(uint _assetId, uint _consumed) | |
external | |
onlyAccount(address(cooContract.demandRegistry())) | |
{ | |
AssetConsumingRegistryDB(db).setCertificatesUsedForWh(_assetId, _consumed); | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Heiko Burkhardt, [email protected] | |
/// @title The Database contract for the Asset Registration | |
/// @notice This contract only provides getter and setter methods | |
contract AssetProducingRegistryDB is AssetGeneralDefinition, AssetDbInterface { | |
struct ProducingProperties { | |
uint assetType; | |
uint capacityWh; | |
uint certificatesCreatedForWh; | |
uint lastSmartMeterCO2OffsetRead; | |
uint cO2UsedForCertificate; | |
uint registryCompliance; | |
bytes32 otherGreenAttributes; | |
bytes32 typeOfPublicSupport; | |
} | |
struct Asset { | |
AssetGeneralDefinition.GeneralInformation general; | |
ProducingProperties producingProps; | |
LocationDefinition.Location location; | |
bool exists; | |
} | |
/// @notice An array containing all registerd assets | |
Asset[] private assets; | |
/// @dev empty structs for initializing, used to avoid compile warnings | |
AssetGeneralDefinition.GeneralInformation generalEmpty; | |
LocationDefinition.Location locationEmpty; | |
ProducingProperties producingEmpty; | |
/// @notice Constructor | |
/// @param _owner The owner of the contract | |
function AssetProducingRegistryDB(address _owner) | |
public | |
Owned(_owner) | |
{ | |
} | |
/// @notice function to create a new empty asset | |
/// @return returns the array-position and thus the index / identifier of this new asset | |
function createAsset() | |
external | |
onlyOwner | |
returns (uint _assetId) | |
{ | |
_assetId = assets.length; | |
assets.push(AssetProducingRegistryDB.Asset({ | |
general: generalEmpty, | |
producingProps: producingEmpty, | |
location: locationEmpty, | |
exists: false | |
})); | |
} | |
/// @notice function to set the general information for an asset | |
/// @param _assetId the ID belonging to the asset | |
/// @param _smartMeter the smart-meter address | |
/// @param _owner the owner of the asset | |
/// @param _operationalSince timestamp of when the asset started producing energy | |
/// @param _lastSmartMeterReadWh the last reading of the smartmeter | |
/// @param _active active-flag | |
/// @param _lastSmartMeterReadFileHash the last filehash of the smartmeter-readings | |
function initGeneral( | |
uint _assetId, | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
uint _lastSmartMeterReadWh, | |
bool _active, | |
bytes32 _lastSmartMeterReadFileHash | |
) | |
onlyOwner | |
external | |
{ | |
Asset storage a = assets[_assetId]; | |
setGeneralInformationInternal(a.general, _smartMeter, _owner, _operationalSince,_lastSmartMeterReadWh, _active, _lastSmartMeterReadFileHash); | |
} | |
/// @notice function to set the producing-properties of an asset | |
/// @param _assetId the ID belonging to the asset | |
/// @param _assetType the assetType of the asset | |
/// @param _lastSmartMeterCO2OffsetRead the last CO2-Offsetreading of the smartmeter | |
/// @param _cO2UsedForCertificate the amount of CO2 used for certificates already | |
/// @param _capacityWh the capacity of the asset in Wh | |
/// @param _certificatesCreatedForWh the amount of Wh already certificated | |
/// @param _registryCompliance the registry-compliance | |
/// @param _otherGreenAttributes other green attributes | |
/// @param _typeOfPublicSupport type of public support | |
function initProducing( | |
uint _assetId, | |
uint _assetType, | |
uint _lastSmartMeterCO2OffsetRead, | |
uint _cO2UsedForCertificate, | |
uint _capacityWh, | |
uint _certificatesCreatedForWh, | |
uint _registryCompliance, | |
bytes32 _otherGreenAttributes, | |
bytes32 _typeOfPublicSupport | |
) | |
onlyOwner | |
external | |
{ | |
Asset storage a = assets[_assetId]; | |
a.producingProps.assetType = _assetType; | |
a.producingProps.lastSmartMeterCO2OffsetRead = _lastSmartMeterCO2OffsetRead; | |
a.producingProps.cO2UsedForCertificate = _cO2UsedForCertificate; | |
a.producingProps.certificatesCreatedForWh = _certificatesCreatedForWh; | |
a.producingProps.capacityWh = _capacityWh; | |
a.producingProps.registryCompliance = _registryCompliance; | |
a.producingProps.otherGreenAttributes = _otherGreenAttributes; | |
a.producingProps.typeOfPublicSupport = _typeOfPublicSupport; | |
} | |
/// @notice function to set all the location Informations for an asset | |
/// @param _assetId The identifier / index of an asset | |
/// @param _country The country where the asset is located | |
/// @param _region The region / state where the asset is located | |
/// @param _zip The zip-code of the region where the asset is located | |
/// @param _city The city where the asset is located | |
/// @param _street The streetname where the asset is located | |
/// @param _houseNumber the housenumber where the asset is located | |
/// @param _gpsLatitude The gps-latitude | |
/// @param _gpsLongitude The gps-longitude | |
function initLocation( | |
uint _assetId, | |
bytes32 _country, | |
bytes32 _region, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _street, | |
bytes32 _houseNumber, | |
bytes32 _gpsLatitude, | |
bytes32 _gpsLongitude | |
) | |
onlyOwner | |
external | |
{ | |
LocationDefinition.Location storage loc = assets[_assetId].location; | |
initLocationInternal(loc,_country,_region,_zip,_city,_street,_houseNumber,_gpsLatitude,_gpsLongitude); | |
} | |
/// @notice Sets if an entry in the asset registry is active | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _active true if active | |
function setActive(uint _assetId, bool _active) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.active = _active; | |
} | |
/// @notice function to set the existing status of an asset | |
/// @param _assetId The index position / identifier of an asset | |
/// @param _exist flag if the asset should exist | |
function setAssetExistStatus(uint _assetId, bool _exist) | |
external | |
onlyOwner | |
{ | |
Asset storage a = assets[_assetId]; | |
a.exists = _exist; | |
} | |
/// @notice Sets the fuel type belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _assetType The new fuel type | |
function setAssetType(uint _assetId, uint _assetType) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].producingProps.assetType = _assetType; | |
} | |
/// @notice Sets the capacity in Wh of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _capacityWh The capacity in Wh | |
function setCapacityWh(uint _assetId, uint _capacityWh) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].producingProps.capacityWh = _capacityWh; | |
} | |
/// @notice Sets amount of Wh used to issue certificates belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _certificatesCreatedForWh The amount of Wh used to issue certificates | |
function setCertificatesCreatedForWh(uint _assetId, uint _certificatesCreatedForWh) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].producingProps.certificatesCreatedForWh = _certificatesCreatedForWh; | |
} | |
/// @notice Sets amount of saved CO2 used to issue certificates belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _used The amount of saved CO2 used to issue certificates | |
function setCO2UsedForCertificate(uint _assetId, uint _used) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].producingProps.cO2UsedForCertificate = _used; | |
} | |
/// @notice Sets the last smart meter read in saved CO2 of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _lastCO2OffsetReading The new amount of saved CO2 | |
function setLastCO2OffsetReading(uint _assetId, uint _lastCO2OffsetReading) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].producingProps.lastSmartMeterCO2OffsetRead = _lastCO2OffsetReading; | |
} | |
/// @notice Sets the timestamp of the last smartmeter-reading | |
/// @param _assetId the id belonging to the asset | |
/// @param _timestamp the new timestamp of reading | |
function setLastSmartMeterReadDate(uint _assetId, uint _timestamp) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.lastMeterReadReceived = _timestamp; | |
} | |
/// @notice Sets last meter read file hash | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _lastSmartMeterReadFileHash Last meter read file hash | |
function setLastSmartMeterReadFileHash(uint _assetId, bytes32 _lastSmartMeterReadFileHash) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.lastSmartMeterReadFileHash = _lastSmartMeterReadFileHash; | |
} | |
/// @notice Sets the last smart meter read in Wh of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _lastSmartMeterReadWh The smart meter read in Wh | |
function setLastSmartMeterReadWh(uint _assetId, uint _lastSmartMeterReadWh) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.lastSmartMeterReadWh = _lastSmartMeterReadWh; | |
} | |
/// @notice Sets the location-country of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @param _country the new country | |
function setLocationCountry(uint _assetId, bytes32 _country) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].location.country = _country; | |
} | |
/// @notice Sets the location-region of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @param _region the new region | |
function setLocationRegion(uint _assetId, bytes32 _region) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].location.region = _region; | |
} | |
/// @notice Sets multiple information of a meterreading | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _newMeterRead the new meterreading of the smart meter | |
/// @param _CO2OffsetMeterRead the new CO2-offset reading | |
/// @param _lastSmartMeterReadFileHash the filehash belonging to that reading | |
/// @param _timestamp the timestamp of that reading | |
function setSmartMeterReadData( | |
uint _assetId, | |
uint _newMeterRead, | |
uint _CO2OffsetMeterRead, | |
bytes32 _lastSmartMeterReadFileHash, | |
uint _timestamp | |
) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].producingProps.lastSmartMeterCO2OffsetRead = _CO2OffsetMeterRead; | |
assets[_assetId].general.lastSmartMeterReadWh = _newMeterRead; | |
assets[_assetId].general.lastSmartMeterReadFileHash = _lastSmartMeterReadFileHash; | |
assets[_assetId].general.lastMeterReadReceived = _timestamp; | |
} | |
/// @notice Sets the operational since field of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _operationalSince The timestamp since the asset is operational | |
function setOperationalSince(uint _assetId, uint _operationalSince) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.operationalSince = _operationalSince; | |
} | |
/// @notice Sets the owner of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _owner The new owner | |
function setOwner(uint _assetId, address _owner) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.owner = _owner; | |
} | |
/// @notice Sets the smart meter address belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _smartMeter The new smart meter address | |
function setSmartMeter(uint _assetId, address _smartMeter) | |
onlyOwner | |
external | |
{ | |
assets[_assetId].general.smartMeter = _smartMeter; | |
} | |
/// @notice Gets if an entry in the asset registry is active | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return true if asset is active | |
function getActive(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(bool) | |
{ | |
return assets[_assetId].general.active; | |
} | |
/// @notice Returns the general information of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @return smartmeter-address, owner-address, operationalSince, lastSmartMeterReading in Wh, active flag and the filehash of the last reading | |
function getAssetGeneral(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns | |
( | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
uint _lastSmartMeterReadWh, | |
bool _active, | |
bytes32 _lastSmartMeterReadFileHash | |
) | |
{ | |
Asset memory asset = assets[_assetId]; | |
_smartMeter = asset.general.smartMeter; | |
_owner = asset.general.owner; | |
_operationalSince = asset.general.operationalSince; | |
_lastSmartMeterReadWh = asset.general.lastSmartMeterReadWh; | |
_active = asset.general.active; | |
_lastSmartMeterReadFileHash = asset.general.lastSmartMeterReadFileHash; | |
} | |
/// @notice function to get the amount of assets | |
/// @return amount of assets | |
function getAssetListLength() | |
onlyOwner | |
external | |
view | |
returns (uint) | |
{ | |
return assets.length; | |
} | |
/// @notice function to get the informations about the location of a struct | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return country, region, zip, city, street, houseNumber, gpsLatitude, gpsLongitude | |
function getAssetLocation(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns( | |
bytes32 country, | |
bytes32 region, | |
bytes32 zip, | |
bytes32 city, | |
bytes32 street, | |
bytes32 houseNumber, | |
bytes32 gpsLatitude, | |
bytes32 gpsLongitude | |
) | |
{ | |
LocationDefinition.Location memory loc = assets[_assetId].location; | |
return getAssetLocationInternal(loc); | |
} | |
/// @notice function to get the producing-properties of an asset | |
/// @param _assetId the id belonging to the asset | |
/// @return returns the producing-properties of an asset | |
function getAssetProducingProperties(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns ( | |
uint assetType, | |
uint capacityWh, | |
uint certificatesCreatedForWh, | |
uint lastSmartMeterCO2OffsetRead, | |
uint cO2UsedForCertificate, | |
uint registryCompliance, | |
bytes32 otherGreenAttributes, | |
bytes32 typeOfPublicSupport | |
) | |
{ | |
Asset memory a = assets[_assetId]; | |
ProducingProperties memory pp = a.producingProps; | |
assetType = pp.assetType; | |
capacityWh = pp.capacityWh; | |
certificatesCreatedForWh = pp.certificatesCreatedForWh; | |
lastSmartMeterCO2OffsetRead = pp.lastSmartMeterCO2OffsetRead; | |
cO2UsedForCertificate = pp.cO2UsedForCertificate; | |
registryCompliance = pp.registryCompliance; | |
otherGreenAttributes = pp.otherGreenAttributes; | |
typeOfPublicSupport = pp.typeOfPublicSupport; | |
} | |
/// @notice Gets the asset type belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the type of asset | |
function getAssetType(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].producingProps.assetType; | |
} | |
/// @notice Gets the capacity in Wh of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the capacity in Wh | |
function getCapacityWh(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].producingProps.capacityWh; | |
} | |
/// @notice Gets amount of Wh used to issue certificates belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the amount of Wh used to issue certificates | |
function getCertificatesCreatedForWh(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].producingProps.certificatesCreatedForWh; | |
} | |
/// @notice Gets the amount of already used CO2-offset for creating certificates | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the aount of already used CO2-offset | |
function getCo2UsedForCertificate(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns (uint) | |
{ | |
return assets[_assetId].producingProps.cO2UsedForCertificate; | |
} | |
/// @notice function the retrieve the existing status of the general information, the location information and the asset itself | |
/// @param _assetId The index position / identifier of the asset | |
/// @return existing status of the general informaiton, existing status of the location informaiton and where the asset-structs exists | |
function getExistStatus(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns (bool general, bool location, bool asset) | |
{ | |
Asset memory a = assets[_assetId]; | |
return(a.general.exists && a.producingProps.capacityWh > 0, a.location.exists, a.exists); | |
} | |
/// @notice function to get the last smartmeter-reading of an asset | |
/// @param _assetId the id belonging to the asset | |
/// @return the last smartmeter-reading | |
function getLastSmartMeterRead(uint _assetId) | |
onlyOwner | |
external | |
returns (uint) | |
{ | |
return assets[_assetId].general.lastSmartMeterReadWh; | |
} | |
/// @notice Gets the last CO2-offset read of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the last logged CO2-offset read tru | |
function getlastSmartMeterCO2OffsetRead(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns (uint) | |
{ | |
return assets[_assetId].producingProps.lastSmartMeterCO2OffsetRead; | |
} | |
/// @notice gets the timestamp of the last reading | |
/// @param _assetId the Id belonging to an entry in the asset registry | |
/// @return the timestamp of the last reading | |
function getLastSmartMeterReadDate(uint _assetId) | |
onlyOwner | |
external | |
returns(uint) | |
{ | |
return assets[_assetId].general.lastMeterReadReceived; | |
} | |
/// @notice Gets last smart merter read file hash | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return last smart merter read file hash | |
function getLastSmartMeterReadFileHash(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(bytes32) | |
{ | |
return assets[_assetId].general.lastSmartMeterReadFileHash; | |
} | |
/// @notice Gets the last smart merter read in Wh of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the last loged smart meter read in Wh | |
function getLastSmartMeterReadWh(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].general.lastSmartMeterReadWh; | |
} | |
/// @notice Gets the location country of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @return country where the asset is based | |
function getLocationCountry(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(bytes32) | |
{ | |
return assets[_assetId].location.country; | |
} | |
/// @notice Gets the location region of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @return region of the country where the asset is based | |
function getLocationRegion(uint _assetId) | |
onlyOwner | |
external | |
view | |
returns(bytes32) | |
{ | |
return assets[_assetId].location.region; | |
} | |
/// @notice Gets the operational since field of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
function getOperationalSince(uint _assetId) | |
external | |
onlyOwner | |
view | |
returns(uint) | |
{ | |
return assets[_assetId].general.operationalSince; | |
} | |
/// @notice Gets the owner of an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the owner address | |
function getOwner(uint _assetId) | |
external | |
onlyOwner | |
view | |
returns(address) | |
{ | |
return assets[_assetId].general.owner; | |
} | |
/// @notice Gets the smart meter address belonging to an entry in the asset registry | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @return the smart meter address | |
function getSmartMeter(uint _assetId) | |
external | |
onlyOwner | |
view | |
returns(address) | |
{ | |
return assets[_assetId].general.smartMeter; | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Jonas Bentke, [email protected] | |
/// @title The logic contract for the asset registration | |
/// @notice This contract provides the logic that determines how the data is stored | |
/// @dev Needs a valid AssetProducingRegistryDB contract to function correctly | |
contract AssetProducingRegistryLogic is AssetLogic { | |
event LogNewMeterRead(uint indexed _assetId, bytes32 indexed _fileHash, uint _oldMeterRead, uint _newMeterRead, bool _smartMeterDown, uint _certificatesCreatedForWh, uint _oldCO2OffsetReading, uint _newCO2OffsetReading, bool _serviceDown); | |
enum AssetType { | |
Wind, | |
Solar, | |
RunRiverHydro, | |
BiomassGas | |
} | |
enum Compliance{ | |
none, | |
IREC, | |
EEC, | |
TIGR | |
} | |
/// @notice Constructor | |
/// @param _cooContract The address of the coo contract | |
function AssetProducingRegistryLogic(CoO _cooContract) | |
public | |
AssetLogic(_cooContract) | |
{ | |
} | |
/// @notice Sets the general information of an asset in the database | |
/// @param _assetId the The index / identifier of an asset | |
/// @param _smartMeter The address of the smart meter | |
/// @param _owner The address of the asset owner | |
/// @param _operationalSince the timestamp of when the asset was activated for production | |
/// @param _active true if active | |
function initGeneral( | |
uint _assetId, | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
bool _active | |
) | |
external | |
isInitialized | |
userHasRole(RoleManagement.Role.AssetManager, _owner) | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
{ | |
AssetProducingRegistryDB((db)).initGeneral(_assetId, _smartMeter, _owner, _operationalSince,0, _active, 0x0); | |
updateAssetExistStatus(_assetId); | |
} | |
/// @notice sets the producing properties of an asset | |
/// @param _assetId the id belonging to an asset | |
/// @param _assetType the asset-type | |
/// @param _capacityWh the capacity of the asset | |
/// @param _registryCompliance the compliance | |
/// @param _otherGreenAttributes other green attributes | |
/// @param _typeOfPublicSupport type of public support | |
function initProducingProperties( | |
uint _assetId, | |
AssetType _assetType, | |
uint _capacityWh, | |
Compliance _registryCompliance, | |
bytes32 _otherGreenAttributes, | |
bytes32 _typeOfPublicSupport | |
) | |
external | |
isInitialized | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
{ | |
AssetProducingRegistryDB((db)).initProducing(_assetId, uint(_assetType), 0, 0, _capacityWh, 0, uint(_registryCompliance), _otherGreenAttributes, _typeOfPublicSupport); | |
updateAssetExistStatus(_assetId); | |
} | |
/// @notice Logs meter read | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _newMeterRead The current meter read of the asset | |
/// @param _smartMeterDown flag if there was an error with the smart meter | |
/// @param _lastSmartMeterReadFileHash Last meter read file hash | |
/// @param _CO2OffsetServiceDown flag if there was an error with the co2-offset-server | |
/// @param _CO2OffsetMeterRead The new CO2-offset reading | |
/// @dev The client needs to check if the blockgas limit could be reached and if so the log should be splitted | |
function saveSmartMeterRead( | |
uint _assetId, | |
uint _newMeterRead, | |
bool _smartMeterDown, | |
bytes32 _lastSmartMeterReadFileHash, | |
uint _CO2OffsetMeterRead, | |
bool _CO2OffsetServiceDown | |
) | |
external | |
isInitialized | |
onlyAccount(AssetProducingRegistryDB(db).getSmartMeter(_assetId)) | |
{ | |
require(db.getActive(_assetId)); | |
LogNewMeterRead(_assetId, _lastSmartMeterReadFileHash, AssetProducingRegistryDB(db).getLastSmartMeterReadWh(_assetId), _newMeterRead, _smartMeterDown, AssetProducingRegistryDB(db).getCertificatesCreatedForWh(_assetId), AssetProducingRegistryDB(db).getlastSmartMeterCO2OffsetRead(_assetId), _CO2OffsetMeterRead, _CO2OffsetServiceDown); | |
/// @dev need to check if new meter read is higher then the old one | |
AssetProducingRegistryDB(address(db)).setSmartMeterReadData(_assetId, _newMeterRead, _CO2OffsetMeterRead, _lastSmartMeterReadFileHash, now); | |
} | |
/// @notice function to set the amount of CO2 used for certificates | |
/// @param _assetId the assetId | |
/// @param _co2 the amount of CO2 saved | |
function setCO2UsedForCertificate(uint _assetId, uint _co2) | |
external | |
isInitialized | |
onlyAccount(address(cooContract.certificateRegistry())) | |
{ | |
uint currentCO = AssetProducingRegistryDB(address(db)).getCo2UsedForCertificate(_assetId); | |
uint fullCO = AssetProducingRegistryDB(address(db)).getlastSmartMeterCO2OffsetRead(_assetId); | |
uint temp = currentCO + _co2; | |
assert(temp >= currentCO); | |
// we have to check that we can only account that amount of CO2 that was actually saved | |
require(temp <= fullCO); | |
AssetProducingRegistryDB(address(db)).setCO2UsedForCertificate(_assetId, temp); | |
} | |
/// @notice increases the amount of wh used for the creation of certificates | |
/// @param _assetId The id belonging to an entry in the asset registry | |
/// @param _whUsed The amount of wh that is about to be used for a new certificate | |
function useWhForCertificate(uint _assetId, uint _whUsed) | |
external | |
isInitialized | |
onlyAccount(address(cooContract.certificateRegistry())) | |
returns(bool) | |
{ | |
uint temp = AssetProducingRegistryDB(address(db)).getCertificatesCreatedForWh(_assetId) + _whUsed; | |
require(AssetProducingRegistryDB(address(db)).getLastSmartMeterReadWh(_assetId) >= temp); | |
AssetProducingRegistryDB(address(db)).setCertificatesCreatedForWh(_assetId, temp); | |
return true; | |
} | |
/// @notice Gets the general information of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @return the general information of an asset | |
function getAssetGeneral(uint _assetId) | |
external | |
view | |
returns( | |
address _smartMeter, | |
address _owner, | |
uint _operationalSince, | |
uint _lastSmartMeterReadWh, | |
bool _active, | |
bytes32 _lastSmartMeterReadFileHash | |
) | |
{ | |
return AssetProducingRegistryDB(address(db)).getAssetGeneral(_assetId); | |
} | |
/// @notice get the producing properties of an asset | |
/// @param _assetId the id belonging to an entry in the asset registry | |
/// @return the producing properties | |
function getAssetProducingProperties(uint _assetId) | |
external | |
view | |
returns( | |
uint assetType, | |
uint capacityWh, | |
uint certificatesCreatedForWh, | |
uint lastSmartMeterCO2OffsetRead, | |
uint cO2UsedForCertificate, | |
uint registryCompliance, | |
bytes32 otherGreenAttributes, | |
bytes32 typeOfPublicSupport | |
) | |
{ | |
return AssetProducingRegistryDB(address(db)).getAssetProducingProperties(_assetId); | |
} | |
/// @notice Function to get the Asset-Type | |
/// @dev The asset-type gets converted from unsigned integer to an Asset-type enum, can still be accessed as uint | |
/// @param _assetId The identifier / index of an asset | |
/// @return AssetType as enum | |
function getAssetType(uint _assetId) | |
external | |
view | |
returns( | |
AssetType | |
) | |
{ | |
return AssetType(AssetProducingRegistryDB(address(db)).getAssetType(_assetId)); | |
} | |
/// @notice function to get the compliance | |
/// @param _assetId the assetId | |
/// @return the compliance | |
function getCompliance(uint _assetId) | |
external | |
view | |
returns (Compliance c) | |
{ | |
var ( , , , , , ctemp, , ) = AssetProducingRegistryDB(address(db)).getAssetProducingProperties(_assetId); | |
c = Compliance(ctemp); | |
} | |
/// @notice Function to get the amount of already used CO2 for creating certificates | |
/// @param _assetId The identifier / index of an asset | |
/// @return the amount of already used CO2 for creating certificates | |
function getCo2UsedForCertificate(uint _assetId) | |
external | |
view | |
returns (uint) | |
{ | |
return AssetProducingRegistryDB(address(db)).getCo2UsedForCertificate(_assetId); | |
} | |
/// @notice function to calculated how much CO2-offset can be used for a certificate | |
/// @param _assetId The identifier / index of an asset | |
/// @param _wh The amount of wh produced | |
/// @return amount of CO2-offset used for a certificate | |
function getCoSaved(uint _assetId, uint _wh) external view returns(uint) { | |
uint lastRead = AssetProducingRegistryDB(address(db)).getLastSmartMeterReadWh(_assetId); | |
uint lastUsedWh = AssetProducingRegistryDB(address(db)).getCertificatesCreatedForWh(_assetId); | |
uint availableWh = lastRead - lastUsedWh; | |
// we have to check for an underflow and if there are even availale Wh | |
assert(lastUsedWh <= lastRead); | |
if (availableWh == 0) return 0; | |
uint coRead = AssetProducingRegistryDB(address(db)).getlastSmartMeterCO2OffsetRead(_assetId); | |
uint coUsed = AssetProducingRegistryDB(address(db)).getCo2UsedForCertificate(_assetId); | |
uint availableCo = coRead - coUsed; | |
assert(coUsed <= coRead); | |
return (availableCo*((_wh*1000000)/availableWh))/1000000; | |
} | |
/// @notice returns whether an asset exists | |
/// @param _assetId The identifier of an asset | |
/// @return bool if asset exists, false if some information are missing | |
function getExistStatus(uint _assetId) external view returns (bool) { | |
var (general, location, asset) = db.getExistStatus(_assetId); | |
return (general && location && asset); | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Jonas Bentke, [email protected] | |
/// @title The Database contract for the Certificate of Origin list | |
/// @notice This contract only provides getter and setter methods | |
contract CertificateDB is Owned { | |
struct Certificate { | |
uint assetId; | |
address owner; | |
uint powerInW; | |
bool retired; | |
bytes32 dataLog; | |
uint coSaved; | |
address escrow; | |
uint creationTime; | |
} | |
/// @notice An array containing all created certificates | |
Certificate[] private certificateList; // why is it private read? People can still read it, just not use from within a smart contract (even there it is possible) | |
/// @notice Constructor | |
/// @param _certificateLogic The address of the corresbonding logic contract | |
function CertificateDB(address _certificateLogic) Owned(_certificateLogic) public { | |
} | |
/// @notice Creates a new certificate | |
/// @param _assetId The id of the Certificate | |
/// @param _owner The owner of the Certificate | |
/// @param _powerInW The amount of Watts the Certificate holds | |
/// @return The id of the certificate | |
function createCertificate(uint _assetId, address _owner, uint _powerInW, bytes32 _dataLog, uint _coSaved, address _escrow) public onlyOwner returns (uint _certId) { | |
_certId = certificateList.length; | |
certificateList.push(Certificate(_assetId, _owner, _powerInW, false, _dataLog, _coSaved, _escrow, now)); | |
} | |
/// @notice sets the escrow-address of a certificate | |
/// @param _certificateId certificateId | |
/// @param _escrow new escrow-address | |
function setCertificateEscrow(uint _certificateId, address _escrow) | |
public | |
onlyOwner | |
{ | |
certificateList[_certificateId].escrow = _escrow; | |
} | |
/// @notice Sets the owner of a certificate | |
/// @param _certificateId The array position in which the certificate is stored | |
/// @param _owner The address of the new owner | |
function setCertificateOwner(uint _certificateId, address _owner) public onlyOwner { | |
certificateList[_certificateId].owner = _owner; | |
} | |
/// @notice Sets a certificate to retired | |
/// @param _certificateId The array position in which the certificate is stored | |
function retireCertificate(uint _certificateId) public onlyOwner { | |
certificateList[_certificateId].retired = true; | |
} | |
/// @notice Returns the certificate that corresponds to the given array id | |
/// @param _certificateId The array position in which the certificate is stored | |
/// @return all elements of the certificate | |
function getCertificate(uint _certificateId) | |
public | |
view | |
returns ( | |
uint _assetId, | |
address _owner, | |
uint _powerInW, | |
bool _retired, | |
bytes32 _dataLog, | |
uint _coSaved, | |
address _escrow, | |
uint _creationTime | |
) | |
{ | |
Certificate memory c = certificateList[_certificateId]; | |
_assetId = c.assetId; | |
_owner = c.owner; | |
_powerInW = c.powerInW; | |
_retired = c.retired; | |
_dataLog = c.dataLog; | |
_coSaved = c.coSaved; | |
_escrow = c.escrow; | |
_creationTime = c.creationTime; | |
} | |
/// @notice Returns the certificate owner | |
/// @param _certificateId The array position in which the certificate is stored | |
/// @return address owner | |
function getCertificateOwner(uint _certificateId) | |
public | |
onlyOwner | |
view | |
returns (address) | |
{ | |
return certificateList[_certificateId].owner; | |
} | |
/// @notice Getter for state of retirement | |
/// @param _certificateId The id of the requested certificate | |
/// @return bool if it is retired | |
function isRetired(uint _certificateId) | |
public | |
onlyOwner | |
view | |
returns (bool) | |
{ | |
return certificateList[_certificateId].retired; | |
} | |
/// @notice function to get the amount of all certificates | |
/// @return the amount of all certificates | |
function getCertificateListLength() | |
public | |
onlyOwner | |
view | |
returns (uint) | |
{ | |
return certificateList.length; | |
} | |
/// @notice function to get the escrow-address of a certificate | |
/// @param _certificateId certificate-ID | |
/// @return escrow-address | |
function getCertificateEscrow(uint _certificateId) | |
public | |
onlyOwner | |
view | |
returns (address) | |
{ | |
return certificateList[_certificateId].escrow; | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Jonas Bentke, [email protected] | |
/// @title The logic contract for the Certificate of Origin list | |
/// @notice This contract provides the logic that determines how the data is stored | |
/// @dev Needs a valid CertificateDB contract to function correctly | |
contract CertificateLogic is RoleManagement, Updatable { | |
///@notice The address of a CertificateDB contract | |
CertificateDB public certificateDb; | |
/// @notice Logs the creation of an event | |
event LogCreatedCertificate(uint indexed _certificateId, uint powerInW, address owner, address escrow); | |
/// @notice Logs the request of an retirement of a certificate | |
event LogRetireRequest(uint indexed _certificateId, bool _retire); | |
event LogCertificateOwnerChanged(uint indexed _certificateId, address _oldOwner, address _newOwner, address _oldEscrow, address _newEscrow); | |
/// @notice Checks if the contract is initialized | |
modifier isInitialized() { | |
require(certificateDb != CertificateDB(0x0)); | |
_; | |
} | |
/// @notice Constructor | |
/// @param _coo The Master contract | |
function CertificateLogic(CoO _coo) RoleManagement(_coo) public { | |
} | |
/// @notice Initialises the contract by binding it to a logic contract | |
/// @param _database Sets the logic contract | |
function init(address _database) public onlyRole(RoleManagement.Role.TopAdmin) { | |
require(certificateDb == CertificateDB(0x0)); | |
certificateDb = CertificateDB(_database); | |
} | |
/// @notice Creates a certificate of origin. Checks in the AssetRegistry if requested wh are available. | |
/// @param _assetId The id of the Certificate | |
/// @param _owner The owner of the Certificate | |
/// @param _powerInW The amount of Watts the Certificate holds | |
function createCertificate(uint _assetId, address _owner, uint _powerInW) | |
public | |
isInitialized | |
onlyAccount(address(cooContract.demandRegistry()) ) | |
returns (uint) | |
{ | |
return createCertificateIntern(_assetId, _owner, _powerInW, 0x0); | |
} | |
/// @notice Creates a certificate of origin. Checks in the AssetRegistry if requested wh are available. | |
/// @param _assetId The id of the Certificate | |
/// @param _owner The owner of the Certificate | |
/// @param _powerInW The amount of Watts the Certificate holds | |
/// @param _escrow The escrow of a certificate | |
/// @return a certificate-id | |
function createCertificateIntern(uint _assetId, address _owner, uint _powerInW, address _escrow) | |
internal | |
isInitialized | |
returns (uint) | |
{ | |
uint co = AssetProducingRegistryLogic(address(cooContract.assetProducingRegistry())).getCoSaved(_assetId, _powerInW); | |
require(AssetProducingRegistryLogic(address(cooContract.assetProducingRegistry())).useWhForCertificate(_assetId, _powerInW)); | |
bytes32 dataLog = AssetProducingRegistryLogic(address(cooContract.assetProducingRegistry())).getLastSmartMeterReadFileHash(_assetId); | |
uint certId = certificateDb.createCertificate(_assetId, _owner, _powerInW, dataLog, co, _escrow); | |
LogCreatedCertificate(certId, _powerInW, _owner, _escrow); | |
AssetProducingRegistryLogic(address(cooContract.assetProducingRegistry())).setCO2UsedForCertificate(_assetId,co); | |
return certId; | |
} | |
/// @notice Creates a certificate of origin for the asset owner. Checks in the AssetRegistry if requested wh are available. | |
/// @dev the msg.sender (a matcher) will become the escrow-of that certificate and is allowed to change the change the ownership | |
/// @param _assetId The id of the Certificate | |
/// @param _powerInW The amount of Watts the Certificate holds | |
/// @return the certificate-id | |
function createCertificateForAssetOwner(uint _assetId, uint _powerInW) | |
public | |
onlyRole(RoleManagement.Role.Matcher) | |
isInitialized | |
returns (uint) | |
{ | |
require( AssetProducingRegistryLogic(address(cooContract.assetProducingRegistry())).getExistStatus(_assetId)); | |
var ( , ownerAddress, , , , ) = AssetProducingRegistryLogic(address(cooContract.assetProducingRegistry())).getAssetGeneral(_assetId); | |
return createCertificateIntern(_assetId, ownerAddress, _powerInW, msg.sender); | |
} | |
/// @notice Request a certificate to retire. Only Certificate owner can retire | |
/// @param _id The id of the certificate | |
function retireCertificate(uint _id) | |
public | |
isInitialized | |
{ | |
var (, owner, , retired,, ,,) = certificateDb.getCertificate(_id); | |
require(owner == msg.sender); | |
if (!retired) { | |
certificateDb.setCertificateEscrow(_id, 0x0); | |
certificateDb.retireCertificate(_id); | |
LogRetireRequest(_id, true); | |
} | |
} | |
/// @notice function to allow an escrow-address to change the ownership of a certificate | |
/// @dev this function can only be called by the demandLogic | |
/// @param _id the certificate-id | |
/// @param _newOwner the new owner of the certificate | |
function transferOwnershipByEscrow(uint _id, address _newOwner) | |
public | |
isInitialized | |
onlyAccount(address(cooContract.demandRegistry()) ) | |
{ | |
address oldOwner; | |
bool retired; | |
address oldEscrow; | |
( ,oldOwner,,retired,,,oldEscrow,) = certificateDb.getCertificate(_id); | |
require(!retired); | |
certificateDb.setCertificateOwner(_id, _newOwner); | |
certificateDb.setCertificateEscrow(_id, 0x0); | |
LogCertificateOwnerChanged(_id, oldOwner, _newOwner, oldEscrow, 0x0); | |
} | |
/// @notice Sets a new owner for the certificate | |
/// @param _id The id of the certificate | |
/// @param _newOwner The address of the new owner of the certificate | |
function changeCertificateOwner(uint _id, address _newOwner) | |
public | |
isInitialized() | |
userExists(_newOwner) | |
{ | |
require(msg.sender == certificateDb.getCertificateOwner(_id) && !(certificateDb.isRetired(_id))); | |
certificateDb.setCertificateOwner(_id, _newOwner); | |
address oldOwner = certificateDb.getCertificateOwner(_id); | |
address oldEscrow = certificateDb.getCertificateEscrow(_id); | |
LogCertificateOwnerChanged(_id, oldOwner, _newOwner, oldEscrow, oldEscrow); | |
} | |
/// @notice Getter for a specific Certificate | |
/// @param _certificateId The id of the requested certificate | |
/// @return the certificate as single values | |
function getCertificate(uint _certificateId) | |
public | |
view | |
returns ( | |
uint _assetId, | |
address _owner, | |
uint _powerInW, | |
bool _retired, | |
bytes32 _dataLog, | |
uint _coSaved, | |
address _escrow, | |
uint _creationTime | |
) | |
{ | |
return certificateDb.getCertificate(_certificateId); | |
} | |
/// @notice Getter for a specific Certificate | |
/// @param _certificateId The id of the requested certificate | |
/// @return the certificate as single values | |
function getCertificateOwner(uint _certificateId) | |
public | |
view | |
returns (address) | |
{ | |
return certificateDb.getCertificateOwner(_certificateId); | |
} | |
/// @notice Getter for a specific Certificate | |
/// @param _certificateId The id of the requested certificate | |
/// @return the certificate as single values | |
function isRetired(uint _certificateId) | |
public | |
view | |
returns (bool) | |
{ | |
return certificateDb.isRetired(_certificateId); | |
} | |
/// @notice Getter for the length of the list of certificates | |
/// @return the length of the array | |
function getCertificateListLength() | |
public | |
view | |
returns (uint) | |
{ | |
return certificateDb.getCertificateListLength(); | |
} | |
/// @notice Updates the logic contract | |
/// @param _newLogic Address of the new logic contract | |
function update(address _newLogic) | |
external | |
onlyAccount(address(cooContract)) | |
{ | |
require(address(cooContract) == msg.sender); | |
certificateDb.changeOwner(_newLogic); | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title Contract for storing the current logic-contracts-addresses for the certificate of origin | |
contract CoO is Owned { | |
event LogUserRegistryUpdated(address _old, address _new); | |
event LogAssetProducingRegistryUpdated(address _old, address _new); | |
event LogCertificateRegistryUpdated(address _old, address _new); | |
event LogDemandRegistryUpdated(address _old, address _new); | |
event LogAssetConsumingRegistryUpdated(address _old, address _new); | |
Updatable public userRegistry; | |
Updatable public assetProducingRegistry; | |
Updatable public certificateRegistry; | |
Updatable public demandRegistry; | |
Updatable public assetConsumingRegistry; | |
/// @notice The constructor of the UserDB | |
function CoO() | |
Owned(msg.sender) | |
public | |
{ | |
} | |
/// @notice function to initialize the contracts, setting the needed contract-addresses | |
/// @param _userRegistry user-registry logic contract address | |
/// @param _assetProducingRegistry producing-asset-registry logic contract address | |
/// @param _certificateRegistry certificate-registry logic contract address | |
/// @param _demandRegistry demand-registry logic contract address | |
/// @param _assetConsumingRegistry consuming-asset-registry logic contract address | |
function init( | |
Updatable _userRegistry, | |
Updatable _assetProducingRegistry, | |
Updatable _certificateRegistry, | |
Updatable _demandRegistry, | |
Updatable _assetConsumingRegistry | |
) | |
onlyOwner | |
external | |
{ | |
require( | |
_userRegistry != address(0) && _assetProducingRegistry != address(0) && _certificateRegistry != address(0) && _demandRegistry != address(0) && _assetConsumingRegistry != address(0) | |
&& userRegistry == address(0) && assetProducingRegistry == address(0) && certificateRegistry == address(0) && demandRegistry == address(0) && assetConsumingRegistry == address(0) | |
); | |
userRegistry = _userRegistry; | |
assetProducingRegistry = _assetProducingRegistry; | |
certificateRegistry = _certificateRegistry; | |
demandRegistry = _demandRegistry; | |
assetConsumingRegistry = _assetConsumingRegistry; | |
} | |
/// @notice function to update one or more logic-contracts | |
/// @param _userRegistry address of the new user-registry-logic-contract | |
/// @param _assetProducingRegistry address of the new asset-registry-logic-contract | |
/// @param _certificateRegistry address of the new certificate-registry-logic-contract | |
/// @param _demandRegistry demand-registry logic contract address | |
/// @param _assetConsumingRegistry consuming-asset-registry logic contract address | |
function update( | |
Updatable _userRegistry, | |
Updatable _assetProducingRegistry, | |
Updatable _certificateRegistry, | |
Updatable _demandRegistry, | |
Updatable _assetConsumingRegistry | |
) | |
onlyOwner | |
external | |
{ | |
if (_userRegistry != address(0)) { | |
LogUserRegistryUpdated(userRegistry, _userRegistry); | |
userRegistry.update(_userRegistry); | |
userRegistry = _userRegistry; | |
} | |
if (_assetProducingRegistry != address(0)) { | |
LogAssetProducingRegistryUpdated(assetProducingRegistry, _assetProducingRegistry); | |
assetProducingRegistry.update(_assetProducingRegistry); | |
assetProducingRegistry = _assetProducingRegistry; | |
} | |
if (_certificateRegistry != address(0)) { | |
LogCertificateRegistryUpdated(certificateRegistry, _certificateRegistry); | |
certificateRegistry.update(_certificateRegistry); | |
certificateRegistry = _certificateRegistry; | |
} | |
if (_demandRegistry != address(0)) { | |
LogDemandRegistryUpdated(demandRegistry, _demandRegistry); | |
demandRegistry.update(_demandRegistry); | |
demandRegistry = _demandRegistry; | |
} | |
if(_assetConsumingRegistry != address(0)) { | |
LogAssetConsumingRegistryUpdated(assetConsumingRegistry, _assetConsumingRegistry); | |
assetConsumingRegistry.update(_assetConsumingRegistry); | |
assetConsumingRegistry = _assetConsumingRegistry; | |
} | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title The Database contract for the AgreementDB of Origin list | |
/// @notice This contract only provides getter and setter methods and only its logic-contract is able to call the functions | |
contract DemandDB is Owned { | |
/// @notice struct for all the data belonging to the matcher | |
struct MatcherProperties { | |
// how many Wh per Period | |
uint targetWhPerperiod; | |
// amount of Wh the demand has already received | |
uint currentWhPerperiod; | |
uint certInCurrentperiod; | |
uint productionLastSetInPeriod; | |
// simple address of privateKey-keypair | |
address matcher; | |
} | |
/// @notice struct for all the information belonging to the coupling, can be 0 | |
struct Coupling { | |
uint producingAssets; | |
uint consumingAssets; | |
} | |
/// @notice struct for all the information that can affect a price | |
struct PriceDriving { | |
LocationDefinition.Location location; | |
uint registryCompliance; | |
uint assettype; | |
// proportion between CO2 and wh in percent (100 * CO2 / Wh) | |
uint minCO2Offset; | |
bytes32 otherGreenAttributes; | |
bytes32 typeOfPublicSupport; | |
bool isInitialized; | |
} | |
/// @notice struct for all the general information about a demand | |
struct GeneralInfo { | |
address originator; | |
address buyer; | |
uint startTime; | |
uint endTime; | |
uint timeframe; | |
uint pricePerCertifiedKWh; | |
uint currency; | |
} | |
/// @notice struct for gather all information | |
struct Demand { | |
GeneralInfo general; | |
Coupling couple; | |
PriceDriving priceDriving; | |
MatcherProperties matchProp; | |
bool enabled; | |
uint created; | |
uint demandMask; | |
} | |
GeneralInfo generalEmpty; | |
Coupling coupleEmpty; | |
PriceDriving priceDrivingEmpty; | |
MatcherProperties matchPropEmpty; | |
/// @notice list with all currenty active Demands | |
uint[] private activeDemands; | |
/// @notice empty location struct for initializing, used to avoid compile warnings | |
LocationDefinition.Location private locationEmpty; | |
/// @notice list with all created demands | |
Demand[] private allDemands; | |
/// @notice Constructor | |
/// @param _owner The owner of the contract | |
function DemandDB(address _owner) | |
public | |
Owned(_owner) | |
{ | |
} | |
/// @notice function to add a demand to the activeDemands-array | |
/// @param _demandId hash-identifier of a demand | |
function addActiveDemand(uint _demandId) | |
external | |
onlyOwner | |
{ | |
activeDemands.push(_demandId); | |
} | |
/// @notice function to create a coupling | |
/// @param _demandId identifier | |
/// @param _prodAssets array with assets that are allowed to produce energy for this agreement | |
/// @param _consAssets array with assets that are allowed to consume energy for this agreement | |
function createCoupling( | |
uint _demandId, | |
uint _prodAssets, | |
uint _consAssets | |
) | |
external | |
onlyOwner | |
{ | |
Demand storage d = allDemands[_demandId]; | |
Coupling storage c = d.couple; | |
c.producingAssets = _prodAssets; | |
c.consumingAssets = _consAssets; | |
} | |
/// @notice function to create an empty demand | |
/// @param _mask bitmask with the demand properties | |
/// @return the index and thus the identifier of a demand | |
function createEmptyDemand(uint _mask) | |
external | |
onlyOwner | |
returns (uint _demandId) | |
{ | |
_demandId = allDemands.length; | |
allDemands.push(Demand({ | |
general: generalEmpty, | |
couple: coupleEmpty, | |
priceDriving: priceDrivingEmpty, | |
matchProp: matchPropEmpty, | |
enabled: false, | |
created : 0, | |
demandMask: _mask | |
})); | |
} | |
/// @notice function to create the general informations of a demand | |
/// @param _demandId identifier | |
/// @param _originator producer of energy | |
/// @param _buyer buyer of a certiface, can be 0x0 | |
/// @param _startTime eariest accepted certificates | |
/// @param _endTime latest accepted certificates | |
/// @param _timeframe the timeframe for the demand | |
/// @param _pricePerCertifiedKWh price per certified kWh | |
/// @param _currency currency the originator wants to be paid with | |
function createGeneralDemand( | |
uint _demandId, | |
address _originator, | |
address _buyer, | |
uint _startTime, | |
uint _endTime, | |
uint _timeframe, | |
uint _pricePerCertifiedKWh, | |
uint _currency | |
) | |
external | |
onlyOwner | |
{ | |
Demand storage d = allDemands[_demandId]; | |
GeneralInfo storage g = d.general; | |
g.originator = _originator; | |
g.buyer = _buyer; | |
g.startTime = _startTime; | |
g.endTime = _endTime; | |
g.timeframe = _timeframe; | |
g.pricePerCertifiedKWh = _pricePerCertifiedKWh; | |
g.currency = _currency; | |
} | |
/// @notice function to create the matching-properties | |
/// @param _demandId identifier | |
/// @param _WhAmountPerperiod the desired amount of Wh per period | |
/// @param _currentWhPerperiod the current amount of Wh | |
/// @param _certInCurrentperiod the amount of certificates created in the current period | |
/// @param _productionLastSetInPeriod the last period where the consumption was set | |
/// @param _matcher account of the javaScript-matcher | |
function createMatchProperties( | |
uint _demandId, | |
uint _WhAmountPerperiod, | |
uint _currentWhPerperiod, | |
uint _certInCurrentperiod, | |
uint _productionLastSetInPeriod, | |
address _matcher | |
) | |
external | |
onlyOwner | |
{ | |
Demand storage d = allDemands[_demandId]; | |
MatcherProperties storage m = d.matchProp; | |
m.targetWhPerperiod = _WhAmountPerperiod; | |
m.currentWhPerperiod = _currentWhPerperiod; | |
m.certInCurrentperiod = _certInCurrentperiod; | |
m.productionLastSetInPeriod = _productionLastSetInPeriod; | |
m.matcher = _matcher; | |
} | |
/// @notice function to create the pricedriving-factors of a demand | |
/// @param _demandId identifier | |
/// @param _country country the engery has to come from | |
/// @param _region region the energy has to come from | |
/// @param _zip zip code the energy has to come from | |
/// @param _street the streetname | |
/// @param _houseNumber the housenumber | |
/// @param _gpsLatitude latitude of coordinates | |
/// @param _gpsLongitude longitude of coordinates | |
/// @param _type fuel-tyoe | |
/// @param _minCO2Offset CO2-offset | |
/// @param _registryCompliance compliance | |
/// @param _otherGreenAttributes other green attributes | |
/// @param _typeOfPublicSupport type of public support | |
function createPriceDriving( | |
uint _demandId, | |
bytes32 _country, | |
bytes32 _region, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _street, | |
bytes32 _houseNumber, | |
bytes32 _gpsLatitude, | |
bytes32 _gpsLongitude, | |
uint _type, | |
uint _minCO2Offset, | |
uint _registryCompliance, | |
bytes32 _otherGreenAttributes, | |
bytes32 _typeOfPublicSupport | |
) | |
external | |
onlyOwner | |
{ | |
allDemands[_demandId].priceDriving.location = locationEmpty; | |
allDemands[_demandId].priceDriving.assettype = _type; | |
allDemands[_demandId].priceDriving.minCO2Offset = _minCO2Offset; | |
allDemands[_demandId].priceDriving.registryCompliance = _registryCompliance; | |
allDemands[_demandId].priceDriving.otherGreenAttributes = _otherGreenAttributes; | |
allDemands[_demandId].priceDriving.typeOfPublicSupport = _typeOfPublicSupport; | |
setDemandLocation(_demandId,_country,_region,_zip,_city,_street, _houseNumber, _gpsLatitude, _gpsLongitude); | |
allDemands[_demandId].priceDriving.isInitialized = true; | |
} | |
/// @notice function to remove an entry in the activeDemands-array | |
/// @param _demandId the index position of the full demand in the allDemands-array | |
/// @param _from the start-index to search for the demandID | |
/// @param _to the end-index to search for the demandID | |
/// @dev due to the design the order of elements in the array will change when removing an element! | |
function removeActiveDemand(uint _demandId, uint _from, uint _to) | |
external | |
onlyOwner | |
returns (bool _success) | |
{ | |
/* | |
uint end = _to < activeDemands.length ? _to : activeDemands.length-1; | |
for (uint i = _from; i < end; i++) { | |
if ( activeDemands[i] == _demandId) { | |
activeDemands[i] = activeDemands[activeDemands.length-1]; | |
activeDemands.length--; | |
return _success; | |
} | |
}*/ | |
var (found, index) = searchForDemand(_demandId, _from, _to); | |
if(found){ | |
activeDemands[index] = activeDemands[activeDemands.length-1]; | |
activeDemands.length--; | |
} | |
return found; | |
} | |
/// @notice function to set the creation-time of a demand | |
/// @param _demandId identifier | |
/// @param _time creation-time | |
function setDemandCreationTime(uint _demandId, uint _time) | |
external | |
onlyOwner | |
{ | |
allDemands[_demandId].created = _time; | |
} | |
/// @notice function to en- or disable a demand | |
/// @param _demandId identifier | |
/// @param _enabled flag if the demand should be enabled | |
function setEnabled(uint _demandId, bool _enabled) | |
external | |
onlyOwner | |
{ | |
Demand storage d = allDemands[_demandId]; | |
d.enabled = _enabled; | |
} | |
/// @notice function to update some matching parameters | |
/// @param _demandId identifier | |
/// @param _currentWhPerperiod the current amount of Wh | |
/// @param _certInCurrentperiod the amount of certificates created in the current period | |
/// @param _productionLastSetInPeriod the last period where the consumption was set | |
function updateMatchProperties( | |
uint _demandId, | |
uint _currentWhPerperiod, | |
uint _certInCurrentperiod, | |
uint _productionLastSetInPeriod | |
) | |
external | |
onlyOwner | |
{ | |
Demand storage d = allDemands[_demandId]; | |
MatcherProperties storage m = d.matchProp; | |
m.currentWhPerperiod = _currentWhPerperiod; | |
m.certInCurrentperiod = _certInCurrentperiod; | |
m.productionLastSetInPeriod = _productionLastSetInPeriod; | |
} | |
/// @notice function that returns if a demands exists | |
/// @param _demandId identifier | |
/// @return true if demand exists | |
function demandExists(uint _demandId) | |
onlyOwner | |
external | |
view | |
returns (bool) | |
{ | |
return allDemands[_demandId].enabled; | |
} | |
/// @notice function to get the hash-identifier of an active demand in the activeDemands-array | |
/// @param _demandId index of the element in the array | |
/// @return hash-identifier of an active demand | |
function getActiveDemandIdAt(uint _demandId) | |
external | |
onlyOwner | |
view | |
returns (uint) | |
{ | |
return activeDemands[_demandId]; | |
} | |
/// @notice function to retrieve the length of the activeDemands-array | |
/// @return the length of the activeDemands-array | |
function getActiveDemandListLength() | |
external | |
onlyOwner | |
view | |
returns (uint) | |
{ | |
return activeDemands.length; | |
} | |
/// @notice funtion to retrieve the length of the allDemands-array | |
/// @return the length of the allDemands-array | |
function getAllDemandListLength() | |
external | |
onlyOwner | |
view | |
returns (uint) | |
{ | |
return allDemands.length; | |
} | |
/// @notice function to get the information if the coupling-struct | |
/// @dev at the moment arrays can't be accessed in other contracts due to their dynamic length | |
/// @param _demandId identifier | |
/// @return used timeFrame, arrays of producing and consuming assets | |
function getDemandCoupling(uint _demandId) | |
external | |
onlyOwner | |
view | |
returns( | |
uint producingAssets, | |
uint consumingAssets | |
) | |
{ | |
Coupling memory s = allDemands[_demandId].couple; | |
return (s.producingAssets,s.consumingAssets); | |
} | |
/// @notice function to retrieve the general informations of a demand | |
/// @param _assetId identifier of the demand | |
/// @return the originator, buyer, startTime, endTime, currency, coupled | |
function getDemandGeneral(uint _assetId) | |
external | |
onlyOwner | |
view | |
returns( | |
address originator, | |
address buyer, | |
uint startTime, | |
uint endTime, | |
uint timeframe, | |
uint pricePerCertifiedKWh, | |
uint currency, | |
uint demandMask | |
) | |
{ | |
Demand memory d = allDemands[_assetId]; | |
GeneralInfo memory g = allDemands[_assetId].general; | |
return (g.originator, g.buyer, g.startTime, g.endTime, g.timeframe, g.pricePerCertifiedKWh, g.currency, d.demandMask); | |
} | |
/// @notice function to get the matcher-properties of a demand | |
/// @param _assetId identifier | |
/// @return amount of Wh per period, current Wh per period, certificates in current period, last period where a consumption was set and the matcher-address | |
function getDemandMatcherProperties(uint _assetId) | |
external | |
onlyOwner | |
view | |
returns ( | |
uint wHAmountPerperiod, | |
uint currentWhPerperiod, | |
uint certInCurrentperiod, | |
uint productionLastSetInPeriod, | |
address matcher | |
) | |
{ | |
MatcherProperties memory m = allDemands[_assetId].matchProp; | |
return (m.targetWhPerperiod, m.currentWhPerperiod, m.certInCurrentperiod, m.productionLastSetInPeriod, m.matcher); | |
} | |
/// @notice function to get the price-driving informations | |
/// @param _assetId identifier | |
/// @return location country and region, fueltype and CO2-offset | |
function getDemandPriceDriving(uint _assetId) | |
external | |
onlyOwner | |
view | |
returns ( | |
bytes32 locationCountry, | |
bytes32 locationRegion, | |
uint assettype, | |
uint minCO2Offset, | |
uint registryCompliance, | |
bytes32 _otherGreenAttributes, | |
bytes32 _typeOfPublicSupport, | |
bool isInitialized | |
) | |
{ | |
PriceDriving memory p = allDemands[_assetId].priceDriving; | |
return (p.location.country, p.location.region, p.assettype, p.minCO2Offset, p.registryCompliance, p.otherGreenAttributes, p.typeOfPublicSupport, p.isInitialized); | |
} | |
/// @notice gets the bitmask of a demand | |
/// @param _demandId the demand-id | |
/// @return bitmask with the set properties of a demand | |
function getDemandMask(uint _demandId) | |
external | |
onlyOwner | |
view | |
returns (uint) | |
{ | |
return allDemands[_demandId].demandMask; | |
} | |
/// @notice function to return the creationtime of the demand | |
/// @param _demandId identifier | |
/// @return blocktime of the creation of the demand | |
function getStartEpoche(uint _demandId) | |
external | |
onlyOwner | |
view | |
returns (uint) | |
{ | |
return allDemands[_demandId].created; | |
} | |
/// @notice Funtion to get the used timeframe for an demand | |
/// @param _assetId the asset-id | |
/// @dev will return an unsigned integer, that has to be converted to a timeframe in the logic-contract | |
/// @return the chosen timeframe for a demand | |
function getTimeFrame(uint _assetId) | |
public | |
onlyOwner | |
view | |
returns (uint) | |
{ | |
return allDemands[_assetId].general.timeframe; | |
} | |
/// @notice funciton to search for an active demands | |
/// @param _demandId the demandId to search for | |
/// @param _from starting index | |
/// @param _to ending index | |
/// @return returns true and index if an index was found, otherwise false and 0 | |
function searchForDemand( | |
uint _demandId, | |
uint _from, | |
uint _to | |
) | |
onlyOwner | |
public | |
view | |
returns (bool, uint) | |
{ | |
uint end = _to < activeDemands.length ? _to : activeDemands.length-1; | |
for(uint i = _from; i < end; i++){ | |
if(activeDemands[i] == _demandId) { | |
return (true,i); | |
} | |
} | |
} | |
/// @notice sets the demand Location | |
/// @dev internal helper function | |
/// @param _assetId identifier | |
/// @param _country country the engery has to come from | |
/// @param _region region the energy has to come from | |
/// @param _zip zip code the energy has to come from | |
/// @param _city the city the energy has to come from | |
/// @param _street the streetname | |
/// @param _houseNumber the housenumber the energy has to come from | |
/// @param _gpsLatitude latitude of coordinates | |
/// @param _gpsLongitude longitude of coordinates | |
function setDemandLocation( | |
uint _assetId, | |
bytes32 _country, | |
bytes32 _region, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _street, | |
bytes32 _houseNumber, | |
bytes32 _gpsLatitude, | |
bytes32 _gpsLongitude | |
) | |
internal | |
{ | |
allDemands[_assetId].priceDriving.location.country = _country; | |
allDemands[_assetId].priceDriving.location.region = _region; | |
allDemands[_assetId].priceDriving.location.zip = _zip; | |
allDemands[_assetId].priceDriving.location.city = _city; | |
allDemands[_assetId].priceDriving.location.street = _street; | |
allDemands[_assetId].priceDriving.location.houseNumber = _houseNumber; | |
allDemands[_assetId].priceDriving.location.gpsLatitude = _gpsLatitude; | |
allDemands[_assetId].priceDriving.location.gpsLongitude = _gpsLongitude; | |
allDemands[_assetId].priceDriving.location.exists = true; | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title The logic contract for the AgreementDB of Origin list | |
contract DemandLogic is RoleManagement, Updatable { | |
/// @notice database contract | |
DemandDB public db; | |
event createdEmptyDemand(address sender, uint indexed _demandId); | |
event LogDemandFullyCreated(uint indexed _demandId); | |
event LogDemandExpired(uint indexed _demandId); | |
event LogMatcherPropertiesUpdate(uint indexed _demandId, uint currentWhPerPeriod, uint certInCurrentPeriod, uint currentPeriod, uint certID); | |
enum TimeFrame{ | |
yearly, | |
monthly, | |
daily, | |
hourly | |
} | |
enum Currency{ | |
Euro, | |
USD, | |
SingaporeDollar, | |
Ether | |
} | |
/* | |
none: 0x0...0000000000 | |
originator: 0x0...---------1 | |
assetTyoe: 0x0...--------1- | |
complaince: 0x0...-------1-- | |
country: 0x0...------1--- | |
region: 0x0...-----1---- | |
minCO2: 0x0...----1----- | |
producing 0x0...---1------ | |
consuming 0x0...--1------- | |
otherGreenAttributes 0x0...-1-------- | |
typeOfPublicSupport 0x0...1--------- | |
*/ | |
enum DemandProperties { | |
originator, | |
assetType, | |
compliance, | |
country, | |
region, | |
minCO2, | |
producing, | |
consuming, | |
otherGreenAttributes, | |
typeOfPublicSupport | |
} | |
modifier isInitialized { | |
require((db) != address(0x0)); | |
_; | |
} | |
modifier doesNotExist(uint _demandId) { | |
require(!db.demandExists(_demandId)); | |
_; | |
} | |
/// @notice constructor | |
/// @param _cooContract coo-contract | |
function DemandLogic(CoO _cooContract) | |
public | |
RoleManagement(_cooContract) | |
{ | |
} | |
/// @notice Function to create an empty demand, functions initGeneralandCouplong, initMatcherProperties and initPricedriving have to be called in order to fully create a demandc | |
/// @param _properties array with the to be enabled demandproperties (see DemandProperties struct) | |
/// @dev will return an event with the event-Id | |
function createDemand(bool[] _properties) | |
external | |
isInitialized | |
onlyRole(RoleManagement.Role.AgreementAdmin) | |
{ | |
// if the 1st and the 6th property are set (originator and producing) we will abort because those properties are not allowed to be set at the same time | |
if(_properties[0] && _properties[6]) { | |
revert(); | |
} | |
require(_properties.length == 10); | |
uint demandID = db.createEmptyDemand(createDemandBitmask(_properties)); | |
createdEmptyDemand(msg.sender, demandID); | |
} | |
/// @notice fuction to set the database contract, can only be called once | |
/// @param _dbAddress address of the database contract | |
function init(DemandDB _dbAddress) | |
external | |
onlyRole(RoleManagement.Role.TopAdmin) | |
{ | |
require(address(db) == 0x0); | |
db = _dbAddress; | |
} | |
/// @notice function to create a demand and coupling of a new demand, should be called 1st | |
/// @param _demandId identifier | |
/// @param _originator address of an energy-producer, can be 0x0 | |
/// @param _buyer address oh the buyer | |
/// @param _startTime the starttime for a demand | |
/// @param _endTime the endtime for a demand | |
/// @param _tf timeFrame | |
/// @param _pricePerCertifiedKWh price per certified kWh | |
/// @param _currency currency to be used | |
/// @param _prodAsset array with producing assets, can be empty | |
/// @param _consAsset array with consuming assets, can be empty | |
function initGeneralAndCoupling( | |
uint _demandId, | |
address _originator, | |
address _buyer, | |
uint _startTime, | |
uint _endTime, | |
TimeFrame _tf, | |
uint _pricePerCertifiedKWh, | |
Currency _currency, | |
uint _prodAsset, | |
uint _consAsset | |
) | |
external | |
onlyRole(RoleManagement.Role.AgreementAdmin) | |
isInitialized | |
doesNotExist(_demandId) | |
{ | |
uint demandMask = db.getDemandMask(_demandId); | |
createGeneralDemandInternal(_demandId, _originator, _buyer, _startTime, _endTime, _tf, _pricePerCertifiedKWh, _currency); | |
createCouplingInternal(_demandId, _prodAsset, _consAsset, demandMask); | |
checkForFullDemand(_demandId); | |
} | |
/// @notice function to create the matcher-properties | |
/// @param _demandId identifier | |
/// @param _kWAmountPerPeriod amounts of KW per Period | |
/// @param _productionLastSetInPeriod todo: needed? | |
/// @param _matcher address of the matcher | |
function initMatchProperties( | |
uint _demandId, | |
uint _kWAmountPerPeriod, | |
uint _productionLastSetInPeriod, | |
address _matcher | |
) | |
external | |
onlyRole(RoleManagement.Role.AgreementAdmin) | |
isInitialized | |
doesNotExist(_demandId) | |
{ | |
require(isRole(RoleManagement.Role.Matcher,_matcher)); | |
db.createMatchProperties(_demandId, _kWAmountPerPeriod, 0, 0, _productionLastSetInPeriod, _matcher); | |
checkForFullDemand(_demandId); | |
} | |
/// @notice function to create a priceDriving-struct | |
/// @param _demandId identifier | |
/// @param _locationCountry country where the energy should be generated | |
/// @param _locationRegion region where the energy should be generated | |
/// @param _type fueltype | |
/// @param _minCO2Offset CO2-offset | |
/// @param _registryCompliance compliance | |
/// @param _otherGreenAttributes other green attributes | |
/// @param _typeOfPublicSupport type of public support | |
function initPriceDriving( | |
uint _demandId, | |
bytes32 _locationCountry, | |
bytes32 _locationRegion, | |
AssetProducingRegistryLogic.AssetType _type, | |
uint _minCO2Offset, | |
uint _registryCompliance, | |
bytes32 _otherGreenAttributes, | |
bytes32 _typeOfPublicSupport | |
) | |
external | |
isInitialized | |
{ | |
// we can't use modifier for this function due to the stack limitation. So we have to call the checkForDemandExist function that checks the requirements while bypassing the stacklimit | |
checkForDemandExist(_demandId); | |
db.createPriceDriving( _demandId, _locationCountry, _locationRegion, 0x0, 0x0, 0x0, 0, 0x0, 0x0, uint(_type), _minCO2Offset, _registryCompliance, _otherGreenAttributes, _typeOfPublicSupport); | |
checkForFullDemand(_demandId); | |
} | |
/// @notice function to match a certificate to a demand | |
/// @param _demandId the demand-id | |
/// @param _certificateId the id of a non retired certificate | |
function matchCertificate(uint _demandId, uint _certificateId) | |
external | |
isInitialized | |
{ | |
// we get all the needed data from a certificate | |
var(prodAssetId, , powerInW, retired, , coSaved, escrow, creationTime) = CertificateLogic(address(cooContract.certificateRegistry())).getCertificate(_certificateId); | |
// we accept only non retired certificates and they have to creates less then 1 year ago | |
// we also make sure that only the scrow-address (aka a matcher) is able to call this function | |
require(!retired && (creationTime + 365 days) >= now && msg.sender == escrow); | |
require(!hasDemandPropertySet(DemandProperties.consuming, db.getDemandMask(_demandId))); | |
// we're trying to match the certificate to a demand. If there is a non-match the function will revert | |
var (owner, currentWhPerPeriod, certInCurrentPeriod, currentPeriod) = matchInternal(_demandId, powerInW, prodAssetId, coSaved); | |
// at the end we have to update the matcher-properties | |
db.updateMatchProperties(_demandId, currentWhPerPeriod,certInCurrentPeriod, currentPeriod); | |
CertificateLogic(address(cooContract.certificateRegistry())).transferOwnershipByEscrow( _certificateId, owner); | |
LogMatcherPropertiesUpdate(_demandId, currentWhPerPeriod, certInCurrentPeriod, currentPeriod, _certificateId); | |
} | |
/// @notice function to check whether an active demand lies within the provided range | |
/// @param _demandId the demandId to search for | |
/// @param _from starting index | |
/// @param _to ending index | |
function searchForDemand( | |
uint _demandId, | |
uint _from, | |
uint _to | |
) | |
external | |
view | |
returns (bool _found, uint index) | |
{ | |
return db.searchForDemand(_demandId, _from, _to); | |
} | |
/// @notice function for internal matching, gets called by both matchDemand and matchCertificate | |
/// @param _demandId demandid | |
/// @param _wCreated amount of power created | |
/// @param _prodAssetId id of the producing-asset | |
/// @param _co2Saved amount of CO2-saved | |
/// @return the owner, the new (increased) amount of CurrentWhPerPeriod, the new (increased) amount of certificatesCreated per period and the current period | |
function matchInternal( | |
uint _demandId, | |
uint _wCreated, | |
uint _prodAssetId, | |
uint _co2Saved | |
) | |
internal | |
view | |
isInitialized | |
returns (address owner, uint currentWhPerPeriod, uint certInCurrentPeriod, uint currentPeriod) | |
{ | |
// we have to check if a demand with that identifier actually exists | |
var (generalExists, priceDrivingExists, matcherExists) = getExistStatus(_demandId); | |
require(generalExists && priceDrivingExists && matcherExists); | |
bool passCheck; | |
// we're comparing the demand-properties | |
(owner, passCheck,) = checkDemandGeneral(_demandId, _prodAssetId); | |
require(passCheck); | |
(passCheck,) = checkPriceDriving(_demandId, _prodAssetId, _wCreated, _co2Saved); | |
require(passCheck); | |
(currentWhPerPeriod,certInCurrentPeriod, currentPeriod,passCheck,) = checkMatcher(_demandId, _wCreated); | |
require(passCheck); | |
(passCheck,) = checkDemandCoupling(_demandId, _prodAssetId, _wCreated); | |
require(passCheck); | |
} | |
/// @notice Updates the logic contract | |
/// @param _newLogic Address of the new logic contract | |
function update(address _newLogic) | |
external | |
onlyAccount(address(cooContract)) | |
{ | |
db.changeOwner(_newLogic); | |
} | |
/// @notice funciton to retrieve the identifier-hash of an active demand | |
/// @param _demandId position in the array | |
/// @return identifier-hash | |
function getActiveDemandIdAt(uint _demandId) external isInitialized view returns (uint) { | |
return db.getActiveDemandIdAt(_demandId); | |
} | |
/// @notice function to return the length of the acticeDemands-array in the database | |
/// @return length if the activeDemands-array in the database | |
function getActiveDemandListLength() external isInitialized view returns (uint) { | |
return db.getActiveDemandListLength(); | |
} | |
/// @notice function to return the length of the allDemands-array in the database | |
/// @return length of the allDemansa-array | |
function getAllDemandListLength() external isInitialized view returns (uint) { | |
return db.getAllDemandListLength(); | |
} | |
/// @notice function to get the information if the coupling-struct | |
/// @param _demandId identifier | |
/// @return used timeFrame | |
function getDemandCoupling(uint _demandId) | |
external | |
view | |
isInitialized | |
returns( | |
uint producingAssets, | |
uint consumingAssets | |
) | |
{ | |
return db.getDemandCoupling(_demandId); | |
} | |
/// @notice function to retrieve the general informations of a demand | |
/// @param _demandId identifier of the demand | |
/// @return the originator, buyer, startTime, endTime, currency, coupled | |
function getDemandGeneral(uint _demandId) | |
external | |
isInitialized | |
view | |
returns ( | |
address originator, | |
address buyer, | |
uint startTime, | |
uint endTime, | |
uint timeframe, | |
uint pricePerCertifiedKWh, | |
uint currency, | |
uint demandMask | |
) | |
{ | |
return db.getDemandGeneral(_demandId); | |
} | |
/// @notice function to get the matcher-properties of a demand | |
/// @param _demandId identifier | |
/// @return amount of Wh per Period, current Wh per Period, certificates in current Period, last Period where a consumption was set and the matcher-address | |
function getDemandMatcherProperties(uint _demandId) | |
external | |
view | |
isInitialized | |
returns ( | |
uint targetWhPerPeriod, | |
uint currentWhPerPeriod, | |
uint certInCurrentPeriod, | |
uint productionLastSetInPeriod, | |
address matcher | |
) | |
{ | |
return db.getDemandMatcherProperties(_demandId); | |
} | |
/// @notice function to get the price-driving informations | |
/// @param _demandId identifier | |
/// @return location country and region, assettype, CO2-offset, compliance, green attributes and type of public support | |
function getDemandPriceDriving(uint _demandId) | |
external | |
view | |
isInitialized | |
returns ( | |
bytes32 locationCountry, | |
bytes32 locationRegion, | |
uint assettype, | |
uint minCO2Offset, | |
uint registryCompliance, | |
bytes32 _otherGreenAttributes, | |
bytes32 _typeOfPublicSupport, | |
bool isInit | |
) | |
{ | |
return db.getDemandPriceDriving(_demandId); | |
} | |
/// @notice function to get the existing status of the different demand-structs | |
/// @param _demandId identifier | |
/// @return returns existing of generalInformation, priceDriving and matcher-Properties | |
function getExistStatus(uint _demandId) | |
public | |
view | |
returns (bool general, bool priceDriving, bool matchProp) | |
{ | |
var(,buyer,,,,,,) = db.getDemandGeneral(_demandId); | |
general = (buyer != address(0)); | |
var(,,,,matcher) = db.getDemandMatcherProperties(_demandId); | |
matchProp = (matcher != address(0)); | |
(,,,,priceDriving) = db.getDemandPriceDriving(_demandId); | |
} | |
/// @notice funciton to remove an active demand, can only be successfully processed if the the endTime already passed | |
/// @param _demandId index of the demand in the activeDemands-array | |
/// @param _from index of the starting element | |
/// @param _to index of the end-element | |
function removeActiveDemand( | |
uint _demandId, | |
uint _from, | |
uint _to | |
) | |
public | |
{ | |
var ( , , , endTime, , , , ) = db.getDemandGeneral(_demandId); | |
require(endTime < now); | |
require(db.removeActiveDemand( _demandId, _from, _to)); | |
LogDemandExpired(_demandId); | |
} | |
/// @notice function to check the coupling properties of a demand | |
/// @param _demandId demand-Id | |
/// @param _prodAssetId production-asset id | |
/// @param _wCreated amount of Wh created | |
/// @return flag if the check was successfull and a string with the result | |
function checkDemandCoupling(uint _demandId, uint _prodAssetId, uint _wCreated) | |
public | |
view | |
returns (bool, string) | |
{ | |
var (prodAsset, consAsset ) = db.getDemandCoupling(_demandId); | |
if (hasDemandPropertySet(DemandProperties.producing, db.getDemandMask(_demandId))) { | |
if (_prodAssetId != prodAsset){ | |
return (false, "wrong prodAssetId"); | |
} | |
} | |
if (hasDemandPropertySet(DemandProperties.consuming, db.getDemandMask(_demandId))) { | |
var (capacityWh, maxCapacitySet, certificatesUsedForWh) = AssetConsumingRegistryLogic(address(cooContract.assetConsumingRegistry())).getConsumingProperies(consAsset); | |
if(maxCapacitySet){ | |
if(certificatesUsedForWh + _wCreated > capacityWh ){ | |
assert(capacityWh >= certificatesUsedForWh); | |
return (false, "too much energy for max capacity"); | |
} | |
} else { | |
var(wHAmountPerperiod, , , , ) = db.getDemandMatcherProperties(_demandId); | |
if(certificatesUsedForWh + _wCreated > wHAmountPerperiod) { | |
assert(wHAmountPerperiod >= certificatesUsedForWh); | |
return (false, "too much energy for for consuming target");} | |
} | |
} | |
return(true,""); | |
} | |
/// @notice function to check the fitting of the general-demand information with a matching | |
/// @param _demandId identifier | |
/// @param _prodAssetId asset-id that produced some energy | |
/// @return originator-address, coupled-flag, if there was an error and what check failed | |
function checkDemandGeneral(uint _demandId, uint _prodAssetId) | |
public | |
view | |
returns (address, bool, string) | |
{ | |
var ( originator, buyer, startTime, endTime, , , ,demandMask) = db.getDemandGeneral(_demandId); | |
var ( , owner, , , , ) = AssetProducingRegistryLogic(address(cooContract.assetProducingRegistry())).getAssetGeneral(_prodAssetId); | |
if(hasDemandPropertySet(DemandProperties.originator, demandMask)){ | |
if(originator != owner){ | |
return (0x0, false, "wrong originator"); | |
} | |
} | |
if(!( | |
startTime <= now && | |
endTime >= now | |
&& isRole(RoleManagement.Role.Trader,owner) | |
&& isRole(RoleManagement.Role.Trader, buyer) | |
&& isRole(RoleManagement.Role.AssetManager, owner) | |
)) return (0x0, false, "starttime or rolecheck"); | |
return (buyer, true, "everything ok"); | |
} | |
/// @notice function to check the matcher-properties | |
/// @param _demandId identifier | |
/// @param _wCreated Wh created | |
/// @return currentWhPerPeriod, certInCurrentPeriod, currentPeriod, if there was an error and what check failed | |
function checkMatcher(uint _demandId, uint _wCreated) | |
public | |
view | |
returns (uint , uint , uint, bool, string ) | |
{ | |
var( whAmountPerPeriod, currentWhPerPeriod, certInCurrentPeriod, lastPeriod, matcher) = db.getDemandMatcherProperties(_demandId); | |
whAmountPerPeriod = getMaxEnergyCoupling(_demandId, whAmountPerPeriod); | |
if (matcher != msg.sender) return (0,0,0, false, "wrong matcher"); | |
uint currentPeriod = getCurrentPeriod(_demandId); | |
if (currentPeriod == lastPeriod) { | |
if(currentWhPerPeriod+_wCreated > whAmountPerPeriod) { | |
return (0,0,0, false, "too much whPerPeriode"); | |
} | |
} else { | |
if(_wCreated > whAmountPerPeriod) { | |
return (0,0,0, false, "too much whPerPeriode and currentPeriod != lastPeriod"); | |
} | |
lastPeriod = currentPeriod; | |
currentWhPerPeriod = 0; | |
certInCurrentPeriod = 0; | |
} | |
currentWhPerPeriod += _wCreated; | |
certInCurrentPeriod += 1; | |
return (currentWhPerPeriod, certInCurrentPeriod, currentPeriod, true, "everything OK"); | |
} | |
/// @notice function to check the priceDriving-oarameters for the matching | |
/// @param _demandId identifier | |
/// @param _prodAssetId the producing asset-id | |
/// @param _wCreated the amount of energy created | |
/// @param _co2Saved the amount of CO2 saved | |
/// @return if there was an error and what check failed | |
function checkPriceDriving( | |
uint _demandId, | |
uint _prodAssetId, | |
uint _wCreated, | |
uint _co2Saved | |
) | |
public | |
view | |
returns (bool, string) | |
{ | |
if(_wCreated == 0) { | |
return (false, "no energy created"); | |
} | |
var (,,, minCO2OffsetDemand, compliance,,,) = db.getDemandPriceDriving(_demandId); | |
var(checkRes, error) = checkAssetType(_demandId, _prodAssetId); | |
if(!checkRes) { | |
return (checkRes,error); | |
} | |
(checkRes, error) = checkLocation(_demandId, _prodAssetId); | |
if(!checkRes) { | |
return (checkRes,error); | |
} | |
if(hasDemandPropertySet(DemandProperties.compliance, db.getDemandMask(_demandId))){ | |
if(uint(AssetProducingRegistryLogic(cooContract.assetProducingRegistry()).getCompliance(_prodAssetId)) !=compliance) { | |
return (false, "wrong compliance"); | |
} | |
} | |
if(hasDemandPropertySet(DemandProperties.minCO2, db.getDemandMask(_demandId))){ | |
if(_co2Saved == 0) { | |
_co2Saved = AssetProducingRegistryLogic(cooContract.assetProducingRegistry()).getCoSaved(_prodAssetId, _wCreated); | |
} | |
uint co2PerWh = ((_co2Saved * 1000) / _wCreated)/10; | |
if(co2PerWh < minCO2OffsetDemand){ | |
return (false, "wrong CO2"); | |
} | |
} | |
if(hasDemandPropertySet(DemandProperties.otherGreenAttributes, db.getDemandMask(_demandId))){ | |
if(!checkGreenAttributes(_demandId, _prodAssetId)) { | |
return (false,"wrong Green Attribute"); | |
} | |
} | |
if(hasDemandPropertySet(DemandProperties.typeOfPublicSupport, db.getDemandMask(_demandId))){ | |
if(!checkTypeOfPublicSupport(_demandId, _prodAssetId)) { | |
return (false,"wrong Type of public support"); | |
} | |
} | |
return (true,"everything OK"); | |
} | |
/// @notice function to calculate the current Period for a demand | |
/// @param _demandId identifier | |
/// @return current Period | |
function getCurrentPeriod(uint _demandId) | |
public | |
view | |
isInitialized | |
returns (uint) | |
{ | |
uint tf = db.getTimeFrame(_demandId); | |
if ( TimeFrame(tf) == TimeFrame.yearly) | |
{ | |
return ( now - db.getStartEpoche(_demandId) ) / (1 years); | |
} | |
if ( TimeFrame(tf) == TimeFrame.monthly) { | |
return ( now - db.getStartEpoche(_demandId) ) / (30 days); | |
} | |
if ( TimeFrame(tf) == TimeFrame.daily) { | |
return ( now - db.getStartEpoche(_demandId) ) / (1 days); | |
} | |
if ( TimeFrame(tf) == TimeFrame.hourly) { | |
return ( now - db.getStartEpoche(_demandId) ) / (1 hours); | |
} | |
} | |
/// @notice function to calculate the maximum amount of energy left for a demand and period | |
/// @param _demandId the demand-id | |
/// @param _whAmountPerPeriod the amount of Wh per Period | |
/// @return the maximum ammount of energy left for a demand | |
function getMaxEnergyCoupling(uint _demandId, uint _whAmountPerPeriod) | |
public | |
view | |
returns(uint) | |
{ | |
// there is no coupling, so we don't have to go further | |
if (!hasDemandPropertySet(DemandProperties.consuming, db.getDemandMask(_demandId))) return _whAmountPerPeriod; | |
//we're getting the consuming Assets and its properties | |
var (, consAsset ) = db.getDemandCoupling(_demandId); | |
var (capacityWh, maxCapacitySet, certificatesUsedForWh) = AssetConsumingRegistryLogic(address(cooContract.assetConsumingRegistry())).getConsumingProperies(consAsset); | |
// the maxCapacitySet-flag was set | |
if(maxCapacitySet){ | |
//we do not allow to let the capacity exceeds the amount of energy set in the demand | |
if(capacityWh > _whAmountPerPeriod) { | |
capacityWh = _whAmountPerPeriod; | |
} | |
if(certificatesUsedForWh <= capacityWh){ | |
return (capacityWh-certificatesUsedForWh); | |
} | |
else { | |
return 0; | |
} | |
} | |
// there is no max capacity set, so only the demand-energy is counting | |
else { | |
if(certificatesUsedForWh <= _whAmountPerPeriod){ | |
return (_whAmountPerPeriod-certificatesUsedForWh); | |
} | |
else{ | |
return 0; | |
} | |
} | |
return _whAmountPerPeriod; | |
} | |
/// @notice function to check if a full demand is created and enabling him | |
/// @param _demandId identifier | |
function checkForFullDemand(uint _demandId) | |
private | |
{ | |
var (generalExists, priceDrivingExists, matcherExists) = getExistStatus(_demandId); | |
if (generalExists && priceDrivingExists && matcherExists) { | |
db.setEnabled(_demandId,true); | |
db.addActiveDemand(_demandId); | |
db.setDemandCreationTime(_demandId, now); | |
LogDemandFullyCreated(_demandId); | |
} | |
} | |
/// @notice function to create the bitmask for a demand | |
/// @param _demandArray the array with demand properties | |
/// @return the calculated bitmask | |
function createDemandBitmask (bool[] _demandArray) | |
public | |
pure | |
returns (uint demandMask) | |
{ | |
/** Bitmask: originator, assetType, compliance, country, region, minCO2, producing, consuming */ | |
for(uint8 i = 0; i < 10; i++) { | |
if(_demandArray[i]){ | |
demandMask += uint(2) ** uint(i); | |
} | |
} | |
} | |
/// @notice function for comparing the role and the needed rights of an user | |
/// @param _props entry of the demandProperties-enum | |
/// @param _demandMask the bitmask of the demand | |
/// @return the demand has the property set | |
function hasDemandPropertySet( | |
DemandProperties _props, | |
uint _demandMask | |
) | |
public | |
pure | |
returns (bool) | |
{ | |
uint demandActive = uint(2) ** uint(_props); | |
return (_demandMask & demandActive != 0); | |
} | |
/// @notice function to check the assetType | |
/// @param _demandId the demand-id | |
/// @param _prodAssetId the production-asset id | |
/// @return the bool-flag for check and error-message | |
function checkAssetType(uint _demandId, uint _prodAssetId) | |
internal | |
view | |
returns (bool, string) | |
{ | |
if(hasDemandPropertySet(DemandProperties.assetType, db.getDemandMask(_demandId))){ | |
var (, , assettypeDemand, ,,,, ) = db.getDemandPriceDriving(_demandId); | |
if(AssetProducingRegistryLogic.AssetType(assettypeDemand) != AssetProducingRegistryLogic(cooContract.assetProducingRegistry()).getAssetType( _prodAssetId)){ | |
return (false, "wrong asset type"); | |
} | |
} | |
return (true, ""); | |
} | |
/// @notice internal helper function to check if the demand exists and the sender has the right role | |
/// @param _demandId the demandid | |
function checkForDemandExist(uint _demandId) | |
internal | |
view | |
{ | |
require(!db.demandExists(_demandId)); | |
require(isRole(RoleManagement.Role.AgreementAdmin, msg.sender)); | |
} | |
/// @notice function to check the location | |
/// @param _demandId the demand-id | |
/// @param _prodAssetId the production-asset id | |
/// @return the bool-flag for check and error-message | |
function checkLocation(uint _demandId, uint _prodAssetId) | |
internal | |
view returns (bool, string) | |
{ | |
if(hasDemandPropertySet(DemandProperties.country, db.getDemandMask(_demandId))){ | |
var (countryAsset, regionAsset, , , , , ) = AssetProducingRegistryLogic(cooContract.assetProducingRegistry()).getAssetLocation(_prodAssetId); | |
var (locationCountryDemand, locationRegionDemand, , , , ) = db.getDemandPriceDriving(_demandId); | |
if(locationCountryDemand != countryAsset){ | |
return (false, "wrong country"); | |
} | |
if(hasDemandPropertySet(DemandProperties.region, db.getDemandMask(_demandId))){ | |
if(locationRegionDemand != regionAsset) { | |
return (false, "wrong region"); | |
} | |
} | |
} | |
return (true,""); | |
} | |
/// @notice internal helper function to check green attributes | |
/// @param _demandId the demandId | |
/// @param _prodAssetId the id of the producing asset | |
/// @return true if the attributes are matching | |
function checkGreenAttributes(uint _demandId, uint _prodAssetId) | |
internal | |
view | |
returns(bool) | |
{ | |
var ( , , , , , demandGreenAttribute, , ) = db.getDemandPriceDriving(_demandId); | |
var ( , , , , , , assetGreenAttribute,) = AssetProducingRegistryLogic(cooContract.assetProducingRegistry()).getAssetProducingProperties(_prodAssetId); | |
return(demandGreenAttribute == assetGreenAttribute ); | |
} | |
/// @notice internal helper function to check the type of public support | |
/// @param _demandId the id of the demand | |
/// @param _prodAssetId the id of the producing asset | |
/// @return true if the green attributes are matching | |
function checkTypeOfPublicSupport(uint _demandId, uint _prodAssetId) | |
internal | |
view | |
returns (bool) | |
{ | |
var ( , , , , , ,demandTypeOfPublicSupport , ) = db.getDemandPriceDriving(_demandId); | |
var ( , , , , , , ,assetTypeOfPublicSupport) = AssetProducingRegistryLogic(cooContract.assetProducingRegistry()).getAssetProducingProperties(_prodAssetId); | |
return(demandTypeOfPublicSupport == assetTypeOfPublicSupport); | |
} | |
/// @notice internal function to create a coupling | |
/// @param _demandId demand-id | |
/// @param _prodAsset production-AssetId, gets only checked if the flag in the demand-Bitmask is set | |
/// @param _consAsset consuming-AssetId, gets only checked if the flag in the demand-Bitmask is set | |
function createCouplingInternal(uint _demandId, uint _prodAsset, uint _consAsset, uint _demandMask) | |
internal | |
{ | |
if(hasDemandPropertySet(DemandProperties.producing, _demandMask)){ | |
require(AssetProducingRegistryLogic(address(cooContract.assetProducingRegistry())).getActive((_prodAsset))); | |
} | |
if(hasDemandPropertySet(DemandProperties.consuming, _demandMask)){ | |
require(AssetConsumingRegistryLogic(address(cooContract.assetConsumingRegistry())).getActive((_consAsset))); | |
} | |
db.createCoupling(_demandId, _prodAsset, _consAsset); | |
} | |
/// @notice internal function to create a demand | |
/// @param _demandId the demand-Id | |
/// @param _originator the originator (can be set) | |
/// @param _buyer the buyer, has to bet set | |
/// @param _startTime starttime of the demand | |
/// @param _endTime endtime of the demand | |
/// @param _tf timeframe | |
/// @param _pricePerCertifiedKWh price per certified KWh | |
/// @param _currency used currency | |
function createGeneralDemandInternal( | |
uint _demandId, | |
address _originator, | |
address _buyer, | |
uint _startTime, | |
uint _endTime, | |
TimeFrame _tf, | |
uint _pricePerCertifiedKWh, | |
Currency _currency) | |
internal | |
{ | |
db.createGeneralDemand(_demandId, _originator, _buyer, _startTime, _endTime, uint(_tf), _pricePerCertifiedKWh, uint(_currency)); | |
} | |
/// @notice function to match produced energy with the needed demand | |
/// @param _demandId identifier of the demand | |
/// @param _wCreated amount of Wh created | |
/// @param _prodAssetId asset-Id that produced the energy | |
function matchDemand(uint _demandId, uint _wCreated, uint _prodAssetId) | |
external | |
isInitialized | |
{ | |
var (owner, currentWhPerPeriod, certInCurrentPeriod, currentPeriod) = matchInternal(_demandId, _wCreated, _prodAssetId, 0); | |
// all the criteria are matched, so we can create the certificate | |
uint certId = CertificateLogic(address(cooContract.certificateRegistry())).createCertificate(_prodAssetId, owner, _wCreated); | |
// at the end we have to update the matcher-properties | |
db.updateMatchProperties(_demandId, currentWhPerPeriod, certInCurrentPeriod, currentPeriod); | |
LogMatcherPropertiesUpdate(_demandId, currentWhPerPeriod, certInCurrentPeriod, currentPeriod, certId); | |
// there is a consuming activated, so we have to write the new amount of consumed energy into the asset information | |
if(hasDemandPropertySet(DemandProperties.consuming, db.getDemandMask(_demandId))){ | |
writeConsumingEnergy(_demandId, _wCreated, currentPeriod); | |
} | |
} | |
/// @notice function to write the consumed energy into the asset | |
/// @param _demandId the demandId | |
/// @param _wCreated the amount of energy created / consumed | |
/// @param _currentPeriod the current period | |
function writeConsumingEnergy(uint _demandId, uint _wCreated, uint _currentPeriod) | |
internal | |
isInitialized | |
{ | |
var( , , , lastPeriod, ) = db.getDemandMatcherProperties(_demandId); | |
var (, consAsset ) = db.getDemandCoupling(_demandId); | |
if (_currentPeriod == lastPeriod) { | |
var(,,currentConsumption) = AssetConsumingRegistryLogic(address(cooContract.assetConsumingRegistry())).getConsumingProperies(consAsset); | |
AssetConsumingRegistryLogic(address(cooContract.assetConsumingRegistry())).setConsumptionForPeriode(consAsset,_wCreated+currentConsumption); | |
} else { | |
AssetConsumingRegistryLogic(address(cooContract.assetConsumingRegistry())).setConsumptionForPeriode(consAsset,_wCreated); | |
} | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title the locationDefinition for the contracts | |
contract LocationDefinition { | |
struct Location { | |
bytes32 country; //why do you use bytes32 for everything instead of string, uint, ...? | |
bytes32 region; | |
bytes32 city; | |
bytes32 street; | |
bytes32 zip; | |
bytes32 houseNumber; | |
bytes32 gpsLatitude; | |
bytes32 gpsLongitude; | |
bool exists; | |
} | |
}// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuchler, [email protected] | |
pragma solidity ^0.4.17; | |
contract Migrations { | |
address public owner; | |
uint public last_completed_migration; | |
modifier restricted() { | |
if (msg.sender == owner) _; | |
} | |
function Migrations() public { | |
owner = msg.sender; | |
} | |
function setCompleted(uint completed) external restricted { | |
last_completed_migration = completed; | |
} | |
function upgrade(address new_address) external restricted { | |
Migrations upgraded = Migrations(new_address); | |
upgraded.setCompleted(last_completed_migration); | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title this interface defines functions for defining functions of the user-logic in order to call them in different contracts | |
interface RolesInterface { | |
/// @notice function to retrieve the rights of an user | |
/// @dev if the user does not exist in the mapping it will return 0x0 thus preventing them from accidently getting any rights | |
/// @param _user user someone wants to know its rights | |
/// @return bitmask with the rights of the user | |
function getRolesRights(address _user) external view returns (uint); | |
/// @notice function that checks if there is an user for the provided ethereum-address | |
/// @param _user ethereum-address of that user | |
/// @return bool if the user exists | |
function doesUserExist(address _user) external view returns (bool); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title The database contract for the users, traders and admins of the certificate of origin | |
/// @notice This contract only provides getter and setter methods that are only callable by the corresponging owner-contract | |
contract UserDB is Owned { | |
/// @notice The structure of an user / admin / trader | |
/// @dev as it's for now impossible to return a struct, there is a special get-function for this struct. | |
/// @dev keep in mind to update that function aswell when changing the user-struct | |
struct User { | |
bytes32 firstName; | |
bytes32 surname; | |
bytes32 organization; | |
LocationDefinition.Location location; | |
uint roles; | |
bool active; | |
} | |
/// @notice mapping for addresses to users | |
mapping(address => User) private userList; // why private? | |
modifier userExists(address _user) { | |
require(userList[_user].firstName != 0x0 && userList[_user].surname != 0x0); | |
_; | |
} | |
/// @notice The constructor of the UserDB | |
/// @dev the deployer of this contract will get full adminrights! | |
function UserDB(address _logic) Owned(_logic) public { | |
} | |
/// @notice function to set a new address for an existing organization | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to write into the storage | |
/// @param _user ethereum-address of the organization | |
/// @param _street new streetname | |
/// @param _number new number | |
/// @param _zip new zip-code | |
/// @param _city new city | |
/// @param _country new country | |
/// @param _state new state | |
function setAddress( | |
address _user, | |
bytes32 _street, | |
bytes32 _number, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _country, | |
bytes32 _state | |
) | |
external | |
onlyOwner | |
userExists(_user) | |
{ | |
User storage u = userList[_user]; | |
u.location.street = _street; | |
u.location.houseNumber = _number; | |
u.location.zip = _zip; | |
u.location.city = _city; | |
u.location.country = _country; | |
u.location.region = _state; | |
u.active = true; | |
} | |
/// @notice function to change the name of an existing organization, can only be used when the user already exists | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to write into the storage | |
/// @param _user ethereum-address of an user | |
/// @param _organization new name of the organization | |
function setOrganization( | |
address _user, | |
bytes32 _organization | |
) | |
external | |
onlyOwner | |
userExists(_user) | |
{ | |
User storage u = userList[_user]; | |
u.organization = _organization; | |
u.active = true; | |
} | |
/// @notice function for creating, editing an user, it cannot be used to set a Role of an user | |
/// @notice if the user does not exists yet it will be creates, otherwise the older userdata will be overwritten | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to write into the storage | |
/// @param _user address of the user | |
/// @param _firstName first name of the user | |
/// @param _surname surname of the user | |
/// @param _organization organization the user is representing | |
/// @param _street streetname | |
/// @param _number housenumber | |
/// @param _zip zip-code | |
/// @param _city city-name | |
/// @param _country country-name | |
/// @param _state state | |
function setUser( | |
address _user, | |
bytes32 _firstName, | |
bytes32 _surname, | |
bytes32 _organization, | |
bytes32 _street, | |
bytes32 _number, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _country, | |
bytes32 _state | |
) | |
external | |
onlyOwner | |
{ | |
User storage u = userList[_user]; | |
LocationDefinition.Location storage loc = u.location; | |
u.firstName = _firstName; | |
u.surname = _surname; | |
u.organization = _organization; | |
u.location = loc; | |
loc = u.location; | |
loc.country = _country; | |
loc.region = _state; | |
loc.city = _city; | |
loc.street = _street; | |
loc.zip = _zip; | |
loc.houseNumber = _number; | |
loc.gpsLatitude = 0x0; | |
loc.gpsLongitude = 0x0; | |
loc.exists = true; | |
u.active = true; | |
} | |
/// @notice function to (de-)active a user, dan only be used when the user already exists | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to write into the storage | |
/// @param _user ethereum-address of an user | |
/// @param _active flag if the account should be active | |
function setUserActive( | |
address _user, | |
bool _active | |
) | |
external | |
onlyOwner | |
{ | |
User storage u = userList[_user]; | |
u.active = _active; | |
} | |
/// @notice function to change the username, can only be used when the user already exists | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to write into the storage | |
/// @param _user ethereum-address of an user | |
/// @param _firstName new first name | |
/// @param _surname new surname | |
function setUserName( | |
address _user, | |
bytes32 _firstName, | |
bytes32 _surname | |
) | |
external | |
onlyOwner | |
userExists(_user) | |
{ | |
User storage u = userList[_user]; | |
u.firstName = _firstName; | |
u.surname = _surname; | |
u.active = true; | |
} | |
/// @notice function for editing the rights of an user | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to write into the storage | |
/// @param _user address of the user | |
/// @param _roles first name of the user | |
function setRoles( | |
address _user, | |
uint _roles | |
) | |
external | |
onlyOwner | |
{ | |
User storage u = userList[_user]; | |
u.roles = _roles; | |
} | |
/// @notice function that checks if there is an user for the provided ethereum-address | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to read directly from the contract | |
/// @param _user ethereum-address of that user | |
/// @return bool if the user exists | |
function doesUserExist(address _user) | |
external | |
view | |
returns (bool) { | |
return userList[_user].active; | |
} | |
/// @notice function to return all the data of an user | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to read directly from the contract | |
/// @param _user user | |
/// @return returns firstName, surname, organization, street, number, zip, city, country, state, roles and the active-flag | |
function getFullUser(address _user) | |
external | |
view | |
returns ( | |
bytes32 firstName, | |
bytes32 surname, | |
bytes32 organization, | |
bytes32 street, | |
bytes32 number, | |
bytes32 zip, | |
bytes32 city, | |
bytes32 country, | |
bytes32 state, | |
uint roles, | |
bool active | |
) | |
{ | |
User memory u = userList[_user]; | |
return (u.firstName, u.surname, u.organization, u.location.street, u.location.houseNumber, u.location.zip, u.location.city, u.location.country, u.location.region, u.roles, u.active); | |
} | |
/// @notice function to retrieve the rights of an user | |
/// @dev the onlyOwner-modifier is used, so that only the logic-contract is allowed to read directly from the contract | |
/// @dev if the user does not exist in the mapping it will return 0x0 thus preventing them from accidently getting any rights | |
/// @param _user user someone wants to know its rights | |
/// @return bitmask with the rights of the user | |
function getRolesRights(address _user) | |
external | |
view | |
returns (uint) | |
{ | |
return userList[_user].roles; | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Copyright 2018 Energy Web Foundation | |
// This file is part of the Origin Application brought to you by the Energy Web Foundation, | |
// a global non-profit organization focused on accelerating blockchain technology across the energy sector, | |
// incorporated in Zug, Switzerland. | |
// | |
// The Origin Application is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY and without an implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details, at <http://www.gnu.org/licenses/>. | |
// | |
// @authors: slock.it GmbH, Martin Kuechler, [email protected] | |
/// @title The logic-contract for the user-data | |
/// @notice this contract will not directly store any data, instead it will store them into the userDB-contract | |
contract UserLogic is RoleManagement, Updatable, RolesInterface { | |
/// @notice db user-db for storing the contract | |
UserDB public db; | |
modifier isInitialized { | |
require(address(db) != 0x0); | |
_; | |
} | |
/// @notice constructor | |
/// @param _coo address of the Certificate Registry contract (CoO.sol) | |
/// @dev it will also call the RoleManagement-constructor | |
function UserLogic(CoO _coo) RoleManagement(_coo) public { | |
} | |
/// @notice grant a user a an admin-right | |
/// @param _user user that should get rights | |
/// @param role admin-right to be granted | |
function addAdminRole(address _user, RoleManagement.Role role) | |
external | |
userExists(_user) | |
onlyRole(RoleManagement.Role.TopAdmin) | |
{ | |
if ((role == RoleManagement.Role.TopAdmin || role == RoleManagement.Role.UserAdmin | |
|| role == RoleManagement.Role.AssetAdmin || role == RoleManagement.Role.Trader) | |
// && role != RoleManagement.Role.Trader && role != RoleManagement.Role.AssetManager | |
) { | |
if (!isRole(role,_user)) { | |
uint roles = db.getRolesRights(_user); | |
db.setRoles(_user, roles + uint(2) ** uint(role)); | |
} | |
} | |
} | |
/// @notice grants a user the role AssetManager | |
/// @param _user user | |
function addAssetManagerRole(address _user) | |
external | |
userExists(_user) | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
{ | |
if (!isRole(RoleManagement.Role.AssetManager,_user)) { | |
uint roles = db.getRolesRights(_user); | |
db.setRoles(_user, roles + uint(2) ** uint(RoleManagement.Role.AssetManager)); | |
} | |
} | |
/// @notice grants an ethereum-account the matcher-rights | |
/// @param _user ethereum-account | |
function addMatcherRole(address _user) | |
external | |
onlyRole(RoleManagement.Role.TopAdmin) | |
{ | |
if (!isRole(RoleManagement.Role.Matcher,_user)) { | |
uint roles = db.getRolesRights(_user); | |
db.setRoles(_user, roles + uint(2) ** uint(RoleManagement.Role.Matcher)); | |
} | |
} | |
/// @notice grants a user the trader-Role | |
/// @param _user user | |
function addTraderRole(address _user) | |
external | |
userExists(_user) | |
onlyRole(RoleManagement.Role.AgreementAdmin) | |
{ | |
if (!isRole(RoleManagement.Role.Trader,_user)) { | |
uint roles = db.getRolesRights(_user); | |
db.setRoles(_user, roles + uint(2) ** uint(RoleManagement.Role.Trader)); | |
} | |
} | |
/// @notice Initialises the contract by binding it to a logic contract | |
/// @param _database Sets the logic contract | |
function init(address _database) external { | |
require(db == UserDB(0x0) && cooContract.owner() == msg.sender); | |
db = UserDB(_database); | |
} | |
/// @notice function to deactive an use, only executable for user-admins | |
/// @param _user the user that should be deactivated | |
function deactivateUser(address _user) | |
external | |
onlyRole(RoleManagement.Role.UserAdmin) | |
isInitialized | |
{ | |
require(!isRole(RoleManagement.Role.TopAdmin,_user) | |
&& !isRole(RoleManagement.Role.UserAdmin,_user) | |
&& !isRole(RoleManagement.Role.AssetAdmin,_user) | |
&& !isRole(RoleManagement.Role.AgreementAdmin,_user) | |
); | |
db.setUserActive(_user, false); | |
} | |
/// @notice function to remove an admin-right from a user | |
/// @param _user user | |
/// @param role role to be removed | |
function removeAdminRole(address _user, RoleManagement.Role role) | |
external | |
userExists(_user) | |
onlyRole(RoleManagement.Role.TopAdmin) | |
{ | |
if ((role == RoleManagement.Role.TopAdmin || role == RoleManagement.Role.UserAdmin | |
|| role == RoleManagement.Role.AssetAdmin || role == RoleManagement.Role.AgreementAdmin) | |
) { | |
if (isRole(role,_user)) { | |
uint roles = db.getRolesRights(_user); | |
db.setRoles(_user, roles - uint(2) ** uint(role)); | |
} | |
} | |
} | |
/// @notice removes the assetManagerRole from a user | |
/// @param _user user | |
function removeAssetManagerRole(address _user) | |
external | |
userExists(_user) | |
onlyRole(RoleManagement.Role.AssetAdmin) | |
{ | |
if (isRole(RoleManagement.Role.AssetManager,_user)) { | |
uint roles = db.getRolesRights(_user); | |
db.setRoles(_user, roles - uint(2) ** uint(RoleManagement.Role.AssetManager)); | |
} | |
} | |
/// @notice removes the traderRole from a user | |
/// @param _user user | |
function removeTraderRole(address _user) | |
external | |
userExists(_user) | |
onlyRole(RoleManagement.Role.AgreementAdmin) | |
{ | |
if (isRole(RoleManagement.Role.Trader,_user)) { | |
uint roles = db.getRolesRights(_user); | |
db.setRoles(_user, roles - uint(2) ** uint(RoleManagement.Role.Trader)); | |
} | |
} | |
/// @notice function set change the name of an organization | |
/// @param _user ethereum-address of an user / organization | |
function setOrganization(address _user, bytes32 _organization) | |
external | |
onlyRole(RoleManagement.Role.UserAdmin) | |
{ | |
require(_organization != 0x0); | |
db.setOrganization(_user,_organization); | |
} | |
/// @notice function to set a new address for an existing organization | |
/// @param _user ethereum-address of the organization | |
/// @param _street new streetname | |
/// @param _number new number | |
/// @param _zip new zip-code | |
/// @param _city new city | |
/// @param _country new country | |
/// @param _state new state | |
function setOrganizationAddress( | |
address _user, | |
bytes32 _street, | |
bytes32 _number, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _country, | |
bytes32 _state | |
) | |
external | |
onlyRole(RoleManagement.Role.UserAdmin) | |
{ | |
require(_city != 0x0 && _street != 0x0 && _number > 0 && _zip != 0x0 && _country != 0x0); | |
db.setAddress(_user, _street, _number, _zip, _city, _country, _state); | |
} | |
/// @notice funciton that can be called to create a new user in the storage-contract, only executable for user-admins! | |
/// @notice if the user does not exists yet it will be creates, otherwise the older userdata will be overwritten | |
/// @param _user address of the user | |
/// @param _firstName first name of the user | |
/// @param _surname surname of the user | |
/// @param _organization organization the user is representing | |
/// @param _street streetname | |
/// @param _number housenumber | |
/// @param _zip zip-code | |
/// @param _city city-name | |
/// @param _country country-name | |
/// @param _state state | |
function setUser( | |
address _user, | |
bytes32 _firstName, | |
bytes32 _surname, | |
bytes32 _organization, | |
bytes32 _street, | |
bytes32 _number, | |
bytes32 _zip, | |
bytes32 _city, | |
bytes32 _country, | |
bytes32 _state | |
) | |
external | |
onlyRole(RoleManagement.Role.UserAdmin) | |
isInitialized | |
{ | |
require( | |
_user != address(0x0) | |
&& _firstName != 0x0 && _surname != 0x0 | |
&& _organization != 0x0 | |
&& _city != 0x0 && _street != 0x0 && _number > 0 && _zip != 0x0 && _country != 0x0 | |
); | |
db.setUser( _user, _firstName, _surname, _organization, _street, _number, _zip, _city, _country, _state); | |
} | |
/// @notice function to change the name of an user | |
/// @param _user ethereum-account of that user | |
/// @param _firstName new first name | |
/// @param _surname new surname | |
function setUserName( | |
address _user, | |
bytes32 _firstName, | |
bytes32 _surname | |
) | |
external | |
onlyRole(RoleManagement.Role.UserAdmin) | |
{ | |
require(_firstName != 0x0 && _surname != 0x0); | |
db.setUserName(_user, _firstName, _surname); | |
} | |
/// @notice function to set / edit the rights of an user / account, only executable for Top-Admins! | |
/// @param _user user that rights will change | |
/// @param _rights rights encoded as bitmask | |
function setRoles(address _user, uint _rights) | |
external | |
onlyRole(RoleManagement.Role.UserAdmin) | |
isInitialized | |
userExists(_user) | |
{ | |
db.setRoles(_user, _rights); | |
} | |
/// @notice function to update the logic of a smart contract | |
/// @param _newLogic contract-address of the new smart contract, replacing the currently active one | |
function update(address _newLogic) | |
external | |
onlyAccount(address(cooContract)) | |
isInitialized | |
{ | |
db.changeOwner(_newLogic); | |
} | |
/// @notice function that checks if there is an user for the provided ethereum-address | |
/// @param _user ethereum-address of that user | |
/// @return bool if the user exists | |
function doesUserExist(address _user) | |
external | |
view | |
returns (bool) | |
{ | |
return db.doesUserExist(_user); | |
} | |
/// @notice function to return all the data of an user | |
/// @param _user user | |
/// @return returns firstName, surname, organization, street, number, zip, city, country, state, roles and the active-flag | |
function getFullUser(address _user) | |
external | |
view | |
returns ( | |
bytes32 firstName, | |
bytes32 surname, | |
bytes32 organization, | |
bytes32 street, | |
bytes32 number, | |
bytes32 zip, | |
bytes32 city, | |
bytes32 country, | |
bytes32 state, | |
uint roles, | |
bool active | |
) | |
{ | |
return db.getFullUser(_user); | |
} | |
/// @notice function to retrieve the rights of an user | |
/// @dev if the user does not exist in the mapping it will return 0x0 thus preventing them from accidently getting any rights | |
/// @param _user user someone wants to know its rights | |
/// @return bitmask with the rights of the user | |
function getRolesRights(address _user) | |
external | |
view | |
returns (uint) | |
{ | |
return db.getRolesRights(_user); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment