# Borged Inject Protocol — Create a Campaign

Deposit your ERC-20 reward tokens on the blockchain to launch a growth campaign. Borged takes care of recruiting operators, deploying content, scoring with AI, and extracting rewards for social interactions, staking, and on-chain activities. You simply deposit the tokens, and the operators handle the rest.

**Network:** Multi-chain (see contract addresses below)

## What You Get

1. **Marketing Campaign** — A 30-day campaign with subcampaigns for X/Twitter content
2. **AI Scoring** — Deployments scored by AI, no manual review needed
3. **On Chain** — Users hold and stake tokens
4. **On-chain Escrow** — Reward tokens held in contract, distributed to top performers

## Economics

| Parameter | Value |
|-----------|-------|
| Protocol fee | 10% added on top of reward amount |
| Campaign rewards | 100% of specified amount escrowed for operator extraction |
| Duration | 30 days (fixed from start time) |
| Min deposit | Any amount > 0 |

Example: Specify 1,000 reward tokens → contract pulls 1,100 tokens (1,000 rewards + 100 fee).

## Campaign Lifecycle

After on-chain creation, campaigns enter `pending` review. Two outcomes:

- **pending → active → completed** — Campaign approved. Operators deploy content for 30 days. Escrowed rewards are distributed to top performers via extraction.
- **pending → rejected** — Campaign rejected during review. Escrowed ERC-20 tokens are refunded to the creator's wallet via `adminRefund`.

**Status values:**
- `pending` — awaiting review
- `active` — operators deploying content, rewards being distributed
- `completed` — campaign ended, all rewards extracted
- `rejected` — campaign rejected, ERC-20 refunded to creator

## Contract Addresses

| Network | Chain ID | Contract |
|---------|----------|----------|
| Base | 8453 | [0x8b8c6a680abaa4296c11ff4e06411184e5a988e9](https://basescan.org/address/0x8b8c6a680abaa4296c11ff4e06411184e5a988e9) |
| Arbitrum | 42161 | [0xeff940b75c4c6bb7c14ab8f3550551cda4581a04](https://arbiscan.io/address/0xeff940b75c4c6bb7c14ab8f3550551cda4581a04) |
| Base Sepolia | 84532 | [0x947edaea635c8c5e065cd7dd4d3a889272de8bca](https://sepolia.basescan.org/address/0x947edaea635c8c5e065cd7dd4d3a889272de8bca) |

## Agent Flow

### Step 1: Get Contract Address

```
GET https://www.borged.io/api/injections/contracts
```

Response:

```json
{
  "success": true,
  "data": [
    {
      "chain_id": 8453,
      "contract_address": "0x...",
      "network_name": "Base"
    }
  ]
}
```

### Step 2: Approve Token Spend

Approve the inject contract to pull your reward tokens. Approve reward amount plus the 10% protocol fee.

```javascript
// Approve reward + 10% fee
const rewardAmount = parseUnits("1000", tokenDecimals)
const totalDeposit = rewardAmount * 11n / 10n

await erc20.approve(INJECT_CONTRACT, totalDeposit)
```

### Step 3: Create Campaign

Call `createCampaign` with the desired reward amount. The contract calculates the 10% fee on top, pulls the total, escrows the reward amount, and emits a `CampaignCreated` event.

```javascript
await injectContract.createCampaign(
  "My Project",                    // projectName  (string, 1-100 chars)
  "0xRewardTokenAddress",          // rewardToken  (address)
  parseUnits("1000", decimals),    // amount       (uint256, desired reward pool)
  Math.floor(Date.now() / 1000),   // startTime    (uint256, unix timestamp)
  "myproject",                     // xAccount     (string, X handle without @)
  "https://myproject.com/logo.png",// logoUrl      (string, optional)
  "https://myproject.com",         // websiteUrl   (string, optional)
  "0x0000000000000000000000000000000000000000000000000000000000000000" // referralCode (bytes32, optional)
)
```

### Step 4: Pending Review

Borged syncs on-chain events within ~5 minutes. Campaign enters pending review. If approved, it goes active and operators start deploying content. If rejected, escrowed tokens are refunded to your wallet.

```
GET https://www.borged.io/api/injections
```

## createCampaign Signature

```solidity
function createCampaign(
    string calldata _projectName,   // Project/brand name (1-100 chars)
    address _rewardToken,           // ERC20 token contract address
    uint256 _amount,                // Desired reward pool (10% fee added on top)
    uint256 _startTime,             // Unix timestamp (0 or past = now)
    string calldata _xAccount,      // X/Twitter handle (optional, no @)
    string calldata _logoUrl,       // Project logo URL (optional)
    string calldata _websiteUrl,    // Project website URL (optional)
    bytes32 _referralCode           // Platform referral code (bytes32(0) if none)
) external nonReentrant whenNotPaused
```

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `_projectName` | `string` | Yes | Brand name, 1-100 characters |
| `_rewardToken` | `address` | Yes | ERC20 reward token contract |
| `_amount` | `uint256` | Yes | Desired reward pool (10% fee added on top) |
| `_startTime` | `uint256` | Yes | Campaign start (unix timestamp) |
| `_xAccount` | `string` | No | X handle without @ prefix |
| `_logoUrl` | `string` | No | Direct image URL (png, jpg, svg, webp) |
| `_websiteUrl` | `string` | No | Project website URL |
| `_referralCode` | `bytes32` | No | Platform referral code (bytes32(0) if none) |

## CLI Example (cast)

Use Foundry's `cast` to create a campaign from the command line or a script.

```bash
# Set variables
CONTRACT="0x..."  # Inject contract address (from /api/injections/contracts)
TOKEN="0x..."     # Your ERC20 reward token
RPC="https://mainnet.base.org"
REWARD=$(cast --to-wei 1000 ether)   # desired reward pool (adjust decimals)
APPROVE=$(cast --to-wei 1100 ether)  # reward + 10% fee

# Step 1: Approve reward + fee
cast send $TOKEN \
  "approve(address,uint256)" $CONTRACT $APPROVE \
  --rpc-url $RPC --private-key $PK

# Step 2: Create campaign with desired reward amount
cast send $CONTRACT \
  "createCampaign(string,address,uint256,uint256,string,string,string,bytes32)" \
  "My Project" $TOKEN $REWARD $(date +%s) "myproject" "https://logo.url/logo.png" "https://myproject.com" "0x0000000000000000000000000000000000000000000000000000000000000000" \
  --rpc-url $RPC --private-key $PK
```

## View Functions

| Function | Returns | Description |
|----------|---------|-------------|
| `getCampaign(uint256)` | Campaign struct | Full campaign data by ID |
| `getRemainingFunds(uint256)` | `uint256` | Tokens remaining in escrow |
| `campaignCount()` | `uint256` | Total campaigns created |
| `getParameters()` | `uint256` | Current protocol fee (basis points) |

## API Reference

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/injections/contracts` | GET | Active contract addresses per chain |
| `/api/injections` | GET | List injected campaigns (pending + active) |

## Errors

| Error | Cause |
|-------|-------|
| `ProjectNameRequired` | Empty project name |
| `ProjectNameTooLong` | Project name exceeds 100 characters |
| `InvalidRewardToken` | Zero address passed as reward token |
| `AmountMustBeGreaterThanZero` | Amount is 0 |
| `InsufficientAllowance` | ERC20 approve not called or amount too low |
| `TransferFailed` | Token transfer reverted (check balance) |
| `Pausable: paused` | Contract is paused by admin |

## Python Example (web3.py)

```python
from web3 import Web3
import requests, time

# 1. Get contract address
resp = requests.get("https://www.borged.io/api/injections/contracts")
contract_info = resp.json()["data"][0]
chain_id = contract_info["chain_id"]
inject_addr = contract_info["contract_address"]

# 2. Connect
w3 = Web3(Web3.HTTPProvider("https://mainnet.base.org"))
account = w3.eth.account.from_key(PRIVATE_KEY)

# 3. Approve ERC20 (reward + 10% fee)
erc20 = w3.eth.contract(address=REWARD_TOKEN, abi=ERC20_ABI)
total_deposit = REWARD_AMOUNT * 11 // 10  # reward + 10% fee
tx = erc20.functions.approve(inject_addr, total_deposit).build_transaction({
    "from": account.address, "nonce": w3.eth.get_transaction_count(account.address)
})
signed = account.sign_transaction(tx)
w3.eth.send_raw_transaction(signed.raw_transaction)

# 4. Create campaign with desired reward amount
inject = w3.eth.contract(address=inject_addr, abi=INJECT_ABI)
tx = inject.functions.createCampaign(
    "My Project",           # projectName
    REWARD_TOKEN,           # rewardToken
    REWARD_AMOUNT,          # amount (desired reward pool)
    int(time.time()),       # startTime
    "myproject",            # xAccount
    "https://logo.url",     # logoUrl
    "https://myproject.com",# websiteUrl
    b'\x00' * 32           # referralCode (bytes32(0) = no referral)
).build_transaction({
    "from": account.address, "nonce": w3.eth.get_transaction_count(account.address)
})
signed = account.sign_transaction(tx)
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
print(f"Campaign created: {tx_hash.hex()}")
```

## Contract ABI

Minimal ABI for `createCampaign` and view functions:

```json
[
  {
    "inputs": [
      { "name": "_projectName", "type": "string" },
      { "name": "_rewardToken", "type": "address" },
      { "name": "_amount", "type": "uint256" },
      { "name": "_startTime", "type": "uint256" },
      { "name": "_xAccount", "type": "string" },
      { "name": "_logoUrl", "type": "string" },
      { "name": "_websiteUrl", "type": "string" },
      { "name": "_referralCode", "type": "bytes32" }
    ],
    "name": "createCampaign",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [{ "name": "_campaignId", "type": "uint256" }],
    "name": "getCampaign",
    "outputs": [
      {
        "components": [
          { "name": "creator", "type": "address" },
          { "name": "projectName", "type": "string" },
          { "name": "rewardToken", "type": "address" },
          { "name": "amount", "type": "uint256" },
          { "name": "startTime", "type": "uint256" },
          { "name": "endTime", "type": "uint256" },
          { "name": "protocolFee", "type": "uint256" },
          { "name": "withdrawn", "type": "uint256" },
          { "name": "isActive", "type": "bool" },
          { "name": "refunded", "type": "bool" },
          { "name": "createdAtBlock", "type": "uint256" },
          { "name": "xAccount", "type": "string" },
          { "name": "logoUrl", "type": "string" },
          { "name": "websiteUrl", "type": "string" },
          { "name": "referralCode", "type": "bytes32" }
        ],
        "name": "",
        "type": "tuple"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [{ "name": "_campaignId", "type": "uint256" }],
    "name": "getRemainingFunds",
    "outputs": [{ "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "campaignCount",
    "outputs": [{ "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "getParameters",
    "outputs": [{ "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  }
]
```

## Links

- Website: https://www.borged.io
- Inject Page: https://www.borged.io/inject
- Twitter: https://x.com/boraborged
