Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .starkli-wallets/deployer-account.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": 1,
"variant": {
"type": "open_zeppelin",
"version": 1,
"public_key": "0x2b1d7b7bb0bb3ae8e062ad5ed27c0b12eb16a4c4ea51e1e164e0f2e36a2ad9d",
"legacy": false
},
"deployment": {
"status": "deployed",
"class_hash": "0x61dac032f228abef9c6626f995015233097ae253a7f72d68552db02f2971b8f",
"address": "0x0f082b9d66cd3d9e4edc4d9c9450e7b154e88d490a22b214ee41c9d291df876"
}
}
141 changes: 141 additions & 0 deletions STARKNET_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# BigInc Starknet Integration Guide

This repository now supports both Ethereum/Polygon (via WAGMI) and Starknet implementations of the BigIncGenesis smart contract.

## Quick Start - Starknet Local Development

### Prerequisites

1. **Install Dojo (includes Katana)**:
```bash
curl -L https://install.dojo.sh | bash
dojoup
```

2. **Install Starkli**:
```bash
curl https://get.starkli.sh | sh
starkliup
```

3. **Install Scarb**:
```bash
curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh
```

### Development Setup

**Option 1: Full Automated Setup**
```bash
npm run setup:full
```
This will:
- Start Katana devnet
- Deploy contracts (BigIncGenesis, MockUSDT, MockUSDC)
- Update frontend configuration
- Start Next.js dev server with Starknet enabled

**Option 2: Manual Step-by-Step**

1. **Start Katana devnet**:
```bash
npm run setup:devnet
```

2. **Deploy contracts**:
```bash
npm run deploy:contracts
```

3. **Start frontend with Starknet**:
```bash
npm run dev:starknet
```

### Contract Addresses

After deployment, contract addresses are automatically updated in:
- `src/lib/starknet/config.ts`
- `deployment/contracts.json`

### Test Accounts

The devnet provides prefunded test accounts:

**Account #0:**
- Address: `0xf082b9d66cd3d9e4edc4d9c9450e7b154e88d490a22b214ee41c9d291df876`
- Private Key: `0x53b7668914511a29edc1247c0d2a9a44d0c9c78b4a2d8163c6439a4bde52a98`

**Account #1:**
- Address: `0x175c0552eda5d4b38250a5388d4d11b1a018df0c3081c7fe2ee3478ada43d78`
- Private Key: `0x7dd2923d111acc143d8e1f1b95850bce0479e19bdd4dc4c83a33da7efeb0fd7`

### Using the dApp

1. Visit `http://localhost:3000/dewhitepaper`
2. Connect your Starknet wallet (Braavos, ArgentX, etc.)
3. The page will automatically detect if Starknet contracts are deployed
4. Use MockUSDT/USDC to buy shares
5. View live share distribution in the pie chart

### Architecture

#### Dual Implementation Support
The app supports both Ethereum and Starknet:
- **Ethereum**: Uses WAGMI + WalletConnect
- **Starknet**: Uses starknet-react + StarknetKit
- Automatically switches based on `NEXT_PUBLIC_USE_STARKNET` or contract availability

#### Key Components

**Starknet-Specific:**
- `ShareChartStarknet.tsx` - Live on-chain share visualization
- `ShareModalStarknet.tsx` - Buy shares using Mock USDT/USDC
- `src/lib/starknet/hooks.ts` - Contract interaction hooks
- `src/lib/starknet/config.ts` - Chain and contract configuration

**Smart Contracts:**
- `BigIncGenesis.cairo` - Main share management contract
- `MockERC20.cairo` - Mock USDT/USDC for testing

### Stopping the Environment

```bash
# Stop Next.js dev server
Ctrl+C

# Stop Katana devnet
npm run stop:devnet
```

### Contract Functions

The BigIncGenesis contract supports:
- `mint_share()` - Buy shares with USDT/USDC
- `get_shares(address)` - Get user's share balance
- `get_shareholders()` - Get all shareholders
- `get_available_shares()` - Get remaining shares for sale
- `transfer_share()` - Transfer shares between users
- `donate()` - Donate tokens to the contract

### Environment Variables

- `NEXT_PUBLIC_USE_STARKNET=true` - Enables Starknet mode in frontend

## Troubleshooting

**Contract not found errors:**
- Ensure Katana is running on port 5050
- Redeploy contracts with `npm run deploy:contracts`

**Wallet connection issues:**
- Use browser wallets compatible with Starknet devnet
- Check that wallet is connected to the correct network

**Transaction failures:**
- Ensure you have sufficient mock token balance
- Approve tokens before minting shares

**Build errors:**
- Run `scarb build` in the `contract_/` directory
- Check that all dependencies are installed
89 changes: 89 additions & 0 deletions contract_/src/MockERC20.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use starknet::ContractAddress;

#[starknet::interface]
pub trait IERC20<TContractState> {
fn name(self: @TContractState) -> ByteArray;
fn symbol(self: @TContractState) -> ByteArray;
fn decimals(self: @TContractState) -> u8;
fn total_supply(self: @TContractState) -> u256;
fn balance_of(self: @TContractState, account: ContractAddress) -> u256;
fn allowance(self: @TContractState, owner: ContractAddress, spender: ContractAddress) -> u256;
fn transfer(ref self: TContractState, recipient: ContractAddress, amount: u256) -> bool;
fn transfer_from(
ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256,
) -> bool;
fn approve(ref self: TContractState, spender: ContractAddress, amount: u256) -> bool;
}

#[starknet::interface]
pub trait IMockERC20<TContractState> {
fn mint(ref self: TContractState, recipient: ContractAddress, amount: u256);
fn burn(ref self: TContractState, account: ContractAddress, amount: u256);
}

#[starknet::contract]
pub mod MockERC20 {
use openzeppelin::token::erc20::ERC20Component;
use starknet::ContractAddress;
use super::IMockERC20;

component!(path: ERC20Component, storage: erc20, event: ERC20Event);

#[abi(embed_v0)]
impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
#[abi(embed_v0)]
impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
impl InternalImpl = ERC20Component::InternalImpl<ContractState>;

// Implement the required ERC20HooksTrait
impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {
fn before_update(
ref self: ERC20Component::ComponentState<ContractState>,
from: ContractAddress,
recipient: ContractAddress,
amount: u256,
) { // No custom logic needed for mock token
}

fn after_update(
ref self: ERC20Component::ComponentState<ContractState>,
from: ContractAddress,
recipient: ContractAddress,
amount: u256,
) { // No custom logic needed for mock token
}
}

#[storage]
struct Storage {
#[substorage(v0)]
erc20: ERC20Component::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC20Event: ERC20Component::Event,
}

#[constructor]
fn constructor(ref self: ContractState, initial_supply: u256, recipient: ContractAddress) {
// Use hardcoded values to avoid ByteArray serialization issues
let name: ByteArray = "Mock Token";
let symbol: ByteArray = "MOCK";
self.erc20.initializer(name, symbol);
self.erc20.mint(recipient, initial_supply);
}

#[abi(embed_v0)]
impl MockERC20Impl of IMockERC20<ContractState> {
fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
self.erc20.mint(recipient, amount);
}

fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
self.erc20.burn(account, amount);
}
}
}
87 changes: 87 additions & 0 deletions contract_/src/MockUSDC.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use starknet::ContractAddress;

#[starknet::interface]
pub trait IERC20<TContractState> {
fn name(self: @TContractState) -> ByteArray;
fn symbol(self: @TContractState) -> ByteArray;
fn decimals(self: @TContractState) -> u8;
fn total_supply(self: @TContractState) -> u256;
fn balance_of(self: @TContractState, account: ContractAddress) -> u256;
fn allowance(self: @TContractState, owner: ContractAddress, spender: ContractAddress) -> u256;
fn transfer(ref self: TContractState, recipient: ContractAddress, amount: u256) -> bool;
fn transfer_from(
ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256,
) -> bool;
fn approve(ref self: TContractState, spender: ContractAddress, amount: u256) -> bool;
}

#[starknet::interface]
pub trait IMockUSDC<TContractState> {
fn mint(ref self: TContractState, recipient: ContractAddress, amount: u256);
fn burn(ref self: TContractState, account: ContractAddress, amount: u256);
}

#[starknet::contract]
pub mod MockUSDC {
use openzeppelin::token::erc20::ERC20Component;
use starknet::ContractAddress;
use super::IMockUSDC;

component!(path: ERC20Component, storage: erc20, event: ERC20Event);

#[abi(embed_v0)]
impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
#[abi(embed_v0)]
impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
impl InternalImpl = ERC20Component::InternalImpl<ContractState>;

// Implement the required ERC20HooksTrait
impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {
fn before_update(
ref self: ERC20Component::ComponentState<ContractState>,
from: ContractAddress,
recipient: ContractAddress,
amount: u256,
) {}

fn after_update(
ref self: ERC20Component::ComponentState<ContractState>,
from: ContractAddress,
recipient: ContractAddress,
amount: u256,
) {}
}

#[storage]
struct Storage {
#[substorage(v0)]
erc20: ERC20Component::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC20Event: ERC20Component::Event,
}

#[constructor]
fn constructor(ref self: ContractState, initial_supply: u256, recipient: ContractAddress) {
// Hardcoded USDC values
let name: ByteArray = "Mock USD Coin";
let symbol: ByteArray = "USDC";
self.erc20.initializer(name, symbol);
self.erc20.mint(recipient, initial_supply);
}

#[abi(embed_v0)]
impl MockUSDCImpl of IMockUSDC<ContractState> {
fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
self.erc20.mint(recipient, amount);
}

fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
self.erc20.burn(account, amount);
}
}
}
Loading
Loading