A single contract for raising for a specific initiative with optional time or target based restraints
Campaigns on POTLOCK provide a structured way to raise funds for specific initiatives associated with an account, with optional minimum escrowed targets.
Overview of Campaigns
Campaigns serve as a vehicle for raising funds toward defined goals or initiatives. They introduce minimum funding targets and operate within a specified timeframe, allowing for refunds if the target is not met. This feature encourages community engagement and provides clarity on funding purposes, making it ideal for both individual projects and broader organizational objectives.
Use Cases
Targeted Fundraising: Raise funds specifically for initiatives like events, projects, or community support.
Supporting Organizations: Individuals can create campaigns on behalf of organizations to expand outreach and impact.
Community Engagement: Enable fans and supporters to contribute towards their favorite projects, fostering a sense of ownership and participation.
Features of Campaigns
Single Currency Support: Each campaign can support only one currency at a time, simplifying transactions.
Beneficiary Approval: The beneficiary (the project or organization being funded) can officially approve the campaign, ensuring transparency.
Escrow Functionality: Donations may be held in escrow until the minimum target is reached; if not met, donors are refunded.
Referral Opportunities: Campaign creators can leverage optional referral systems to encourage more community participation in fundraising efforts.
Contract Structure
The POTLOCK Campaign Contract is designed to facilitate fundraising through donations while managing escrow functionalities based on specified targets.
General Types
type CampaignId = u64;
type DonationId = u64;
type TimestampMs = u64;
type ReferrerPayouts = HashMap<AccountId, Balance>;
CampaignId: Unique identifier for each campaign.
DonationId: Unique identifier for each donation instance.
TimestampMs: Represents time in milliseconds.
Contract Fields
The main contract structure includes several key fields:
owner: The account that created the campaign.
admins: Accounts with administrative privileges over the campaign.
next_campaign_id: Tracks the ID assigned to the next campaign created.
campaigns_by_id: Maps campaign IDs to their details.
donations_by_id: Maps donation IDs to their details.
escrowed_donation_ids_by_campaign_id: Maps campaign IDs to donations held in escrow.
The contract includes several methods for managing campaigns:
create_campaign(): Initializes a new campaign with specified details.
update_campaign(): Allows owners to modify existing campaign details.
delete_campaign(): Removes a campaign from existence.
NB: ALL privileged write methods (those beginning with admin_* or owner_*) require an attached deposit of at least one yoctoNEAR, for security purposes.
// INIT
pub fn new(
owner: AccountId,
protocol_fee_basis_points: u32,
protocol_fee_recipient_account: AccountId,
default_referral_fee_basis_points: u32,
default_creator_fee_basis_points: u32,
source_metadata: ContractSourceMetadata,
) -> Self {
// Campaign
#[payable]
pub fn create_campaign(
&mut self,
name: String,
description: Option<String>,
cover_image_url: Option<String>,
recipient: AccountId,
start_ms: TimestampMs,
end_ms: Option<TimestampMs>,
ft_id: Option<AccountId>,
target_amount: U128,
min_amount: Option<U128>,
max_amount: Option<U128>,
referral_fee_basis_points: Option<u32>,
creator_fee_basis_points: Option<u32>,
allow_fee_avoidance: Option<bool>,
) -> CampaignExternal
#[payable]
pub fn update_campaign(
&mut self,
campaign_id: CampaignId,
name: Option<String>,
description: Option<String>,
cover_image_url: Option<String>,
start_ms: Option<TimestampMs>,
end_ms: Option<TimestampMs>,
ft_id: Option<AccountId>,
target_amount: Option<Balance>,
max_amount: Option<Balance>,
min_amount: Option<U128>, // Can only be provided if campaign has not started yet
allow_fee_avoidance: Option<bool>,
// NB: recipient cannot be updated. If incorrect recipient is specified, campaign should be deleted and recreated
) -> CampaignExternal {
pub fn delete_campaign(&mut self, campaign_id: CampaignId)
// Donation
#[payable]
pub fn donate(
&mut self,
campaign_id: CampaignId,
message: Option<String>,
referrer_id: Option<AccountId>,
bypass_protocol_fee: Option<bool>,
bypass_creator_fee: Option<bool>,
) -> PromiseOrValue<DonationExternal> {
// STORAGE
pub fn storage_deposit(&mut self) -> U128
pub fn storage_withdraw(&mut self, amount: Option<U128>) -> U128
// OWNER
#[payable]
pub fn owner_change_owner(&mut self, owner: AccountId)
pub fn owner_add_admins(&mut self, admins: Vec<AccountId>)
pub fn owner_remove_admins(&mut self, admins: Vec<AccountId>)
pub fn owner_clear_admins(&mut self)
// SOURCE METADATA
pub fn self_set_source_metadata(&mut self, source_metadata: ContractSourceMetadata) // only callable by the contract account (reasoning is that this should be able to be updated by the same account that can deploy code to the account)
Donation Methods
Users can donate through:
donate(): Allows users to contribute funds to an active campaign, specifying optional messages or referrer IDs.
Read Methods
The contract provides various read methods:
get_campaign(): Retrieves details of a specific campaign by ID.
get_campaigns_by_owner(): Lists all campaigns created by a specific account.
get_donations_for_campaign(): Provides all donations made towards a specific campaign.
Events are emitted during significant actions within the contract:
A campaign_create event indicates that a new Campaign object has been created.
This structured overview provides a comprehensive understanding of how campaigns function within POTLOCK, detailing their purpose, features, contract structure, and methods effectively.