# degen chain hackathon idea
Deploy your own Farcaster community, using DegenChain as settlement layer
+ New Frontend that allows creating your Farcaster community:
+ Set a name for your community (i.e Yellow Collective)
+ Set the census (i.e NFT: 0x1234 or ERC20: 0x567)
+ supported networks: base, optimism, polygon, ethereum
+ Upload a Logo
+ Set a Farcaster channel (i.e /yellow)
+ Set who can create voting proposals
+ farcaster user handles
+ holders (all)
+ holders with mÃnimum followers
+ Enable/Disable notifications via Farcaster when new voting proposal
+ Pay with degen
+ When voting ends on Farcaster, the following information is uploaded to DegenChain
+ Question and options
+ Date
+ Results of the vote
+ Turnout
+ List of the participants
When a new Community is created on the DegenChain smartcontract,
it will automatically appear available on https://farcaster.vote
New voting proposals can then be created using such community on Farcaster.vote using the current standard flow.
Question and result are automatically uploaded to DegenChain, so anyone can verify it and remains settled forever.

---
### Formulari creació community
- s'utilitza el signer Ethereum i s'envia la TX al smartcontract
#### Required API endpoints
- Create a community:
- `GET /users/profile/{fid}` | `/users/profile/{username}`: Get Farcaster user by FID or username.
- `GET /channels`: List of Farcaster channels.
- `GET /channels/{channelID}`: Information about Farcaster channel, if it exists.
- Validate default census:
- `POST /census/check/[nft/erc20]`: If it is a contract, validate that it exists in the associated network.
- `Body: {"address": "", "blockchain": "base"}`
- ~~`POST /census/check/channel-gated`: If it is a channel, validate that it exists~~ --> **Replaced by `GET /channels/{channelID}`**
- `POST /community` Store the resulting community in the database when contract interaction success.
### Dashboard community
### EVM contracts
#### Communities
- This is the community registry, where communities are created and managed.
```solidity
contract CommunityHub is Ownable {
constructor(address owner) Ownable(owner) {}
enum CreateElectionPermission {
GUARDIAN,
CENSUS
}
enum TokenType {
ERC20,
ERC721,
ERC1155
}
struct Token {
string name;
string symbol;
uint8 decimals;
TokenType tokenType;
string chainId;
}
enum CensusType {
FC,
CHANNEL,
FOLLOWERS,
CSV,
TOKEN
}
struct Census {
CensusType censusType;
Token[] tokens;
}
struct CommunityMetadata {
string name;
string imageURI;
string channel;
bool notifications;
}
struct Community {
CommunityMetadata metadata;
Census census;
EnumerableSet.Set guardians;
address electionResultsContract;
CreateElectionPermission createElectionPermission;
uint256 cooldown;
}
mapping(uint256 => Community) private communities;
// create community
function CreateCommunity(
CommunityMetadata memory metadata,
Census memory census,
address[] memory guardians,
address electionResultsContract,
CreateElectionPermission createElectionPermission,
uint256 cooldown
) public {}
// delete community
function DeleteCommunity(uint256 communityId) public onlyOwner {}
// admin manage community
function AdminManageCommunity(
uint256 communityId,
CommunityMetadata memory metadata,
Census memory census,
address[] memory guardians,
address electionResultsContract,
CreateElectionPermission createElectionPermission
) public onlyOwner {}
// set metadata
function SetMetadata(uint256 communityId, CommunityMetadata memory metadata) public onlyGuardian(communityId) {}
// add guardian
function AddGuardian(uint256 communityId, address guardian) public onlyGuardian(communityId) {}
// remove guardian
function RemoveGuardian(uint256 communityId, address guardian) public onlyGuardian(communityId) {}
// isGuardian
function IsGuardian(uint256 communityId, address guardian) internal view returns (bool) {}
// add census
function AddCensus(uint256 communityId, Census memory census) public onlyGuardian(communityId) {}
// remove census
function RemoveCensus(uint256 communityId) public onlyGuardian(communityId) {}
// set election results contract
function SetElectionResultsContract(uint256 communityId, address electionResultsContract) public onlyGuardian(communityId) {}
// set create election permission
function SetCreateElectionPermission(uint256 communityId, CreateElectionPermission createElectionPermission) public onlyGuardian(communityId) {}
// set notifiable elections
function SetNotifiableElections(uint256 communityId, bool notifiableElections) public onlyGuardian(communityId) {}
// set election results
function SetElectionResults(
uint256 communityId,
bytes32 electionId,
string memory question,
string[] memory options,
string memory date,
uint256[][] memory tally,
uint256 turnout,
string[] memory participants,
bytes memory action,
bytes32 censusRoot,
string memory censusURI
) public onlyGuardian(communityId) {}
function GetElectionResults(uint256 communityId, string memory electionId) public view returns (
string memory question,
string[] memory options,
string memory date,
uint256[][] memory tally,
uint256 turnout,
string[] memory participants,
bytes memory action,
bytes32 censusRoot,
string memory censusURI
) {}
}
```
#### Results
- This contract is set by the community, by default Vocdoni will take care of this, but the user can choose to change.
- Stores all the organizations elections results
```solidity
struct Result {
string question;
string[] options;
string date;
uint256[][] tally;
uint256 turnout;
uint256 totalVotingPower;
string[] participants;
bytes action;
bytes32 censusRoot;
string censusURI;
}
// CommunityId => ElectionId => Result
mapping(bytes32 => mapping(bytes32 => Result)) public results;
// set results
function setResult(bytes32 communityId, bytes32 electionId, Result memory result) public onlyOwner {
results[communityId][electionId] = result;
}
// get results
function getResult(bytes32 communityId, bytes32 electionId) public view returns (Result memory) {
return results[communityId][electionId];
}
```