forked from weifund/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
22e7082
commit 784f964
Showing
35 changed files
with
926 additions
and
22 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
The WeiFund platform isn't running on magic. There is a fantastic development team and community behind us, that includes the Ethereum and broader blockchain and crowdfunding communities. | ||
|
||
Weifund is part of the network of ConsenSys projects, and organization that has been a long time supporter of the Ethereum ecosystem and the WeiFund platform. You can read more about ConsenSys and how awesome everyone is at [http://consensys.net](http://consensys.net). | ||
|
||
##Community | ||
* [r/ethereum](https://www.reddit.com/r/ethereum/) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
The WeiFund Campaign Registry allows to register your campaign contact address and the address of any additional interface contract, if needed. Each campaign can only be registered once by the owner (owner():(address ownerAccount)) of the campaign. Ensure that you both have access to the owner account of the contract and that you register the campaign from that account. The campaign registry allows you to get the ID of campaigns registered (i.e. using the “idOf(address)” method) as well as the address of a campaign ID (i.e. using the “addressOf(uint256 id”). | ||
|
||
``` | ||
import "Owner.sol"; | ||
contract CampaignRegistryInterface { | ||
function register(address _campaign, address _interface) returns (uint256 campaignID); | ||
function idOf(address _campaign) constant returns (uint256 campaignID); | ||
function interfaceOf(uint256 _campaignID) constant returns (address interface); | ||
function registeredAt(uint256 _campaignID) constant returns (uint256 registered); | ||
function addressOf(uint256 _campaignID) constant returns (address campaign); | ||
function numCampaigns() constant returns (uint256 count); | ||
} | ||
contract CampaignRegistry is CampaignRegistryInterface { | ||
modifier validRegistration(address _campaign) { | ||
// campaign owner is sender | ||
if (Owner(_campaign).owner() != msg.sender) { | ||
throw; | ||
} | ||
// prevent double registrations | ||
if (campaigns.length > 0) { | ||
if (campaigns[ids[_campaign]].addr == _campaign) { | ||
throw; | ||
} | ||
} | ||
_ | ||
} | ||
function () { | ||
throw; | ||
} | ||
function register(address _campaign, address _interface) validRegistration(_campaign) returns (uint256 campaignID) { | ||
campaignID = campaigns.length++; | ||
ids[_campaign] = campaignID; | ||
campaigns[campaignID] = Campaign({ | ||
addr: _campaign, | ||
interface: _interface, | ||
registered: now | ||
}); | ||
CampaignRegistered(_campaign, _interface, campaignID); | ||
} | ||
function idOf(address _campaign) constant returns (uint256 campaignID) { | ||
return ids[_campaign]; | ||
} | ||
function interfaceOf(uint256 _campaignID) constant returns (address interface) { | ||
return campaigns[_campaignID].interface; | ||
} | ||
function registeredAt(uint256 _campaignID) constant returns (uint256 registered) { | ||
return campaigns[_campaignID].registered; | ||
} | ||
function addressOf(uint256 _campaignID) constant returns (address campaign) { | ||
return campaigns[_campaignID].addr; | ||
} | ||
function numCampaigns() constant returns (uint256 count) { | ||
return campaigns.length; | ||
} | ||
struct Campaign { | ||
address addr; | ||
address interface; | ||
uint256 registered; | ||
} | ||
mapping(address => uint) public ids; | ||
Campaign[] public campaigns; | ||
event CampaignRegistered(address _campaign, address _interface, uint256 _campaignID); | ||
} | ||
``` | ||
##Contract Overview | ||
The WeiFund campaign registry contract is the central store for all campaign contracts listed and accessible on the platform. All campaigns must be registered through this registry before being listed on WeiFund. | ||
|
||
The registry immediately throws an error if the fallback function is called (i.e. any time a method that is not in the contract is called). | ||
|
||
The contract contains a central modifier to check the validity of a campaign registration (i.e. validRegistration). This checks if the campaign has not already been registered and that the campaign contract owner (i.e. owner()) account is the registration sender (I.e the “msg.sender”). | ||
|
||
The contract has a single state changing method (i.e. “register”). This method is used to register campaign contact address and if needed, an interface contract address. Note, the interface contract address is only required if your campaign does not follow the WeiFund campaign contract specification. | ||
|
||
The registry has a range of simple constant information retrieval getter methods, such as getting the campaign ID of a campaign address registered “idOf”, the campaign address of a campaign ID registered “addressOf”, the number of campaigns registered “numCampaigns”, the time at which a campaign was registered “registeredAt” and the interface contract address of registered campaign ID, if any “interfaceOf”. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
The WeiFund Standard Campaign only handles the intake of contributions, and the output of either campaign payout to the beneficiary account. If the campaign is a success or if the funding goal is specified above zero, refund functionality for contributors to receive a refund if the campaign is a failure. | ||
|
||
The WeiFund StandardCampaign uses a tightly enforced state machine design specified in “modifier atStageOr” on all state changing contract methods. This state machine is stated as a modifier which ensures the campaign is in one of three phases or contract stages. There are only three stages a StandardCamapign can be in. The contract is either in the (0) “operational”, (1) “failure” or (2) “success” stage. | ||
|
||
The contract cannot be in any other stage. The contract is in the operational stage, if the current block timestamp is less than the expiry UNIX timestamp specified at the time of contract creation. | ||
|
||
The contract is in the “success” stage, if the current block UNIX timestamp is greater than or equal to the expiry UNIX timestamp stated at contract creation, the amount raised by contributions is greater than or equal to the funding goal and the funding goal is greater than zero. | ||
|
||
A contributor may only contribute to the StandardCampaign if is in the (0) “operational” stage. A contributor may only receive payouts if the campaign is in the (1) “failure” stage. A campaign can only be payed out if it is in the (2) “success” stage. | ||
|
||
The StandardCampaign allows anyone to use the contract fallback function as a contribution method. While this is not a recommended best practice in the “Ethereum Best Practices Doc”, it allows the use of QR codes to send Ether to campaigns which is a very popular feature for many Ethereum and WeiFund users. | ||
|
||
If the contract funding goal is set to zero, this means the campaign will never hit stage “failure” (1). Any StandardCampaign with a funding goal (“fundingGoal()”) set to zero will be considered an open StandardCampaign, which means it never fails and the refund functionality can never be used on the campaign contract. | ||
|
||
The contribution method “contributeMsgValue” simple notates the contribution made and intakes the msg.value (i.e. the Ether sent to the campaign contract). Because all contributions are notated and registered as a contribution instance, this allows third-party services to be constructed and connected with the campaign, that can use the contribution creation time, sender and amount metrics as a way of determining reward or contract logic. Essentially, it's a design model chosen on purpose to allow for other services to build fairly comprehensive third-party services such as: token or product dispersal both during and after a campaign has ended. | ||
|
||
The payout method “payoutToBeneficiary” simply pays out the funds of the campaign out to the beneficiary account address specified. This could be anything from a vanilla Ethereum account, to a multi-signature wallet or governance structure such as a Board (see: BoardRoom.to). | ||
|
||
The refund method “claimRefundOwed” simply pays out the refund of a specific campaign contribution. Only the contributor who made the contribution can initiate the refund claim of that Ether as a refund. Only one refund claim can be made by the rightful refund recipient per each contribution made. This means you only get one shot at refunding each contribution, so please ensure you have enough gas in your transaction and that you have properly specified the refund contribution information. The method requires to to provide a single method input stating the contribution ID as a uint256 (unsigned integer 256). The WeiFund user interface does this for you, but if you would like to do the refund through a wallet or command line system, this is the required single input. Please ensure that you are the contribution sender of the refund you are trying to claim. Only the contribution sender may refund their own contribution if the campaign is in the failure state. | ||
|
||
The total contributions constant method “totalContributions” is a simple method which describes the total number of contributions made to the campaign. | ||
|
||
The total contributions by sender method “totalContributionsBySender” is a simple method which describes the total number of contributions made by a single contributor account to the campaign contract. | ||
|
||
The contribution data structure “Contribution” is a rudimentary data structure which helps organize contribution data, such as the contribution sender, value contributed and creation date (as a UNIX standard timestamp). |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
|
||
The WeiFund platform both uses and recommends a set of contract registries and templates. WeiFUnd offers a standard campaign template, a campaign registry to register campaigns and their interface contracts (if any), a campaign data registry to register additional campaign data (such as descriptions, website links, images and videos) and a standard interface contract which campaigns must follow in order to be listed. | ||
|
||
##Design Philosophy and Practices | ||
The WeiFund platform attempts to build contracts in an atomic manner. It's current construction features several simple registries, meeting a very specific concern, and a standard campaign template to help people start campaigns on WeiFund. In essence we design contracts in general accordance with the ConsenSys “Smart Contract Best Practices” document [provide link] and the UNIX coding design philosophy [provide link] |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
The WeiFund Standard Campaign contract template allows anyone to create, deploy and reap the benefits of a crowdfunding campaign that follows the WeiFund contract standard campaign specifications. | ||
|
||
```javascript | ||
import "../Campaign.sol"; | ||
import "../Owner.sol"; | ||
|
||
contract StandardCampaign is Owner, Campaign { | ||
enum Stages { | ||
CrowdfundOperational, | ||
CrowdfundFailure, | ||
CrowdfundSuccess | ||
} | ||
|
||
modifier atStageOr(uint256 _expectedStage) { | ||
if (now < expiry) { | ||
stage = uint256(Stages.CrowdfundOperational); | ||
} else if(now >= expiry && amountRaised < fundingGoal) { | ||
stage = uint256(Stages.CrowdfundFailure); | ||
} else if(now >= expiry && amountRaised >= fundingGoal) { | ||
stage = uint256(Stages.CrowdfundSuccess); | ||
} | ||
|
||
if (stage != _expectedStage) { | ||
throw; | ||
} | ||
_ | ||
} | ||
|
||
function () { | ||
contributeMsgValue(); | ||
} | ||
|
||
function contributeMsgValue() atStageOr(uint(Stages.CrowdfundOperational)) public returns (uint256 contributionID) { | ||
contributionID = contributions.length++; | ||
contributions[contributionID] = Contribution({ | ||
sender: msg.sender, | ||
value: msg.value, | ||
created: now | ||
}); | ||
contributionsBySender[msg.sender].push(contributionID); | ||
amountRaised += msg.value; | ||
ContributionMade(msg.sender); | ||
} | ||
|
||
function payoutToBeneficiary() atStageOr(uint(Stages.CrowdfundSuccess)) public returns (uint256 amountClaimed) { | ||
amountClaimed = this.balance; | ||
if (!beneficiary.send(amountClaimed)) { | ||
throw; | ||
} | ||
BeneficiaryPayoutClaimed(beneficiary, amountClaimed); | ||
} | ||
|
||
function StandardCampaign(string _name, | ||
uint256 _expiry, | ||
uint256 _fundingGoal, | ||
address _beneficiary, | ||
address _owner) { | ||
name = _name; | ||
expiry = _expiry; | ||
fundingGoal = _fundingGoal; | ||
beneficiary = _beneficiary; | ||
owner = _owner; | ||
} | ||
|
||
function totalContributions() public constant returns (uint256 amount) { | ||
return contributions.length; | ||
} | ||
|
||
function totalContributionsBySender(address _sender) public constant returns (uint256 amount) { | ||
return contributionsBySender[_sender].length; | ||
} | ||
|
||
struct Contribution { | ||
address sender; | ||
uint256 value; | ||
uint256 created; | ||
} | ||
|
||
uint256 public stage; | ||
uint256 public fundingGoal; | ||
uint256 public amountRaised; | ||
uint256 public expiry; | ||
address public beneficiary; | ||
Contribution[] public contributions; | ||
mapping(address => uint256[]) public contributionsBySender; | ||
|
||
string public name; | ||
string public version = "1.0.0"; | ||
string public contributeMethodABI = "contributeMsgValue():(uint256 contributionID)"; | ||
string public payoutMethodABI = "payoutToBeneficiary():(uint256 amountClaimed)"; | ||
} | ||
``` |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
The WeiFund platform allows campaigns to register additional cosmetic non-blockchain campaign data, this is data that tightly conforms to the WeiFund campaign data specification [provide link]. | ||
|
||
``` | ||
import "Owner.sol"; | ||
contract CampaignDataRegistryInterface { | ||
/// @notice call `register` to register your campaign with a specified data store | ||
/// @param _campaign the address of the crowdfunding campaign | ||
/// @param _data the data store of that campaign, potentially an ipfs hash | ||
function register(address _campaign, bytes _data) { | ||
/// @notice call `storedDate` to retrieve data specified for a campaign address | ||
/// @param _campaign the address of the crowdfunding campaign | ||
/// @return the data stored in bytes | ||
function storedData(address _campaign) constant returns (bytes dataStored); | ||
event CampaignDataRegistered(address _campaign); | ||
} | ||
contract CampaignDataRegistry is CampaignDataRegistryInterface { | ||
modifier senderIsCampaignOwner(address _campaign) { | ||
if(Owner(_campaign).owner() != msg.sender) { | ||
throw; | ||
} | ||
} | ||
function () { | ||
throw; | ||
} | ||
function register(address _campaign, bytes _data) senderIsCampaignOwner(_campaign) { | ||
data[_campaign] = _data; | ||
CampaignDataRegistered(_campaign); | ||
} | ||
function storedData(address _campaign) constant returns (bytes dataStored) { | ||
return data[_campaign]; | ||
} | ||
mapping(address => bytes) data; | ||
} | ||
``` | ||
|
||
##Contract Overview | ||
The WeiFund campaign data registry allows any campaign owner (i.e. owner()) to specify additional cosmetic campaign data which enhances the campaign listing, viewing, contribution, refund and payout experiences on the WeiFund user interfaces. | ||
|
||
The registry will automatically throw a EVM error if any method except “storedData” or “register” is used. | ||
The register has a central registry method where campaign owners can register additional cosmetic campaign data to their campaign. The owners may do this multiple times. Presently, the data registered must be a n IPFS hash that has been properly formatted and converted to base58 hex code. The WeiFund UI will determine the nature of the data registered (i.e. if the data is an IPFS hash). If successful, the “CampaignDataRegistered” event will fire. | ||
|
||
The stored data method “storedData” returns the data stored for a specific campaign by the campaign owner. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
The WeiFund campaign interface contract contains all essential method requirements. We recommend that your main campaign contract inherit this contract interface and follow it tightly. If you choose not to do this, then you must provide a side interface contract and register that alongside your campaign in the WeiFund Campaign Registry. Please ensure you have deployed and registered your campaign on the WeiFund Testnet portal or client and that you have gone through the contribution and refund flows successfully before registering your campaign on the WeiFund standard registry. | ||
|
||
``` | ||
contract Campaign { | ||
/// @notice the owner or campaign operator of the campaign | ||
/// @return the Ethereum standard account address of the owner specified | ||
function owner() constant returns(address) {} | ||
/// @notice the campaign interface version | ||
/// @return the version metadata | ||
function version() constant returns(string) {} | ||
/// @notice the campaign name | ||
/// @return contractual metadata which specifies the campaign name as a string | ||
function name() constant returns(string) {} | ||
/// @notice use to determine the contribution method abi/structure | ||
/// @return will return a string that is the exact contributeMethodABI | ||
function contributeMethodABI() constant returns(string) {} | ||
/// @notice use to determine the contribution method abi | ||
/// @return will return a string that is the exact contributeMethodABI | ||
function refundMethodABI() constant returns(string) {} | ||
/// @notice use to determine the contribution method abi | ||
/// @return will return a string that is the exact contributeMethodABI | ||
function payoutMethodABI() constant returns(string) {} | ||
/// @notice use to determine the beneficiary destination for the campaign | ||
/// @return the beneficiary address that will receive the campaign payout | ||
function beneficiary() constant returns(address) {} | ||
/// @notice the time at which the campaign fails or succeeds | ||
/// @return the uint unix timestamp at which time the campaign expires | ||
function expiry() constant returns(uint256 timestamp) {} | ||
/// @notice the goal the campaign must reach in order for it to succeed | ||
/// @return the campaign funding goal specified in wei as a uint256 | ||
function fundingGoal() constant returns(uint256 amount) {} | ||
/// @notice the goal the campaign must reach in order for it to succeed | ||
/// @return the campaign funding goal specified in wei as a uint256 | ||
function amountRaised() constant returns(uint256 amount) {} | ||
// Campaign events | ||
event ContributionMade (address _contributor); | ||
event RefundPayoutClaimed(address _payoutDestination, uint256 _payoutAmount); | ||
event BeneficiaryPayoutClaimed (address _payoutDestination, uint256 _payoutAmount); | ||
} | ||
``` | ||
##Contract Overview | ||
The WeiFund Interface contract follows the WeiFund campaign contract specification [provide link]. Please see that for details on method information. | ||
|
||
The contract also contains a range of events to enhance user experience. This includes a “ContributionMade” event which should be fired when a contribution was made successfully, “RefundPayoutClaimed” which should be fired when a refund was claimed successfully and a “BenificaryPayoutClaimed” which should be fired when the campaign payout was transacted successfully. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
##Github | ||
WeiFund is an open source project.The core development team accepts code commits from all developers. Please submit your code commit to anyone of our github repositories found at [http://github.com/weifund](http://github.com/weifund). Please ensure before committing any code, that you carefully review and follow the WeiFund code of conduct, issue or pull request templates (PR), and that you read over our licence requirements. | ||
|
||
**Licence**<br/> | ||
[https://github.com/weifund/weifund-contracts/blob/master/LICENSE](https://github.com/weifund/weifund-contracts/blob/master/LICENSE) | ||
|
||
**Code of Conduct**<br/> | ||
[https://github.com/weifund/weifund-lib/blob/master/CODE_OF_CONDUCT.md](https://github.com/weifund/weifund-lib/blob/master/CODE_OF_CONDUCT.md) | ||
|
||
**Issue or Pull Request Templates**<br/> | ||
[https://github.com/weifund/weifund-lib/blob/master/CONTRIBUTING.md](https://github.com/weifund/weifund-lib/blob/master/CONTRIBUTING.md) |
Binary file not shown.
Oops, something went wrong.