Skip to content

Instantly share code, notes, and snippets.

@dima91
Created August 16, 2018 16:25
Show Gist options
  • Save dima91/52d32f637dcfb20a0c97bc160c001e0e to your computer and use it in GitHub Desktop.
Save dima91/52d32f637dcfb20a0c97bc160c001e0e to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.24+commit.e67f0147.js&optimize=true&gist=
pragma solidity ^0.4.24;
import "./sharedTypes.sol";
import "./catalogSmartContract.sol";
contract BaseContentManagementContract {
// Enum that describe type of access which an user has
enum AccessType {noneAccess, standardAccess, premiumAccess}
// Struct that indentifies a user who was granted to consume current content
struct GrantedUser {
address userAddress;
AccessType accessType;
bool toBeConsumed;
bool exists;
bool [3] givenFeedbacks; // Stores information about given feedback for each category
}
/* Variables to store feedbacks from users: each user has a unique position in each array. feedbacksSums stores sum of all given feedbacks
* and feedbacksCount stores number of given feedbacks for each category (A user may or not rate a content for a category) */
uint[3] feedbacksSums; // contentAppreciation, priceFairness, availabilityTime
uint8[3] feedbacksCount; // Number of feedbacks given for each category
address private catalogAddress; // Address of catalog to check if determined functions are called only by catalog
SharedTypes.contentType private typeOfContent; // Tpe of content which this contract contains
bytes32 private contentTitle; // Title which identifies this contract in catalog
uint private numberOfViews; // Number of viwes about content of this contract
mapping (bytes32 => GrantedUser) allowedUsers; // Map of users that are allowed to access this content
constructor (SharedTypes.contentType _conType, bytes32 _conTitle, address _catalogAddr) public {
typeOfContent = _conType;
numberOfViews = 0;
contentTitle = _conTitle;
catalogAddress = _catalogAddr;
feedbacksSums[0] = 0;
feedbacksSums[1] = 0;
feedbacksSums[2] = 0;
feedbacksCount[0] = 0;
feedbacksCount[1] = 0;
feedbacksCount[2] = 0;
}
// ***** ***** //
// ***** Modifiers ***** //
modifier onlyCatalog () {
require (msg.sender == catalogAddress);
_;
}
modifier isAllowedUser (bytes32 _username, address _senderAddress) {
bool exists= allowedUsers[_username].exists;
bool correspondAddress= allowedUsers[_username].userAddress == _senderAddress;
require (exists && correspondAddress);
_;
}
modifier notToBeConsumedBy (bytes32 _username) {
require (allowedUsers[_username].accessType == AccessType.noneAccess);
_;
}
modifier toBeConsumedBy (bytes32 _username) {
//require (allowedUsers[_username].toBeConsumed == true);
require (allowedUsers[_username].accessType != AccessType.noneAccess);
_;
}
modifier isCorrectRating (uint8 _val) {
require ((_val <= 5) && (_val>0));
_;
}
modifier isCorrectCategory (uint8 _category) {
require ((_category<=3) && (_category>=1));
_;
}
modifier notGivenFeedbackFor (uint8 _category, bytes32 _username) {
require (allowedUsers[_username].givenFeedbacks[_category] == false);
_;
}
// ***** ***** //
// ***** Helper private/internal functions ***** //
/* This function allows subContracts of this contract to retrieve content if and only if user
* with addrs _userAddr is into "allowedUsers" map
*/
function retrieveContent (bytes32 _username) internal isAllowedUser(_username, msg.sender) toBeConsumedBy (_username) {
bool isStandard= allowedUsers[_username].accessType == AccessType.standardAccess;
if (isStandard) {
numberOfViews++;
(CatalogSmartContract (catalogAddress)).notifyNewView (contentTitle, _username);
}
allowedUsers[_username].accessType = AccessType.noneAccess;
allowedUsers[_username].toBeConsumed = false;
}
// ***** ***** //
// ***** Public functions ***** //
// Function used by catalog to check that has the same address of catalogAddress local variable
function getCatalogAddress () public view returns (address) {
return catalogAddress;
}
function getViewsCount () public view returns (uint) {
return numberOfViews;
}
function getTitle () public view returns (bytes32) {
return contentTitle;
}
function getType () public view returns (SharedTypes.contentType) {
return typeOfContent;
}
// This function allows (only to catalog) to grant access to a user with address _userAddr.
function grantAccessToUser (bytes32 _username, address _userAddr, bool isPremium) public onlyCatalog () notToBeConsumedBy (_username) {
if (allowedUsers[_username].exists == false) {
allowedUsers[_username].exists = true;
allowedUsers[_username].userAddress = _userAddr;
allowedUsers[_username].givenFeedbacks[0] = false;
allowedUsers[_username].givenFeedbacks[1] = false;
allowedUsers[_username].givenFeedbacks[2] = false;
}
if (isPremium)
allowedUsers[_username].accessType= AccessType.premiumAccess;
else
allowedUsers[_username].accessType= AccessType.standardAccess;
allowedUsers[_username].toBeConsumed = true;
}
// This function returns true if a user is allowed to view current content
function isAllowed (bytes32 _username) public view returns (bool) {
return allowedUsers[_username].accessType != AccessType.noneAccess;
}
// ***** ***** //
// ***** Feedback functions ***** //
/* This function allows (only to allowed users) to leave a feedback of type 't' and value 'v' (1<=v<=5) for this content
* _c:1 => first category, _c:2 => second category, _c:3 => third category */
function leaveFeedback (bytes32 _username, uint8 _c, uint8 _v) public isAllowedUser(_username, msg.sender) isCorrectCategory(_c) isCorrectRating(_v) notGivenFeedbackFor(_c-1, _username) notToBeConsumedBy (_username) {
uint8 c1= _c-1;
feedbacksSums[c1] += _v;
feedbacksCount[c1] +=1;
allowedUsers[_username].givenFeedbacks[c1]= true;
}
function getFeedbacksAverages () public view returns (uint [3]) {
uint[3] memory feeds;
uint8 i=0;
for (i=0; i<3; i++) {
if (feedbacksCount[i] != 0)
feeds[i] = feedbacksSums[i] / feedbacksCount[i];
else
feeds[i] = 0;
}
return feeds;
}
function getFeedbacksCount () public view returns (uint [3]) {
uint[3] memory feedsCount;
uint i=0;
for (i=0; i<3; i++) {
feedsCount[i] = feedbacksCount[i];
}
return feedsCount;
}
// ***** ***** //
// ***** Abastract functions ***** //
function consumeContent (bytes32 _username) public;
}
/* *************************************************************************************************************************************** */
/* *************************************************************************************************************************************** */
/* *************************************************************************************************************************************** */
contract SongManagementContract is BaseContentManagementContract {
constructor (bytes32 _title, address _catAddr)
BaseContentManagementContract(SharedTypes.contentType.song, _title, _catAddr) public {
}
function consumeContent (bytes32 _username) public {
retrieveContent (_username);
}
}
/* ********************************************* */
/* ********************************************* */
/* ********************************************* */
contract VideoManagementContract is BaseContentManagementContract {
constructor (bytes32 _title, address _catAddr)
BaseContentManagementContract(SharedTypes.contentType.video, _title, _catAddr) public {
}
function consumeContent (bytes32 _username) public {
retrieveContent (_username);
}
}
/* ********************************************* */
/* ********************************************* */
/* ********************************************* */
contract PhotoManagementContract is BaseContentManagementContract {
constructor (bytes32 _title, address _catAddr)
BaseContentManagementContract(SharedTypes.contentType.photo, _title, _catAddr) public {
}
function consumeContent (bytes32 _username) public {
retrieveContent (_username);
}
}
/* ********************************************* */
/* ********************************************* */
/* ********************************************* */
contract DocumentManagementContract is BaseContentManagementContract {
constructor (bytes32 _title, address _catAddr)
BaseContentManagementContract(SharedTypes.contentType.document, _title, _catAddr) public {
}
function consumeContent (bytes32 _username) public {
retrieveContent (_username);
}
}
pragma solidity ^0.4.24;
import "./sharedTypes.sol";
import "./ownable.sol";
import "./baseContentManagementContract.sol";
contract CatalogSmartContract is Ownable {
// Event list
event NewUser (bytes32 username, address userAddress);
event ContentPublished (bytes32 username, bytes32 contentTitle, address contentAddress);
event GrantedAccess (bytes32 username, address userAddress, bytes32 contentTitle, address contentAddress);
event GrantedPremium (bytes32 username, address userAddress);
event CatalogDied ();
// Duration of premium account (in block height)
uint constant PREMIUM_ACCOUNT_DURATION = 256; // ~240 blocks/hour
// Cost of premium account
uint constant PREMIUM_ACCOUNT_COST= 44000 szabo; // ~ 20 €
// Cost of each single content
uint constant CONTENT_COST= 6300 szabo; // ~ 3 €
// Payout for author for each content access (this value have to be minor than CONTENT_COST)
uint constant PAYOUT_FOR_AUTHOR= 4200 szabo; // ~ 2 €
// Maximum number of views before sending payment
uint constant MAX_VIEWS_LIMIT= 5;
// Array of users which have are registered to service
bytes32 [] usersArray;
// Number of users
uint usersCount;
// Mapping which contains a User struct for each user that hav published or have requeested a content
mapping (bytes32 => SharedTypes.User) usersMapping;
// Mapping which link address to user: needed for functions like getContent
mapping (address => bytes32) addr2User;
// Mapping which contains an ExtendedContent struct for each content published on the platform (identified by a string)
mapping (bytes32 => SharedTypes.ExtendedContent) contentsMapping;
// Array containing addresses of contents published on the system (for loop functions)
bytes32 [] contentsArray;
// Number of contents (also index of next content in the array)
uint contentsCount;
constructor () public payable {
contentsCount= 0;
usersCount= 0;
}
// ************************************************************************************************************** //
// ************************************************************************************************************** //
// Modifiers
// To check if the content "_contentTitle" is already published on catalog
modifier alreadyPublishedM (bytes32 _contentTitle) {
require (alreadyPublished(_contentTitle) == true);
_;
}
// To check if the content "_contentTitle" is NOT already published on catalog
modifier notPublished (bytes32 _contentTitle) {
require (alreadyPublished(_contentTitle) == false);
_;
}
// To check if no user with address "_address" was already registered
modifier addressNotRegistered (address _address) {
require (addr2User[_address] == ""); // Sembra funzionare
_;
}
// To check if the user "_username" is NOT already registered on catalog
modifier userDoesntExist (bytes32 _username) {
require (userExists (_username) == false);
_;
}
// To check if the user "_username" is already registered on catalog
modifier userExistsM (bytes32 _username) {
require (userExists(_username) == true);
_;
}
// To check if the user "_username" has a premim account
modifier isPremiumM (bytes32 _username) {
require (isPremium(_username) == true);
_;
}
// To check if "_msgValue" is equal to "_lim"
modifier equalTo (uint _msgValue, uint _lim) {
require (_msgValue == _lim);
_;
}
// To check if the user "_username" is already allowed to retreive content "_contentTitle". This function calls the "isAllowed" function on BaseContentManagementContract
modifier userAllowed (bytes32 _username, bytes32 _contentTitle) {
BaseContentManagementContract remoteContract= BaseContentManagementContract (contentsMapping[_contentTitle].contractAddress);
require (remoteContract.isAllowed(_username) == true);
_;
}
// To check corectness of category value.
modifier isCorrectCategory (uint8 _category) {
require ((_category<=3) && (_category>=1));
_;
}
// To check corectness of category value. Admits also value 0 because is the value for "all categories"
modifier isCorrectCategoryForGetRating (uint8 _category) {
require ((_category<=3) && (_category>=0));
_;
}
// ************************************************************************************************************** //
// ************************************************************************************************************** //
// Helper private functions
// Function to check if a user exists or not in usersMapping
function userExists (bytes32 _username) private view returns (bool){
return (usersMapping[_username].exists == true);
}
// Function which returns wether a content is already published on the platform
function alreadyPublished (bytes32 _conTitle) private view returns (bool) {
return (contentsMapping[_conTitle].exists == true);
}
// Function to register a user to system ~ 125 k, ~95 k, ~95 k....
function addUser (bytes32 _username, address _userAddr) userDoesntExist(_username) addressNotRegistered(_userAddr) userDoesntExist (_username) private {
addr2User[_userAddr]= _username; // 20 k
usersMapping[_username].userAddress= _userAddr; // 20 k
usersMapping[_username].exists= true; // 22 k
// Following field have already correct values
//usersMapping[_username].accType= SharedTypes.accountType.standard;
//usersMapping[_username].expirationTime= 0;
//usersMapping[_username].latestContent = 0x0;
usersCount++; // 20 la prima volta, 5 poi
usersArray.push (_username); // 40 k
emit NewUser (_username, _userAddr); // 3 k
}
// Function to add new content with address 'contAddr' registered by user with address 'userAddr'
function addContent (bytes32 _contentTitle, address _contentAddr, bytes32 _username) notPublished(_contentTitle) private {
contentsCount++;
contentsArray.push (_contentTitle);
contentsMapping[_contentTitle].exists= true;
contentsMapping[_contentTitle].author= _username;
contentsMapping[_contentTitle].contractAddress= _contentAddr;
usersMapping[_username].latestContent= _contentTitle;
}
// Return true if current premium account is valid
function isPremiumValid (bytes32 _username, uint _currentBlockNumber) userExistsM(_username) private view returns (bool) {
return (usersMapping[_username].expirationTime > _currentBlockNumber);
}
// Return the average value of feedbacks, given as parameter
function feedbacksAverage (uint[3] feeds, uint[3] feedsCount) private pure returns (uint) {
uint feedsSum=0;
uint feedsCnt=0;
uint i=0;
for (i=0; i<3; i++) {
if (feeds[i] != 0) {
feedsSum += feeds[i];
feedsCnt += feedsCount[i];
}
}
if (feedsCnt != 0)
return feedsSum / feedsCnt;
else
return 0;
}
// This function generalize getMostRated* operations
function genericGetMostRated (bool _filterByAuthor, bytes32 _author, bool _filterByGenre, SharedTypes.contentType _type, uint8 _category)
private view isCorrectCategoryForGetRating(_category) returns (bytes32) {
require (contentsCount > 0);
uint i = 0;
uint mostRatedIdx = 0;
uint mostRateValue = 0;
uint inspectedElements = 0;
for (i=0; i<contentsCount; i++) {
BaseContentManagementContract _content = BaseContentManagementContract (contentsMapping[contentsArray[i]].contractAddress);
bytes32 currentAuthor = contentsMapping[contentsArray[i]].author;
if (_filterByGenre && _content.getType() != _type)
continue;
if (_filterByAuthor && currentAuthor != _author)
continue;
uint[3] memory feeds = (BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress)).getFeedbacksAverages();
uint[3] memory feedsCount = (BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress)).getFeedbacksCount();
if (_category == 0) {
// Calculating average and compare to temporary most rated
// FIXME Add check on feedsCount > 0
uint tmpRating = feedbacksAverage (feeds, feedsCount);
if (tmpRating > mostRateValue) {
mostRatedIdx = i;
mostRateValue = tmpRating;
}
}
else {
// FIXME Add check on feedsCount > 0
if (feeds[_category-1] > mostRateValue) {
mostRatedIdx = i;
mostRateValue = feeds[_category-1];
}
}
inspectedElements++;
}
// This instruction
require (inspectedElements > 0);
return contentsArray[mostRatedIdx];
}
// ************************************************************************************************************** //
// ************************************************************************************************************** //
// Public functions
// Function which kills current contract. It is callable only from contract's owner
function killMe () public onlyOwner() {
// First of all, it distrubutes payments amog authors
uint i=0;
uint sumViews= 0;
for (i=0; i<usersCount; i++) {
BaseContentManagementContract remoteContract= BaseContentManagementContract (usersMapping[usersArray[i]].userAddress);
uint count= remoteContract.getViewsCount();
if ((count % MAX_VIEWS_LIMIT) != 0) {
address(remoteContract).transfer ((count % MAX_VIEWS_LIMIT) * PAYOUT_FOR_AUTHOR);
}
sumViews += count;
}
uint unit= address(this).balance / sumViews;
// Second, equally distribute current balance to among authors
for (i=0; i<usersCount; i++) {
uint payment= unit * BaseContentManagementContract (usersMapping[usersArray[i]].userAddress).getViewsCount ();
address (usersMapping[usersArray[i]].userAddress).transfer (payment);
}
emit CatalogDied ();
selfdestruct (owner);
}
// Function that allows users to registrate themselves into service
function registerMe (bytes32 _username) public userDoesntExist (_username) addressNotRegistered (msg.sender) {
addUser (_username, msg.sender);
}
// Function to link a content with the system
function publishContent (bytes32 _username, bytes32 _contentTitle, address _contentAddr) notPublished (_contentTitle) public {
if (!userExists(_username)) {
// Registering new user
addUser (_username, msg.sender);
}
// Checking wether content's catalogAddress and contentTitle are correct
BaseContentManagementContract remoteContract= BaseContentManagementContract (_contentAddr);
require (remoteContract.getCatalogAddress() == address (this));
require (remoteContract.getTitle() == _contentTitle);
addContent (_contentTitle, _contentAddr, _username);
emit ContentPublished (_username, _contentTitle, _contentAddr);
}
// Function to notify new view from another content manager
function notifyNewView (bytes32 _contentTitle, bytes32 _username) alreadyPublishedM (_contentTitle) userExistsM (_username) userAllowed (_username, _contentTitle) public {
bytes32 author= contentsMapping[_contentTitle].author;
uint count= BaseContentManagementContract (msg.sender).getViewsCount ();
if ((count % MAX_VIEWS_LIMIT) == 0) {
address rcvAddr= usersMapping[author].userAddress;
rcvAddr.transfer (MAX_VIEWS_LIMIT * PAYOUT_FOR_AUTHOR);
}
}
// Function to get a content's address
function getAddressOf (bytes32 _contentTitle) alreadyPublishedM (_contentTitle) public view returns (address) {
return contentsMapping[_contentTitle].contractAddress;
}
// ************************************************************************************************************** //
// ************************************************************************************************************** //
// Required functions
// Returns the number of views for each content
function getStatistics () public view returns (uint [], bytes32 []) {
uint [] memory stats= new uint[] (contentsCount);
bytes32 [] memory strs= new bytes32[] (contentsCount);
uint i= 0;
bytes32 tmpCnt;
for (i=0;i<contentsCount; i++) {
tmpCnt= contentsArray[i];
stats[i]= (BaseContentManagementContract (contentsMapping[tmpCnt].contractAddress)).getViewsCount();
strs[i]= tmpCnt;
}
return (stats, strs);
}
// Returns the list of contents without the number of views
function getContentList () public view returns (bytes32 []) {
bytes32 [] memory conList= new bytes32[] (contentsCount);
uint i=0;
for (i=0; i<contentsCount; i++) {
conList[i]= contentsArray[i];
}
return conList;
}
// Returns the list of x newest contents
function getNewContentList (uint _n) public view returns (bytes32 []) {
uint count=0;
uint i=0;
uint j=0;
if (_n>contentsCount)
count=contentsCount;
else
count=_n;
bytes32 [] memory newest = new bytes32[] (count);
while (count!=0) {
j=i;
i++;
newest[j]= contentsArray[contentsCount-(i)];
count--;
}
return newest;
}
// Returns the most recent content with genre x
function getLatestByGenre (SharedTypes.contentType _ct) public view returns (bytes32) {
uint i= contentsCount;
bool found= false;
bytes32 reqStr;
if (contentsCount == 0) {
return "";
}
while (i != 0 && !found ) {
i--;
if ((BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress)).getType() == _ct) {
found = true;
reqStr= (BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress)).getTitle();
}
}
return reqStr;
}
// Returns the content with genre x, which has received the maximum number of views
function getMostPopularByGenre (SharedTypes.contentType _ct) public view returns (bytes32) {
bytes32 reqStr= "";
uint maximum=0;
uint i= contentsCount;
if (contentsCount == 0) {
return "";
}
while (i != 0) {
i--;
BaseContentManagementContract remoteContract= BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress);
if (remoteContract.getType() == _ct) {
if (remoteContract.getViewsCount() > maximum)
reqStr= remoteContract.getTitle();
}
}
return reqStr;
}
// Returns the most recent content of the author x
function getLatestByAuthor (bytes32 _author) userExistsM (_author) public view returns (bytes32) {
bytes32 reqStr;
bool found= false;
uint i= contentsCount;
if (contentsCount == 0) {
return "";
}
while (i != 0 && !found) {
i--;
bytes32 author= contentsMapping[contentsArray[i]].author;
if (author == _author) {
found = true;
reqStr= (BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress)).getTitle();
}
}
return reqStr;
}
// FIXME Returns the content with most views of the author x
function getMostPopularByAuthor (bytes32 _author) userExistsM (_author) public view returns (bytes32) {
bytes32 reqStr= "";
uint maximum=0;
uint i= contentsCount;
if (contentsCount == 0) {
return "";
}
while (i != 0) {
i--;
BaseContentManagementContract remoteContract= BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress);
if (contentsMapping[contentsArray[i]].author == _author) {
if (remoteContract.getViewsCount() > maximum)
reqStr= remoteContract.getTitle();
}
}
return reqStr;
}
// Returns true if x holds a still valid premium account, false otherwise
function isPremium (bytes32 _username) userExistsM (_username) public view returns (bool) {
return (usersMapping[_username].accType == SharedTypes.accountType.premium);
}
// Returns the content with highest rating for feedback category y (or highest average of all ratings if y is not specified)
// TEST ME
function getMostRated (uint8 _category) public view isCorrectCategoryForGetRating(_category) returns (bytes32) {
return genericGetMostRated (false, 0, false, SharedTypes.contentType.song, _category);
/*require (contentsCount > 0);
uint i=0;
uint mostRatedIdx=0;
uint mostRateValue=0;
for (i=0; i<contentsCount; i++) {
uint[3] memory feeds= (BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress)).getFeedbacksAverages();
if (_category == 0) {
// Calculating average and compare to temporary most rated
uint[3] memory feedsCount= (BaseContentManagementContract(contentsMapping[contentsArray[i]].contractAddress)).getFeedbacksCount();
uint tmpRating= feedbacksAverage (feeds, feedsCount);
if (tmpRating > mostRateValue) {
mostRatedIdx= i;
mostRateValue= tmpRating;
}
}
else {
if (feeds[_category] > mostRateValue) {
mostRatedIdx= i;
mostRateValue= feeds[_category];
}
}
}
return contentsArray[mostRatedIdx];*/
}
/* Returns the content with highest rating for feedback gategory _category
* (or highest average of all ratings if _category is not specified) with genre _genre */
function getMostRatedByGenre (SharedTypes.contentType _genre, uint8 _category) public view returns (bytes32) {
return genericGetMostRated (false, 0, true, _genre, _category);
}
/* Returns the content with highest rating for feedback category _category
* (or highest average of all ratings it _category is not specified) with author _author */
function getMostRatedByAuthor (bytes32 _author, uint8 _category) public view returns (bytes32) {
return genericGetMostRated (true, _author, false, SharedTypes.contentType.song, _category);
}
// ************************************************************************************************************** //
// ************************************************************************************************************** //
// Pays for access to content x (NOT ACCESS TO CONTENT!)
function getContent (bytes32 _contentTitle) userExistsM(addr2User[msg.sender]) alreadyPublishedM (_contentTitle) equalTo (msg.value, CONTENT_COST) public payable {
// ******* --> Check preconditions (enough value..) + handle payments <-- *******
bytes32 senderUser= addr2User[msg.sender];
(BaseContentManagementContract (contentsMapping[_contentTitle].contractAddress)).grantAccessToUser (senderUser, msg.sender, false);
emit GrantedAccess (senderUser, msg.sender, _contentTitle, contentsMapping[_contentTitle].contractAddress);
}
// Requests access to content x without paying, premium accounts only
function getContentPremium (bytes32 _contentTitle) isPremiumM (addr2User[msg.sender]) alreadyPublishedM (_contentTitle) public {
bytes32 senderUser= addr2User[msg.sender];
if (!isPremiumValid (senderUser, block.number)) {
usersMapping[senderUser].accType= SharedTypes.accountType.standard;
usersMapping[senderUser].expirationTime= 0;
revert ();
}
(BaseContentManagementContract (contentsMapping[_contentTitle].contractAddress)).grantAccessToUser (senderUser, msg.sender, true);
emit GrantedAccess (senderUser, msg.sender, _contentTitle, contentsMapping[_contentTitle].contractAddress);
}
// Pays for granting access for content x to the user u
function giftContent (bytes32 _contentTitle, bytes32 _receivingUser) userExistsM(_receivingUser) alreadyPublishedM (_contentTitle) equalTo (msg.value, CONTENT_COST) public payable {
// ******* --> Check preconditions (enough value..) + handle payments <-- *******
(BaseContentManagementContract (contentsMapping[_contentTitle].contractAddress)).grantAccessToUser (_receivingUser, usersMapping[_receivingUser].userAddress, false);
emit GrantedAccess (_receivingUser, usersMapping[_receivingUser].userAddress, _contentTitle, contentsMapping[_contentTitle].contractAddress);
}
// Pays for granting a Premium Account to the user u
function giftPremium (bytes32 _receivingUser) userExistsM(_receivingUser) equalTo (msg.value, PREMIUM_ACCOUNT_COST) public payable {
// ******* --> check preconditions + handle payments <-- *******
usersMapping[_receivingUser].accType= SharedTypes.accountType.premium;
usersMapping[_receivingUser].expirationTime= block.number + PREMIUM_ACCOUNT_DURATION;
emit GrantedPremium (_receivingUser, usersMapping[_receivingUser].userAddress);
}
// Starts a new premium subscription
function buyPremium () userExistsM(addr2User[msg.sender]) equalTo (msg.value, PREMIUM_ACCOUNT_COST) public payable {
// ******* --> check preconditions + handle payments <-- *******
bytes32 senderUser= addr2User[msg.sender];
usersMapping[senderUser].accType= SharedTypes.accountType.premium;
usersMapping[senderUser].expirationTime= block.number + PREMIUM_ACCOUNT_DURATION;
emit GrantedPremium (addr2User[msg.sender], usersMapping[addr2User[msg.sender]].userAddress);
}
}
pragma solidity ^0.4.24;
import "./baseContentManagementContract.sol";
import "./catalogSmartContract.sol"; // FIXME Remove me!!!!!
pragma solidity ^0.4.24;
import "./mortal.sol";
contract Crowdfund {
struct Funder {
address addr;
uint amount;
}
struct Project {
bool created;
bool opened;
string name;
address owner;
mapping (uint => Funder) funders;
uint fundersSize;
uint amount;
uint fundingGoal;
}
event ProjectCreated (string _name, uint _fundingGoal);
event FundTransferred (address _backer, string _project, uint _amount, uint _remainingAmount);
event fundingGoalReached (string project);
address private owner;
mapping (string => Project) private projects;
modifier ProjectNotExists (string _name) {
require (projects[_name].created == false);
_;
}
modifier ProjectExists (string _name) {
require (projects[_name].created == true);
_;
}
constructor () public {
owner= msg.sender;
}
function createProject (string _projectName, uint _amount) public ProjectNotExists (_projectName) {
projects[_projectName]= Project (true, true, _projectName, msg.sender, 0, 0, _amount);
emit ProjectCreated (_projectName, _amount);
}
function sendMoney (string _projectName, uint _sum) public ProjectExists (_projectName) {
Project storage p= projects[_projectName];
p.funders[p.fundersSize]= Funder (msg.sender, _sum);
p.fundersSize++;
p.amount += _sum;
uint remaining= p.fundingGoal - _sum;
emit FundTransferred (msg.sender, _projectName, _sum, remaining);
checkGoalReached (_projectName);
}
function checkGoalReached (string _projectName) private returns (bool) {
Project storage p= projects[_projectName];
if (p.fundingGoal <= p.amount) {
emit fundingGoalReached (_projectName);
p.opened= false;
return true;
}
return false;
}
function getProject (string _projectName) public view returns (bool, address, uint, uint, uint, bool) {
Project storage p= projects[_projectName];
return (p.opened, p.owner, p.fundersSize, p.amount, p.fundingGoal, p.opened);
}
}
pragma solidity ^0.4.24;
contract Ownable {
address owner;
constructor () public {
owner = msg.sender;
}
modifier onlyOwner () {
require (msg.sender == owner);
_;
}
}
pragma solidity ^0.4.24;
// Library Containing types definitions
library SharedTypes {
// Kind of content
enum contentType {song, video, photo, document}
// Kind of account
enum accountType {standard, premium}
/* Kind of feedback
* contentAppreciation : how much the customer enjoyed the content
* priceFairness : how fair the requested price is considered compared to the content
* availabilityTime : how fair the availability of content is considered compating to the price
*/
enum feedbackType {contentAppreciation, priceFairness, availabilityTime}
// Type for registered users, both authors or customers. This struct is stored in the catalog
// Username is the identifier of content
struct User {
address userAddress; // Address of user (key value is the name)
bool exists; // To check if an user exists in the system
accountType accType; // Type of current account (default standard)
uint expirationTime; // Expiration time (calculated in block.size). Valid only for premium account
bytes32 latestContent; // Title of latest content published by current user
}
// Struct to hold reference of BaseContentManagementContracts with its author
// Title of content (a bytes32) is the identifier of content
struct ExtendedContent {
bool exists; // To check if a content exists in the system
address contractAddress; // Contract's address associated to current content
bytes32 author; // Name of owner of content
// Others informations, about views and users which are granted to access to current content, are stored in BaseContentManagementContracts
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment