Criar um sistema de financiamento coletivo

porMatheusem14/06/2022

Nesse artigo iremos aprender a como criar um sistema de financiamento coletivo através de um contrato inteligente.

Sistema de Financiamento Coletivo (Crowd Fund)

Como funciona o token ERC20 de financiamento coletivo?

  1. O usuário cria uma campanha.
  2. Os usuários podem se comprometer, transferindo seu token para uma campanha.
  3. Após o término da campanha, o criador da campanha pode reivindicar os fundos se o valor total prometido for maior que a meta da campanha.
  4. Caso contrário, a campanha não atingiu seu objetivo, então os usuários podem retirar o valor depositado.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IERC20 {
function transfer(address, uint) external returns (bool);
function transferFrom(
address,
address,
uint
) external returns (bool);
}
contract CrowdFund {
event Launch(
uint id,
address indexed creator,
uint goal,
uint32 startAt,
uint32 endAt
);
event Cancel(uint id);
event Pledge(uint indexed id, address indexed caller, uint amount);
event Unpledge(uint indexed id, address indexed caller, uint amount);
event Claim(uint id);
event Refund(uint id, address indexed caller, uint amount);
struct Campaign {
// Criador da campanha
address creator;
// Objetivo de tokens para arrecadar
uint goal;
// Valor doado para a campanha
uint pledged;
// Timestamp do início da campanha
uint32 startAt;
// Timestamp do final da campanha
uint32 endAt;
// True se a meta foi alcançada e o criador reivindicou os tokens.
bool claimed;
}
IERC20 public immutable token;
// Contagem total de campanhas criadas.
// Também é usado para gerar id para novas campanhas.
uint public count;
// Mapeamento do id para a campanha
mapping(uint => Campaign) public campaigns;
// Mapeamento do id da campanha => doador => valor doado
mapping(uint => mapping(address => uint)) public pledgedAmount;
constructor(address _token) {
token = IERC20(_token);
}
function launch(
uint _goal,
uint32 _startAt,
uint32 _endAt
) external {
require(_startAt >= block.timestamp, "data início < agora");
require(_endAt >= _startAt, "data final < data início");
require(_endAt <= block.timestamp + 90 days, "data final > duração máxima (90 dias)");
count += 1;
campaigns[count] = Campaign({
creator: msg.sender,
goal: _goal,
pledged: 0,
startAt: _startAt,
endAt: _endAt,
claimed: false
});
emit Launch(count, msg.sender, _goal, _startAt, _endAt);
}
function cancel(uint _id) external {
Campaign memory campaign = campaigns[_id];
require(campaign.creator == msg.sender, "não é o criador");
require(block.timestamp < campaign.startAt, "iniciada");
delete campaigns[_id];
emit Cancel(_id);
}
function pledge(uint _id, uint _amount) external {
Campaign storage campaign = campaigns[_id];
require(block.timestamp >= campaign.startAt, "não iniciada");
require(block.timestamp <= campaign.endAt, "finalizada");
campaign.pledged += _amount;
pledgedAmount[_id][msg.sender] += _amount;
token.transferFrom(msg.sender, address(this), _amount);
emit Pledge(_id, msg.sender, _amount);
}
function unpledge(uint _id, uint _amount) external {
Campaign storage campaign = campaigns[_id];
require(block.timestamp <= campaign.endAt, "finalizada");
campaign.pledged -= _amount;
pledgedAmount[_id][msg.sender] -= _amount;
token.transfer(msg.sender, _amount);
emit Unpledge(_id, msg.sender, _amount);
}
function claim(uint _id) external {
Campaign storage campaign = campaigns[_id];
require(campaign.creator == msg.sender, "não é o criador");
require(block.timestamp > campaign.endAt, "não finalizada");
require(campaign.pledged >= campaign.goal, "doado < meta");
require(!campaign.claimed, "já reivindicado");
campaign.claimed = true;
token.transfer(campaign.creator, campaign.pledged);
emit Claim(_id);
}
function refund(uint _id) external {
Campaign memory campaign = campaigns[_id];
require(block.timestamp > campaign.endAt, "não finalizada");
require(campaign.pledged < campaign.goal, "valor doado menor que a meta");
uint bal = pledgedAmount[_id][msg.sender];
pledgedAmount[_id][msg.sender] = 0;
token.transfer(msg.sender, bal);
emit Refund(_id, msg.sender, bal);
}
}

Este contrato de financiamento coletivo, poderia ser implementado para um sistema ao estilo do site Vakinha, onde os usuários podem criar campanhas para seus projetos NFT, desenvolvimento de jogos NFT e outros projetos pessoais ou campanhas sociais, através de campanhas de levantamento de fundos de criptomoedas.


Testar no Remix