Skip to main content

POTLOCK Lists Contract: Curated Lists, Registrations, and Upvotes

2025-09-22 · 10 min read

Lists contract

Lists are like Spotify playlists for NEAR accounts. Anyone can create a list; accounts can register or be added by owner/admins. Lists are used as eligibility criteria in pots (e.g. POTLOCK public goods registry is list_id = 1).

PotLock/core11Fork 4

Lists contract: github.com/PotLock/core/tree/main/contracts/lists. Example BOS SDK: PotLock/bos-app widget/SDK/lists.jsx.

View on GitHub →

Use cases

  • Curated playlists of projects for quick donate flows.
  • Membership and airdrop waitlists.
  • Custom explore pages; community signal via upvotes.
  • Donate-to-all flow for a basket of projects.
  • RetroPGF and eligibility in quadratic funding pots.

Roles

  • Owner: created the list; can add/remove admins, transfer ownership, update list, set default registration status, add/remove accounts in batches.
  • Admin: same as owner except add/remove other admins.
  • Registrant: can register/unregister if applications are open (no admin_only_registration).
  • User: can upvote lists; can apply to list if applications open.

General types

type RegistrantId = AccountId;
type RegistrationId = u64;
type ListId = u64;
type TimestampMs = u64;
List and registration identifiers.

ListInternal (stored)

pub struct ListInternal {
    pub name: String,                    // max 64
    pub description: Option<String>,    // max 256
    pub cover_img_url: Option<String>,  // https://
    pub owner: AccountId,
    pub created_at: TimestampMs,
    pub updated_at: TimestampMs,
    pub default_registration_status: RegistrationStatus,
    pub admin_only_registrations: bool,
}
List data stored on-chain.

RegistrationStatus

pub enum RegistrationStatus {
    Pending,
    Approved,
    Rejected,
    Graylisted,
    Blacklisted,
}
Status of a registrant on a list.

Write methods

#[payable]
pub fn create_list(
    &mut self,
    name: String,
    description: Option<String>,
    cover_image_url: Option<String>,
    admins: Option<Vec<AccountId>>,
    default_registration_status: RegistrationStatus,
    admin_only_registrations: Option<bool>,
) -> ListExternal

#[payable]
pub fn update_list(&mut self, list_id: ListId, name: Option<String>, ...) -> ListExternal
#[payable]
pub fn delete_list(&mut self, list_id: ListId)
#[payable]
pub fn upvote(&mut self, list_id: ListId)
#[payable]
pub fn remove_upvote(&mut self, list_id: ListId)
#[payable]
pub fn register_batch(&mut self, list_id: ListId, notes: Option<String>, registrations: Option<Vec<RegistrationInput>>) -> Vec<RegistrationExternal>
#[payable]
pub fn unregister(&mut self, list_id: Option<ListId>, registration_id: Option<RegistrationId>)
#[payable]
pub fn update_registration(&mut self, registration_id: RegistrationId, status: Option<RegistrationStatus>, notes: Option<String>) -> RegistrationExternal
List and registration writes. All require ≥1 yoctoNEAR.

Read methods

pub fn get_list(&self, list_id: ListId) -> ListExternal
pub fn get_lists(&self, from_index: Option<u64>, limit: Option<u64>) -> Vec<ListExternal>
pub fn get_lists_for_owner(&self, owner_id: AccountId) -> Vec<ListExternal>
pub fn get_lists_for_registrant(&self, registrant_id: AccountId) -> Vec<ListExternal>
pub fn get_upvotes_for_list(&self, list_id: ListId, ...) -> Vec<AccountId>
pub fn get_registrations_for_list(&self, list_id: ListId, status: Option<RegistrationStatus>, ...) -> Vec<RegistrationExternal>
pub fn is_registered(&self, list_id: Option<ListId>, account_id: RegistrantId, required_status: Option<RegistrationStatus>) -> bool
Paginated lists, registrations, and upvotes.

Events

"event": "create_list" | "update_list" | "delete_list" | "upvote" | "remove_upvote" | "update_admins" | "owner_transfer" | "create_registration" | "update_registration" | "delete_registration" | "set_source_metadata"
POTLOCK standard 1.0.0 events with data payloads.

Mainnet: lists.potlock.near. Staging: lists.staging.potlock.near. Public goods registry: list_id = 1. Full docs: docs.potlock.org/contracts/lists-live.