> For the complete documentation index, see [llms.txt](https://docs.realms.today/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.realms.today/sowellian/sowellian-how-it-works.md).

# Sowellian: How It Works

## Sowellian: How It Works

Sowellian is a prediction market governance plugin for SPL Governance. It transforms traditional governance proposals into betting markets where participants stake tokens on the outcome of proposals, combining financial incentives with governance participation.

### Overview

Instead of simply voting "Yes" or "No" on a proposal, Sowellian creates a **bet** tied to each proposal. Participants stake tokens on their predicted outcome, and when the bet is resolved, winners earn from the losing pool. This creates a "skin in the game" dynamic that incentivizes informed participation and honest signal expression.

**Program ID:** `sowEL1Rtn3p479rg34gW7mVPeCNY58Es5rkLpFsCJAW`

### Core Concepts

#### Bet

A Bet is the central account that ties a prediction market to an SPL Governance proposal. It tracks:

* The associated proposal
* Total tokens staked on Yes vs No
* The bet's lifecycle state (Active, Settled, Resolved)
* The seed used for PDA derivation
* The owner (proposer) who created it

#### Vote Receipt

When a participant places a bet (casts a Sowellian vote), a **Vote Receipt** is created. This receipt:

* Records the voter's position (Yes or No)
* Records the amount staked
* Becomes the `governing_token_owner` for a dedicated Voter Weight Record
* Is used to claim winnings after resolution

#### Registrar

The Registrar configures the Sowellian plugin for a specific Realm. It stores:

* The linked Realm and governing token mint
* The governance account
* The treasury address (for fee collection)
* The realm authority

### Lifecycle

#### 1. Create a Bet

When a proposal is created, a bet is created alongside it:

```
create_bet(seed, name, description_link, proposal_seed, amount)
```

The proposer provides an initial stake and defines the bet parameters. A proposal is automatically created in SPL Governance tied to this bet.

#### 2. Cast Sowellian Votes

Participants stake tokens on their predicted outcome:

```
cast_sowellian_vote(vote_seed, is_yes, amount)
```

* `is_yes: true` - Betting the proposal will pass
* `is_yes: false` - Betting the proposal will fail
* `amount` - Number of tokens to stake

Tokens are transferred to the bet vault (an Associated Token Account controlled by the bet PDA).

Each vote creates:

1. A **Vote Receipt** PDA: `['vote-receipt', bet, vote_seed]`
2. A **Voter Weight Record** PDA for the receipt, allowing the governance program to recognize the vote

The Sowellian plugin simultaneously casts the governance vote through CPI (Cross-Program Invocation) to the SPL Governance program.

#### 3. Settle the Bet

After the governance vote concludes, anyone can settle the bet:

```
settle_bet()
```

Settlement:

* Locks in all staked amounts
* Prevents further betting
* The proposal owner's receipt is created
* A treasury cut is taken from the pool

#### 4. Resolve the Bet

The realm authority resolves the bet with the actual outcome:

```
resolve_bet(outcome: BetOutcome)  // Yes, No, or Void
```

Resolution:

* Sets the winning side
* Takes a 1% treasury cut from the total pool
* Marks the bet as resolved

#### 5. Claim Winnings

Winners claim their share of the losing pool:

```
claim_bet(vote_seed)
```

Winnings are distributed proportionally based on each winner's stake relative to the total winning pool.

### Fee Structure

| Fee                   | Percentage | Description                                     |
| --------------------- | ---------- | ----------------------------------------------- |
| Proposer Profit Share | 15%        | Portion of profits allocated to the bet creator |
| Voter Profit Share    | 5%         | Additional share for governance voters          |
| Bet Loss Rake         | 1%         | Treasury cut from the total pool on resolution  |

### Bet Weight Multiplier

Sowellian applies a weight multiplier to bets based on the participant's position in the betting order, divided into 10 buckets:

```typescript
const SOWELLIAN_WEIGHT_ARRAY = [
  1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.4, 2.5, 2.5,
];
```

The multiplier ranges from 1x (first bucket) to 2.5x (last buckets). A participant's bucket is determined by their position relative to the total number of bettors.

### PDA Addresses

| Account             | Seeds                                                                |
| ------------------- | -------------------------------------------------------------------- |
| Registrar           | `['registrar', realm, governing_token_mint]`                         |
| Bet                 | `['bet', seed]`                                                      |
| Vote Receipt        | `['vote-receipt', bet, vote_seed]`                                   |
| Voter Weight Record | `['voter-weight-record', realm, governing_token_mint, vote_receipt]` |
| Bet Vault           | ATA of the bet PDA for the governing token mint                      |

### Integration with SPL Governance

Sowellian works as a governance plugin by:

1. **Registering as a voter weight addin** on the Realm through `SetRealmConfig`
2. **Creating VoterWeightRecords** for each bet participant (keyed to their vote receipt, not their wallet directly)
3. **Casting governance votes via CPI** when a Sowellian vote is placed
4. The governance program reads the Sowellian-managed VoterWeightRecords to determine voting power

This means every Sowellian bet simultaneously functions as a governance vote, bridging prediction markets with on-chain governance execution.

### Helper Functions

```typescript
import {
  getBetAddress,
  getRegistrarAddress,
  getVoteReceiptAddress,
  getSowellianVoterWeightRecordAddress,
  SOWELLIAN_PLUGIN_PROGRAM_ID,
} from './sowellian/constants';

// Derive the bet PDA
const betAddress = getBetAddress(seed);

// Derive the registrar PDA
const registrarAddress = getRegistrarAddress(realm, governingTokenMint);

// Derive vote receipt PDA
const receiptAddress = getVoteReceiptAddress(bet, voteSeed);

// Derive voter weight record PDA
const vwrAddress = getSowellianVoterWeightRecordAddress(
  realm, governingTokenMint, governingTokenOwner
);
```
