Розробка платформи крипто-краудфандингу
Принципова різниця між крипто-краудфандингом та ICO: у краудфандингу бэкери фінансують конкретний продукт або проект, а не купують спекулятивний токен. Kickstarter модель — творець обіцяє щось зробити, отримує гроші заздалегідь. У крипто версії смарт-контракт утримує кошти в escrow та відпускає їх за милestones — це усуває центрального посередника-платіжного оператора та робить повернення коштів автоматичним при недосягненні цілі.
Ключові відмінності від класичного ICO контракту
Краудфандинг має специфічну механіку, якої немає в простому token sale:
Milestone-based funding — кошти не переходять до творця одразу. Після кожного milestone відпускається частина коштів. Бэкери можуть голосувати за відмову від виплати якщо milestone не виконаний.
Rewards замість токенів — типова reward-based кампанія (Kickstarter модель): бэкер отримує фізичний або цифровий продукт, не фінансовий інструмент. Це уникає регулювання як securities.
Refund при недосягненні softcap — обов'язковий механізм. Без нього це не краудфандинг, а передоплата з високим ризиком для покупця.
Creator accountability — на відміну від ICO де команда отримує гроші та зникає, краудфандинг включає механізми accountability: milestone верифікацію, можливість vote to refund при недобросовісній поведінці.
Смарт-контракт: Campaign та Escrow
contract CrowdfundingCampaign {
enum Status { Active, Successful, Failed, Cancelled }
struct Milestone {
string description;
uint256 fundsToRelease; // кошти при досягненні
uint256 deadline;
bool isCompleted;
bool isFailed;
uint256 approvalVotes; // бэкери голосують за підтвердження
uint256 rejectionVotes;
mapping(address => bool) hasVoted;
}
address public creator;
uint256 public softcap;
uint256 public hardcap;
uint256 public deadline;
uint256 public totalRaised;
Status public status;
Milestone[] public milestones;
mapping(address => uint256) public contributions;
IERC20 public paymentToken; // USDC/USDT для стабільної суми
function contribute(uint256 amount) external {
require(status == Status.Active, "Campaign not active");
require(block.timestamp < deadline, "Campaign ended");
require(totalRaised + amount <= hardcap, "Hardcap reached");
paymentToken.transferFrom(msg.sender, address(this), amount);
contributions[msg.sender] += amount;
totalRaised += amount;
// Якщо hardcap досягнуто — завершуємо кампанію
if (totalRaised >= hardcap) {
status = Status.Successful;
}
emit ContributionReceived(msg.sender, amount, totalRaised);
}
function finalizeCampaign() external {
require(block.timestamp >= deadline, "Deadline not reached");
require(status == Status.Active, "Already finalized");
if (totalRaised >= softcap) {
status = Status.Successful;
// Перший milestone починає відлік
milestones[0].deadline = block.timestamp + milestones[0].duration;
emit CampaignSuccessful(totalRaised);
} else {
status = Status.Failed;
emit CampaignFailed(totalRaised, softcap);
}
}
// Тільки при Failed статусі
function claimRefund() external {
require(status == Status.Failed || status == Status.Cancelled, "Not refundable");
uint256 amount = contributions[msg.sender];
require(amount > 0, "Nothing to refund");
contributions[msg.sender] = 0;
paymentToken.transfer(msg.sender, amount);
emit RefundClaimed(msg.sender, amount);
}
}
Milestone Governance: бэкери як контролери
function approveMilestone(uint256 milestoneIndex) external {
require(contributions[msg.sender] > 0, "Not a backer");
Milestone storage milestone = milestones[milestoneIndex];
require(!milestone.hasVoted[msg.sender], "Already voted");
require(!milestone.isCompleted && !milestone.isFailed, "Already resolved");
milestone.hasVoted[msg.sender] = true;
// Вага голосу пропорційна внеску
milestone.approvalVotes += contributions[msg.sender];
_checkMilestoneResolution(milestoneIndex);
}
function rejectMilestone(uint256 milestoneIndex) external {
require(contributions[msg.sender] > 0, "Not a backer");
Milestone storage milestone = milestones[milestoneIndex];
require(!milestone.hasVoted[msg.sender], "Already voted");
milestone.hasVoted[msg.sender] = true;
milestone.rejectionVotes += contributions[msg.sender];
_checkMilestoneResolution(milestoneIndex);
}
function _checkMilestoneResolution(uint256 index) internal {
Milestone storage milestone = milestones[index];
uint256 APPROVAL_THRESHOLD = 5000; // 50% від totalRaised
uint256 REJECTION_THRESHOLD = 3300; // 33% достатньо для reject
if (milestone.approvalVotes * 10000 / totalRaised >= APPROVAL_THRESHOLD) {
milestone.isCompleted = true;
// Переводимо кошти творцю
paymentToken.transfer(creator, milestone.fundsToRelease);
emit MilestoneApproved(index, milestone.fundsToRelease);
} else if (milestone.rejectionVotes * 10000 / totalRaised >= REJECTION_THRESHOLD) {
milestone.isFailed = true;
// Решта коштів доступна для рефанду
status = Status.Cancelled;
emit MilestoneRejected(index);
}
}
Важливий нюанс по голосуванню: поріг одобрення vs відхилення асиметричен. Для одобрення потрібна більшість (50%+), для відхилення — менший поріг (33%). Це захист від того, що творець привернув своїх людей для голосування за себе.
NFT як reward tier
Крипто-краудфандинг часто комбінує з NFT: кожен tier взносу — унікальний NFT:
contract CampaignRewards is ERC721 {
struct RewardTier {
uint256 minContribution;
uint256 maxSupply;
uint256 minted;
string metadataURI; // IPFS URI з описом reward
}
RewardTier[] public tiers;
mapping(address => uint256) public backerTier;
// Вишивається при внеску або після завершення кампанії
function mintRewardNFT(address backer, uint256 contribution) internal {
// Визначаємо tier за розміром взносу
uint256 tierIndex = _getTierForAmount(contribution);
RewardTier storage tier = tiers[tierIndex];
require(tier.minted < tier.maxSupply, "Tier sold out");
uint256 tokenId = _nextTokenId++;
_safeMint(backer, tokenId);
_setTokenURI(tokenId, tier.metadataURI);
tier.minted++;
backerTier[backer] = tierIndex;
emit RewardNFTMinted(backer, tokenId, tierIndex);
}
}
NFT як receipt для бэкера — не просто косметика. Це доказ участі, може торгуватися на вторинному ринку (якщо кампанія популярна, early backer NFT цінуються), може бути використаний для додаткових perks (Discord ролі, early access, governance).
Мультивалютні внески
Приймати тільки один токен — ограничення для користувачів. Реалізація мультивалютного escrow через on-chain swap:
// Backend логіка: користувач хоче платити ETH, кампанія приймає USDC
async function processContribution(
userWallet: string,
paymentToken: string, // "ETH" | "USDC" | "WBTC"
amount: bigint,
campaignId: string
): Promise<string> {
if (paymentToken === "USDC") {
// Прямий внесок
return await campaign.contribute(amount);
}
// Для non-USDC: swap через 1inch API, потім contribute
const swapData = await getOneInchSwapData({
fromToken: paymentToken,
toToken: USDC_ADDRESS,
amount,
slippage: 1, // 1%
receiver: campaign.address, // прямо на campaign контракт
});
// Атомарний swap + contribute через multicall
return await multicall([
{ to: swapData.to, data: swapData.data, value: swapData.value },
{ to: campaign.address, data: encodeContribute(convertedAmount) },
]);
}
Platform fee та модель монетизації
Платформа бере процент від успішно профінансованих кампаній (стандарт Kickstarter — 5%). Це реалізується в момент milestone release:
uint256 public constant PLATFORM_FEE_BPS = 500; // 5%
address public platformTreasury;
function _releaseMilestoneFunds(uint256 milestoneIndex) internal {
uint256 gross = milestones[milestoneIndex].fundsToRelease;
uint256 fee = (gross * PLATFORM_FEE_BPS) / 10000;
uint256 net = gross - fee;
paymentToken.transfer(platformTreasury, fee);
paymentToken.transfer(creator, net);
}
Додаткові джерела доходу платформи: listing fee (фіксована плата за створення кампанії), premium features (розширена аналітика, featured placement), launchpad синергія (успішні краудфандинг проекти можуть отримати IDO слот).
Антимошеннічні механізми
Creator verification — KYC для창ателів кампаній обов'язковий. Anonymous creator + $1M в escrow = очевидний rug pull вектор.
Milestone escrow — жодна копійка не йде творцю до виконання першого milestone. Класичне "fundraise and disappear" неможливе.
Emergency stop — платформа може зупинити кампанію при підтвердженому мошенництві, повернути кошти бэкерам. Це centralized override, але необхідний.
Social proof requirements — верифікація команди через LinkedIn/GitHub, публічний roadmap в IPFS (immutable commitment), попередній продукт або MVP демо.
Базова платформа з двома ролями (creator, backer), milestone voting та NFT rewards: 10–14 тижнів розробки.







