FrensPool
Home
  • What is FrensPool?
  • How it works
  • Getting Started
  • Creating a Pool
  • Joining a Pool
  • Resolving Pools
  • Oracles
  • Technical Details
  • FAQ
Powered by GitBook
On this page
  • Architecture Overview
  • Smart Contract Details
  • Frontend Integration

Technical Details

Technical information for developers

This document provides comprehensive technical information about FrensPool's architecture, smart contracts, and integration points for developers who want to build on or interact with the platform.

Architecture Overview

FrensPool uses a modern web3 architecture consisting of:

  1. Smart Contracts: Solidity contracts deployed on Monad Testnet

  2. Frontend Application: Next.js web application with React

  3. Backend Services: Supabase for data indexing and user management

  4. Blockchain Interactions: Ethers.js v6 for contract interactions

  5. State Management: React context and hooks for frontend state

  6. Styling: Tailwind CSS with shadcn/ui components

title FrensPool Architecture
graph TD
  A[Frontend (Next.js)] --> B[Smart Contracts (Solidity)]
  A --> C[Supabase Backend]
  B --> D[Monad Blockchain]
  B --> E[Chainlink Oracles]
  C --> F[Database]
  C --> G[Authentication]
  A --> H[Ethers.js]
  H --> B

Smart Contract Details

Contract Address

Monad Testnet: 0x2535fe5De9A5BfAF6cf27316f141a5f67239E65A

Contract Architecture

The FrensPool contract inherits from OpenZeppelin's Ownable and ReentrancyGuard:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract FrensPool is Ownable, ReentrancyGuard {
    // Contract implementation
}

Uses:

  • Ownable: Access control

  • ReentrancyGuard: Prevent reentrancy

  • AggregatorV3Interface: Chainlink price feeds

Key Data Structures

Enums

enum PoolStatus { Open, Closed, Resolved }
enum OracleType { Chainlink, Social, Manual }
enum Vote { Yes, No }

Pool Struct

struct Pool {
    uint256 id;
    address creator;
    string question;
    uint256 buyIn;
    uint256 deadline;
    OracleType oracleType;
    PoolStatus status;
    uint256 totalYesVotes;
    uint256 totalNoVotes;
    uint256 totalAmount;
    bool outcome;
    address chainlinkFeed;
    uint256 targetPrice;
    bool isGreaterThan;
    mapping(address => Vote) votes;
    mapping(address => bool) hasVoted;
    mapping(address => bool) hasClaimed;
}

Constants

uint256 public constant PLATFORM_FEE = 50;
uint256 public constant BASIS_POINTS = 10000;

Key Functions

Create Pool

function createPool(string memory question, uint256 deadline, OracleType oracleType,
    address chainlinkFeed, uint256 targetPrice, bool isGreaterThan) external payable

Cast Vote

function castVote(uint256 poolId, Vote vote) external payable nonReentrant

Close Pool

function closePool(uint256 poolId) external

Resolve Pool (Manual)

function resolvePoolManually(uint256 poolId, bool outcome) external

Claim Winnings

function claimWinnings(uint256 poolId) external nonReentrant

Events

event PoolCreated(uint256 indexed poolId, address indexed creator, string question, uint256 buyIn, uint256 deadline);
event VoteCast(uint256 indexed poolId, address indexed voter, Vote vote, uint256 amount);
event PoolResolved(uint256 indexed poolId, bool outcome);
event WinningsClaimed(uint256 indexed poolId, address indexed user, uint256 amount);

Frontend Integration

Contract ABI

Refer to the FRENS_POOL_ABI for simplified interaction.

Connecting with Ethers.js

Setup

import { ethers } from "ethers";
import { FRENS_POOL_ABI } from "./abi";

const CONTRACT_ADDRESS = process.env.NEXT_PUBLIC_CONTRACT_ADDRESS;
const RPC_URL = process.env.NEXT_PUBLIC_RPC_URL;

export function getReadOnlyProvider() {
  return new ethers.JsonRpcProvider(RPC_URL);
}

export function getContractInstance(provider: any) {
  return new ethers.Contract(CONTRACT_ADDRESS, FRENS_POOL_ABI, provider);
}

export async function getSigner(provider: any) {
  return await provider.getSigner();
}

Create Pool Example

export async function createPoolOnChain(
  provider: any,
  question: string,
  deadline: string,
  buyInAmount: string,
  oracleType = 2,
  chainlinkFeed = ethers.ZeroAddress,
  targetPrice = "0",
  isGreaterThan = false,
): Promise<{ success: boolean; txHash: string }> {
  const deadlineTimestamp = Math.floor(new Date(deadline).getTime() / 1000);
  const buyInWei = ethers.parseEther(buyInAmount);
  const signer = await getSigner(provider);
  const contract = getContractInstance(signer);

  const tx = await contract.createPool(
    question,
    deadlineTimestamp,
    oracleType,
    chainlinkFeed,
    targetPrice,
    isGreaterThan,
    { value: buyInWei }
  );

  await tx.wait();
  return { success: true, txHash: tx.hash };
}

This documentation will continue to evolve as FrensPool adds features, optimizations, and mainnet support. For full ABI, helper functions, and additional integrations (e.g., Farcaster mini-app context), refer to the frenspool-dev-kit repo.

PreviousOraclesNextFAQ

Last updated 5 days ago