Created
June 10, 2018 10:58
-
-
Save dima91/dd886cd0c1ab3dbce2b2c79e710a8f84 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=false&gist=
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
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; | |
} | |
address private authorAddress; // Address of contract's author | |
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 | |
bytes32 private content; // Content of resource | |
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, bytes32 _cnt, address _catalogAddr) public { | |
typeOfContent = _conType; | |
authorAddress= msg.sender; | |
numberOfViews= 0; | |
contentTitle= _conTitle; | |
content= _cnt; | |
catalogAddress= _catalogAddr; | |
} | |
// ***** ***** // | |
// ***** Modifiers ***** // | |
modifier onlyCatalog () { | |
require (msg.sender == catalogAddress); | |
_; | |
} | |
modifier onlyAllowedUsers (bytes32 _username) { | |
require (allowedUsers[_username].accessType == AccessType.standardAccess || allowedUsers[_username].accessType == AccessType.premiumAccess); | |
_; | |
} | |
// ***** ***** // | |
// ***** 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 onlyAllowedUsers(_username) returns (bytes32) { | |
(CatalogSmartContract (catalogAddress)).notifyNewView (contentTitle, _username); | |
if (allowedUsers[_username].accessType == AccessType.standardAccess) | |
numberOfViews++; | |
allowedUsers[_username].accessType= AccessType.noneAccess; | |
return content; | |
} | |
// ***** ***** // | |
// ***** 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 () { | |
if (isPremium) | |
allowedUsers[_username].accessType= AccessType.premiumAccess; | |
else | |
allowedUsers[_username].accessType= AccessType.standardAccess; | |
allowedUsers[_username].userAddress= _userAddr; | |
} | |
// ***** ***** // | |
// ***** Abastract functions ***** // | |
function consumeContent (bytes32 _username) public returns (bytes32); | |
} | |
/* *************************************************************************************************************************************** */ | |
/* *************************************************************************************************************************************** */ | |
/* *************************************************************************************************************************************** */ | |
contract SongManagementContract is BaseContentManagementContract { | |
constructor (bytes32 _title, bytes32 _cnt, address _catAddr) | |
BaseContentManagementContract(SharedTypes.contentType.song, _title, _cnt, _catAddr) public { | |
} | |
function consumeContent (bytes32 _username) public returns (bytes32) { | |
return retrieveContent (_username); | |
} | |
} | |
/* ********************************************* */ | |
/* ********************************************* */ | |
/* ********************************************* */ | |
contract VideoManagementContract is BaseContentManagementContract { | |
constructor (bytes32 _title, bytes32 _cnt, address _catAddr) | |
BaseContentManagementContract(SharedTypes.contentType.video, _title, _cnt, _catAddr) public { | |
} | |
function consumeContent (bytes32 _username) public returns (bytes32) { | |
return retrieveContent (_username); | |
} | |
} | |
/* ********************************************* */ | |
/* ********************************************* */ | |
/* ********************************************* */ | |
contract PhotoManagementContract is BaseContentManagementContract { | |
constructor (bytes32 _title, bytes32 _cnt, address _catAddr) | |
BaseContentManagementContract(SharedTypes.contentType.photo, _title, _cnt, _catAddr) public { | |
} | |
function consumeContent (bytes32 _username) public returns (bytes32) { | |
return retrieveContent (_username); | |
} | |
} | |
/* ********************************************* */ | |
/* ********************************************* */ | |
/* ********************************************* */ | |
contract DocumentManagementContract is BaseContentManagementContract { | |
constructor (bytes32 _title, bytes32 _cnt, address _catAddr) | |
BaseContentManagementContract(SharedTypes.contentType.document, _title, _cnt, _catAddr) public { | |
} | |
function consumeContent (bytes32 _username) public returns (bytes32) { | |
return retrieveContent (_username); | |
} | |
} |
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
pragma solidity ^0.4.24; | |
contract C { | |
function bytes32ToString(bytes32 x) constant returns (string) { | |
bytes memory bytesString = new bytes(32); | |
uint charCount = 0; | |
for (uint j = 0; j < 32; j++) { | |
byte char = byte(bytes32(uint(x) * 2 ** (8 * j))); | |
if (char != 0) { | |
bytesString[charCount] = char; | |
charCount++; | |
} | |
} | |
bytes memory bytesStringTrimmed = new bytes(charCount); | |
for (j = 0; j < charCount; j++) { | |
bytesStringTrimmed[j] = bytesString[j]; | |
} | |
return string(bytesStringTrimmed); | |
} | |
function bytes32ArrayToString(bytes32[] data) returns (string) { | |
bytes memory bytesString = new bytes(data.length * 32); | |
uint urlLength; | |
for (uint i=0; i<data.length; i++) { | |
for (uint j=0; j<32; j++) { | |
byte char = byte(bytes32(uint(data[i]) * 2 ** (8 * j))); | |
if (char != 0) { | |
bytesString[urlLength] = char; | |
urlLength += 1; | |
} | |
} | |
} | |
bytes memory bytesStringTrimmed = new bytes(urlLength); | |
for (i=0; i<urlLength; i++) { | |
bytesStringTrimmed[i] = bytesString[i]; | |
} | |
return string(bytesStringTrimmed); | |
} | |
} |
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
pragma solidity ^0.4.24; | |
import "./sharedTypes.sol"; | |
import "./ownable.sol"; | |
import "./baseContentManagementContract.sol"; | |
import "./stringUtils.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 CatalogDied (); | |
// Duration of premium account (in block height) | |
uint constant PREMIUM_ACCOUNT_DURATION = 256; // ~20 blocks/hour | |
// Cost of premium account (wei) --> FIXME!!! | |
uint constant PREMIUM_ACCOUNT_COST= 100 wei; | |
// Cost of each single content --> FIXME!! | |
uint constant CONTENT_COST= 10 wei; | |
// Payout for author for each content access (this value have to be minor than CONTENT_COST) --> FIXME!! | |
uint constant PAYOUT_FOR_AUTHOR= 5 wei; | |
// Maximum number of views before sending payment | |
uint constant MAX_VIEWS_LIMIT= 2; | |
// 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, for each author, total number of view of their contents | |
mapping (bytes32 => uint) viewsPerAuthor; | |
// 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 | |
modifier alreadyPublishedM (bytes32 _contentTitle) { | |
require (alreadyPublished(_contentTitle) == true); | |
_; | |
} | |
modifier notPublished (bytes32 _contentTitle) { | |
require (alreadyPublished(_contentTitle) == false); | |
_; | |
} | |
modifier addressNotRegistered (address _address) { | |
require (addr2User[_address] == ""); // Sembra funzionare | |
_; | |
} | |
modifier userDoesntExist (bytes32 _username) { | |
require (userExists (_username) == false); | |
_; | |
} | |
modifier userExistsM (bytes32 _username) { | |
require (userExists(_username) == true); | |
_; | |
} | |
modifier isPremiumM (bytes32 _username) { | |
require (isPremium(_username) == true); | |
_; | |
} | |
modifier enoughValue (uint _msgValue, uint _lim) { | |
require (_msgValue == _lim); | |
_; | |
} | |
modifier userAllowed (bytes32 _username, bytes32 _contentTitle) { | |
require (contentsMapping[_contentTitle].allowedUsers[_username] == true); | |
_; | |
} | |
// ************************************************************************************************************** // | |
// ************************************************************************************************************** // | |
// 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 an user to system | |
function addUser (bytes32 _username, address _userAddr) userDoesntExist(_username) addressNotRegistered(_userAddr) private { | |
addr2User[_userAddr]= _username; | |
usersMapping[_username].userAddress= _userAddr; | |
usersMapping[_username].accType= SharedTypes.accountType.standard; | |
usersMapping[_username].exists= true; | |
usersMapping[_username].expirationTime= 0; | |
usersMapping[_username].latestContent = ""; | |
uint i= usersCount++; | |
usersArray[i]= _username; | |
emit NewUser (_username, _userAddr); | |
} | |
// 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); | |
} | |
// ************************************************************************************************************** // | |
// ************************************************************************************************************** // | |
// Public functions | |
function killMe () public onlyOwner() { | |
selfdestruct (owner); | |
// First of all, it distrubutes payments amog authors | |
uint i=0; | |
for (i=0; i<usersCount; i++) { | |
if (viewsPerAuthor[usersArray[i]] != 0) { | |
address userAddr= usersMapping[usersArray[i]].userAddress; | |
userAddr.transfer (viewsPerAuthor[usersArray[i]] * PAYOUT_FOR_AUTHOR); | |
} | |
} | |
emit CatalogDied (); | |
} | |
// 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; | |
viewsPerAuthor[author]++; | |
if (viewsPerAuthor[author] == MAX_VIEWS_LIMIT) { | |
address rcvAddr= usersMapping[author].userAddress; | |
rcvAddr.transfer (MAX_VIEWS_LIMIT * PAYOUT_FOR_AUTHOR); | |
viewsPerAuthor[author] = 0; | |
} | |
contentsMapping[_contentTitle].allowedUsers[_username]= false; | |
} | |
// FIXME DELETE ME!!!! | |
function getBalance () public view returns (uint) { | |
return address (this).balance; | |
} | |
// ************************************************************************************************************** // | |
// ************************************************************************************************************** // | |
// 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 []) { | |
bytes32 [] memory newest; | |
uint i= 0; | |
uint count=0; | |
if (_n>contentsCount) | |
count=contentsCount; | |
else | |
count=_n; | |
while (count!=0) { | |
newest[i]= 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; | |
} | |
// 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); | |
} | |
// ************************************************************************************************************** // | |
// ************************************************************************************************************** // | |
// Pays for access to content x (NOT ACCESS TO CONTENT!) | |
function getContent (bytes32 _contentTitle) userExistsM(addr2User[msg.sender]) alreadyPublishedM (_contentTitle) enoughValue (msg.value, CONTENT_COST) public payable returns (address) { | |
// ******* --> Check preconditions (enough value..) + handle payments <-- ******* | |
bytes32 senderUser= addr2User[msg.sender]; | |
(BaseContentManagementContract (contentsMapping[_contentTitle].contractAddress)).grantAccessToUser (senderUser, msg.sender, false); | |
contentsMapping[_contentTitle].allowedUsers[senderUser]= true; | |
emit GrantedAccess (senderUser, msg.sender, _contentTitle, contentsMapping[_contentTitle].contractAddress); | |
return contentsMapping[_contentTitle].contractAddress; | |
} | |
// Requests access to content x without paying, premium accounts only | |
function getContentPremium (bytes32 _contentTitle) isPremiumM (addr2User[msg.sender]) alreadyPublishedM (_contentTitle) public returns (address) { | |
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); | |
return contentsMapping[_contentTitle].contractAddress; | |
} | |
// Pays for granting access for content x to the user u | |
function giftContent (bytes32 _contentTitle, bytes32 _receivingUser) userExistsM(_receivingUser) alreadyPublishedM (_contentTitle) enoughValue (msg.value, CONTENT_COST) public payable returns (address) { | |
// ******* --> Check preconditions (enough value..) + handle payments <-- ******* | |
(BaseContentManagementContract (contentsMapping[_contentTitle].contractAddress)).grantAccessToUser (_receivingUser, usersMapping[_receivingUser].userAddress, false); | |
contentsMapping[_contentTitle].allowedUsers[_receivingUser]= true; | |
emit GrantedAccess (_receivingUser, usersMapping[_receivingUser].userAddress, _contentTitle, contentsMapping[_contentTitle].contractAddress); | |
return contentsMapping[_contentTitle].contractAddress; | |
} | |
// Pays for granting a Premium Account to the user u | |
function giftPremium (bytes32 _receivingUser) userExistsM(_receivingUser) enoughValue (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; | |
} | |
// Starts a new premium subscription | |
function buyPremium () userExistsM(addr2User[msg.sender]) enoughValue (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; | |
} | |
} |
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
pragma solidity ^0.4.24; | |
import "./baseContentManagementContract.sol"; | |
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
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); | |
} | |
} |
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
pragma solidity ^0.4.24; | |
contract Mortal { | |
address owner; | |
constructor () public { | |
owner= msg.sender; | |
} | |
function kill () public { | |
if (msg.sender == owner) | |
selfdestruct (owner); | |
} | |
} |
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
pragma solidity ^0.4.24; | |
contract Ownable { | |
address owner; | |
constructor () public { | |
owner = msg.sender; | |
} | |
modifier onlyOwner () { | |
require (msg.sender == owner); | |
_; | |
} | |
} |
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
pragma solidity ^0.4.24; | |
library StringUtils { | |
/// @dev Does a byte-by-byte lexicographical comparison of two strings. | |
/// @return a negative number if `_a` is smaller, zero if they are equal | |
/// and a positive numbe if `_b` is smaller. | |
function compare(string _a, string _b) private pure returns (int) { | |
bytes memory a = bytes(_a); | |
bytes memory b = bytes(_b); | |
uint minLength = a.length; | |
if (b.length < minLength) minLength = b.length; | |
//@todo unroll the loop into increments of 32 and do full 32 byte comparisons | |
for (uint i = 0; i < minLength; i ++) | |
if (a[i] < b[i]) | |
return -1; | |
else if (a[i] > b[i]) | |
return 1; | |
if (a.length < b.length) | |
return -1; | |
else if (a.length > b.length) | |
return 1; | |
else | |
return 0; | |
} | |
/// @dev Compares two strings and returns true iff they are equal. | |
function equal(string _a, string _b) public pure returns (bool) { | |
return compare(_a, _b) == 0; | |
} | |
/// @dev Finds the index of the first occurrence of _needle in _haystack | |
function indexOf(string _haystack, string _needle) public pure returns (int) | |
{ | |
bytes memory h = bytes(_haystack); | |
bytes memory n = bytes(_needle); | |
if(h.length < 1 || n.length < 1 || (n.length > h.length)) | |
return -1; | |
else if(h.length > (2**128 -1)) // since we have to be able to return -1 (if the char isn't found or input error), this function must return an "int" type with a max length of (2^128 - 1) | |
return -1; | |
else | |
{ | |
uint subindex = 0; | |
for (uint i = 0; i < h.length; i ++) | |
{ | |
if (h[i] == n[0]) // found the first char of b | |
{ | |
subindex = 1; | |
while(subindex < n.length && (i + subindex) < h.length && h[i + subindex] == n[subindex]) // search until the chars don't match or until we reach the end of a or b | |
{ | |
subindex++; | |
} | |
if(subindex == n.length) | |
return int(i); | |
} | |
} | |
return -1; | |
} | |
} | |
// Function to convert a bytes32 to a string | |
function bytes32ToString (bytes32 x) public pure returns (string) { | |
bytes memory bytesString = new bytes(32); | |
uint charCount = 0; | |
for (uint j = 0; j < 32; j++) { | |
byte char = byte(bytes32(uint(x) * 2 ** (8 * j))); | |
if (char != 0) { | |
bytesString[charCount] = char; | |
charCount++; | |
} | |
} | |
bytes memory bytesStringTrimmed = new bytes(charCount); | |
for (j = 0; j < charCount; j++) { | |
bytesStringTrimmed[j] = bytesString[j]; | |
} | |
return string(bytesStringTrimmed); | |
} | |
// Function to convert a string to bytes32 | |
function stringToBytes32(string memory source) public pure returns (bytes32 result) { | |
bytes memory tempEmptyStringTest = bytes(source); | |
if (tempEmptyStringTest.length == 0) { | |
return 0x0; | |
} | |
assembly { | |
result := mload(add(source, 32)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment