GushProtocol

0x1f1675daf8d1f6a145837743f3a63f95cdedb926

Verification
Verified
v0.8.28+commit.7893614a
Type
Contract
9,100 bytes
ABI entries
51
16 read · 16 write
License
none

Contract information

Address
0x1f1675daf8d1f6a145837743f3a63f95cdedb926
Chain
Robinhood Chain (4663)
Compiler
v0.8.28+commit.7893614a
Optimization
Enabled
Creation tx
0x8bca36500a…cb39e4a5ca

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (16)

BPS()uint256
DEPTH_UNIT()uint256
WELLHEAD_BURN()address
commodities(uint256)string, uint256, uint256, uint256, uint256, uint256, bool
commodityCount()uint256
emissionBudget()uint256
feeRecipient()address
gush()address
oracle()address
owner()address
pendingGush(uint256)uint256
settlementFeeBps()uint256
wellCount()uint256
wellRatePerSec(uint256)uint256
wells(uint256)uint256, address, uint256, uint256, uint256, bool
wellsRemaining(uint256)uint256

Events (15)

BaseRateSetBudgetFundedBudgetReclaimedClaimPriceSetCommodityActiveCommodityAddedDeepenedFeeRecipientSetGushedOracleSetOwnershipTransferredSettlementFeeSetVolatilitySetWellClaimedWellTransferred

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "gush_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "feeRecipient_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "OwnableInvalidOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "OwnableUnauthorizedAccount",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "name": "SafeERC20FailedOperation",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "id",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "baseRatePerSec",
        "type": "uint256"
      }
    ],
    "name": "BaseRateSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "BudgetFunded",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "BudgetReclaimed",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "id",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "claimPriceWei",
        "type": "uint256"
      }
    ],
    "name": "ClaimPriceSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "id",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "active",
        "type": "bool"
      }
    ],
    "name": "CommodityActive",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "id",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "wellSupply",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "claimPriceWei",
        "type": "uint256"
      }
    ],
    "name": "CommodityAdded",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "gushBurned",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newDepth",
        "type": "uint256"
      }
    ],
    "name": "Deepened",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      }
    ],
    "name": "FeeRecipientSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "toOperator",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "fee",
        "type": "uint256"
      }
    ],
    "name": "Gushed",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "oracle",
        "type": "address"
      }
    ],
    "name": "OracleSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "bps",
        "type": "uint256"
      }
    ],
    "name": "SettlementFeeSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "id",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "volBps",
        "type": "uint256"
      }
    ],
    "name": "VolatilitySet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "commodityId",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "pricePaid",
        "type": "uint256"
      }
    ],
    "name": "WellClaimed",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      }
    ],
    "name": "WellTransferred",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "DEPTH_UNIT",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "WELLHEAD_BURN",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "internalType": "uint256",
        "name": "wellSupply",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "claimPriceWei",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "baseRatePerSec",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "volBps",
        "type": "uint256"
      }
    ],
    "name": "addCommodity",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "id",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "commodityId",
        "type": "uint256"
      }
    ],
    "name": "claimWell",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "commodities",
    "outputs": [
      {
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "internalType": "uint256",
        "name": "wellSupply",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "wellsClaimed",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "claimPriceWei",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "baseRatePerSec",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "volBps",
        "type": "uint256"
      },
      {
        "internalType": "bool",
        "name": "active",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "commodityCount",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "gushAmount",
        "type": "uint256"
      }
    ],
    "name": "deepenWell",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "emissionBudget",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "feeRecipient",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "fundBudget",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "gush",
    "outputs": [
      {
        "internalType": "contract IERC20",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      }
    ],
    "name": "gushWell",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "toOperator",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "oracle",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      }
    ],
    "name": "pendingGush",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "reclaimBudget",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "commodityId",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "baseRatePerSec",
        "type": "uint256"
      }
    ],
    "name": "setBaseRate",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "commodityId",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "claimPriceWei",
        "type": "uint256"
      }
    ],
    "name": "setClaimPrice",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "commodityId",
        "type": "uint256"
      },
      {
        "internalType": "bool",
        "name": "active",
        "type": "bool"
      }
    ],
    "name": "setCommodityActive",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      }
    ],
    "name": "setFeeRecipient",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "oracle_",
        "type": "address"
      }
    ],
    "name": "setOracle",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "bps",
        "type": "uint256"
      }
    ],
    "name": "setSettlementFee",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "commodityId",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "volBps",
        "type": "uint256"
      }
    ],
    "name": "setVolatility",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "settlementFeeBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      }
    ],
    "name": "transferWell",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "wellCount",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "wellId",
        "type": "uint256"
      }
    ],
    "name": "wellRatePerSec",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "wells",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "commodityId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "depth",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "accrued",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "lastUpdate",
        "type": "uint256"
      },
      {
        "internalType": "bool",
        "name": "exists",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "commodityId",
        "type": "uint256"
      }
    ],
    "name": "wellsRemaining",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

Source code

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

/*
        .      GUSH PROTOCOL — The Rig.
       / \\     Claim a well. Run the bit. Let it gush.
      / . \\
     /  o  \\    Wellhead → wallet, in three onchain stages:
    (___|___)
        |        01  CLAIM A WELL   Each well is a unique onchain slot tied to a
        |            real extractive market (WTI, BRENT, NATGAS, COPPER, URANIUM…).
        |            Supply of wells per commodity is FIXED. Early claimers drill
        |            the richest fields; latecomers drill what's left of Alberta.
        |
        |        02  RUN THE BIT     Wells produce $GUSH while you operate them.
        |            Output tracks the real volatility of the underlying commodity
        |            — a hot tape multiplies throughput; a quiet tape seeps slow.
        |
        v        03  LET IT GUSH     Extracted barrels settle to $GUSH at the
    ~~~~~~~~~        wellhead. The protocol fee recipient takes a cut of every
    ~ RESERVOIR      settlement to fund the board. Burn $GUSH to DEEPEN a well and
    ~~~~~~~~~        raise its base output — the only sink in the system, and it's
                     a drill bit.

    NON-RUGGABLE BY CONSTRUCTION:
      • A well, once claimed, belongs to its operator forever. The owner has NO
        path to seize, freeze, or reassign a well, and can NEVER block `gush()`
        or `deepen()`. Wells are freely transferable by their operator.
      • $GUSH payouts come ONLY from a pre-funded emission budget. The protocol
        never mints. If the budget empties, wells simply pay what remains.
      • ETH from claims is forwarded to the immutable fee recipient on receipt —
        it is never custodied here.
      • The owner can only: register commodities, tune volatility / base rates /
        claim prices, and reclaim UNALLOCATED emission budget. Nothing else.
*/

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

/// @title GushProtocol
/// @notice The Rig: claim wells on extractive markets, run the bit, let it gush.
contract GushProtocol is Ownable {
    using SafeERC20 for IERC20;

    /// @notice The reward token, $GUSH. Wells pay out from a pre-funded budget of it.
    IERC20 public immutable gush;

    /// @notice Where well-claim ETH is forwarded (e.g. GushFeeRouter). Owner-set routing.
    address public feeRecipient;

    /// @notice Address permitted to push live volatility multipliers (the "board" oracle).
    address public oracle;

    /// @dev Dead address for the burn sink. $GUSH sent here can never return.
    address public constant WELLHEAD_BURN = 0x000000000000000000000000000000000000dEaD;

    /// @dev Depth is measured in the same 18-dec units as burned $GUSH.
    ///      Base output doubles for every DEPTH_UNIT of $GUSH burned into a well.
    uint256 public constant DEPTH_UNIT = 100 ether;

    /// @dev Basis-points denominator.
    uint256 public constant BPS = 10_000;

    /// @notice Cut of every settlement (in $GUSH) routed to the fee recipient. Max 20%.
    uint256 public settlementFeeBps = 1_000; // 10%

    struct Commodity {
        string symbol; // "WTI", "BRENT", "NATGAS", "COPPER", "URANIUM", ...
        uint256 wellSupply; // max wells that can ever be claimed on this market
        uint256 wellsClaimed; // wells claimed so far
        uint256 claimPriceWei; // ETH cost to claim one well here
        uint256 baseRatePerSec; // $GUSH/sec at depth 0, volatility 1x
        uint256 volBps; // volatility multiplier; 10_000 = 1x, 20_000 = 2x (hot tape)
        bool active; // whether new wells may be claimed
    }

    struct Well {
        uint256 commodityId;
        address operator; // current owner of the well
        uint256 depth; // extra depth from burns (18-dec, same units as $GUSH)
        uint256 accrued; // $GUSH accounted but not yet paid out
        uint256 lastUpdate; // last accrual timestamp
        bool exists;
    }

    Commodity[] public commodities;
    Well[] public wells;

    /// @notice $GUSH reserved as emission budget (funded by anyone via fundBudget).
    uint256 public emissionBudget;

    // ── events ──────────────────────────────────────────────────────────────
    event CommodityAdded(uint256 indexed id, string symbol, uint256 wellSupply, uint256 claimPriceWei);
    event VolatilitySet(uint256 indexed id, uint256 volBps);
    event BaseRateSet(uint256 indexed id, uint256 baseRatePerSec);
    event ClaimPriceSet(uint256 indexed id, uint256 claimPriceWei);
    event CommodityActive(uint256 indexed id, bool active);
    event FeeRecipientSet(address indexed recipient);
    event OracleSet(address indexed oracle);
    event SettlementFeeSet(uint256 bps);
    event BudgetFunded(address indexed from, uint256 amount);
    event BudgetReclaimed(address indexed to, uint256 amount);

    event WellClaimed(uint256 indexed wellId, uint256 indexed commodityId, address indexed operator, uint256 pricePaid);
    event WellTransferred(uint256 indexed wellId, address indexed from, address indexed to);
    event Gushed(uint256 indexed wellId, address indexed operator, uint256 toOperator, uint256 fee);
    event Deepened(uint256 indexed wellId, address indexed operator, uint256 gushBurned, uint256 newDepth);

    constructor(address gush_, address feeRecipient_) Ownable(msg.sender) {
        require(gush_ != address(0), "zero gush");
        require(feeRecipient_ != address(0), "zero recipient");
        gush = IERC20(gush_);
        feeRecipient = feeRecipient_;
        oracle = msg.sender;
    }

    // ──────────────────────────────── Admin ──────────────────────────────────

    /// @notice Register a new extractive market with a fixed well supply.
    function addCommodity(
        string calldata symbol,
        uint256 wellSupply,
        uint256 claimPriceWei,
        uint256 baseRatePerSec,
        uint256 volBps
    ) external onlyOwner returns (uint256 id) {
        require(wellSupply > 0, "zero supply");
        require(volBps > 0, "zero vol");
        id = commodities.length;
        commodities.push(
            Commodity({
                symbol: symbol,
                wellSupply: wellSupply,
                wellsClaimed: 0,
                claimPriceWei: claimPriceWei,
                baseRatePerSec: baseRatePerSec,
                volBps: volBps,
                active: true
            })
        );
        emit CommodityAdded(id, symbol, wellSupply, claimPriceWei);
    }

    /// @notice Push a live volatility multiplier for a market. Oracle or owner only.
    ///         Accrues every subsequent second at the new rate; past accrual is safe
    ///         because wells checkpoint their accrual before any rate change matters.
    function setVolatility(uint256 commodityId, uint256 volBps) external {
        require(msg.sender == oracle || msg.sender == owner(), "not oracle");
        require(volBps > 0, "zero vol");
        commodities[commodityId].volBps = volBps;
        emit VolatilitySet(commodityId, volBps);
    }

    function setBaseRate(uint256 commodityId, uint256 baseRatePerSec) external onlyOwner {
        commodities[commodityId].baseRatePerSec = baseRatePerSec;
        emit BaseRateSet(commodityId, baseRatePerSec);
    }

    function setClaimPrice(uint256 commodityId, uint256 claimPriceWei) external onlyOwner {
        commodities[commodityId].claimPriceWei = claimPriceWei;
        emit ClaimPriceSet(commodityId, claimPriceWei);
    }

    function setCommodityActive(uint256 commodityId, bool active) external onlyOwner {
        commodities[commodityId].active = active;
        emit CommodityActive(commodityId, active);
    }

    function setFeeRecipient(address recipient) external onlyOwner {
        require(recipient != address(0), "zero recipient");
        feeRecipient = recipient;
        emit FeeRecipientSet(recipient);
    }

    function setOracle(address oracle_) external onlyOwner {
        require(oracle_ != address(0), "zero oracle");
        oracle = oracle_;
        emit OracleSet(oracle_);
    }

    function setSettlementFee(uint256 bps) external onlyOwner {
        require(bps <= 2_000, "fee too high"); // hard cap 20%
        settlementFeeBps = bps;
        emit SettlementFeeSet(bps);
    }

    /// @notice Top up the $GUSH emission budget. Anyone may fund the board.
    function fundBudget(uint256 amount) external {
        require(amount > 0, "zero amount");
        gush.safeTransferFrom(msg.sender, address(this), amount);
        emissionBudget += amount;
        emit BudgetFunded(msg.sender, amount);
    }

    /// @notice Reclaim UNALLOCATED emission budget only — never an operator's payout.
    function reclaimBudget(address to, uint256 amount) external onlyOwner {
        require(to != address(0), "zero to");
        require(amount <= emissionBudget, "exceeds budget");
        emissionBudget -= amount;
        gush.safeTransfer(to, amount);
        emit BudgetReclaimed(to, amount);
    }

    // ─────────────────────────────── The Rig ─────────────────────────────────

    /// @notice Claim the next available well on a commodity. Pays ETH to the wellhead.
    /// @dev Overpayment is refunded. ETH is forwarded to the fee recipient on receipt.
    function claimWell(uint256 commodityId) external payable returns (uint256 wellId) {
        Commodity storage c = commodities[commodityId];
        require(c.active, "market closed");
        require(c.wellsClaimed < c.wellSupply, "field depleted");
        require(msg.value >= c.claimPriceWei, "underpaid");

        c.wellsClaimed += 1;
        wellId = wells.length;
        wells.push(
            Well({
                commodityId: commodityId,
                operator: msg.sender,
                depth: 0,
                accrued: 0,
                lastUpdate: block.timestamp,
                exists: true
            })
        );

        uint256 price = c.claimPriceWei;
        // Forward exactly the claim price to the wellhead; refund any overpayment.
        if (price > 0) {
            (bool ok,) = feeRecipient.call{value: price}("");
            require(ok, "wellhead send failed");
        }
        uint256 refund = msg.value - price;
        if (refund > 0) {
            (bool ok2,) = msg.sender.call{value: refund}("");
            require(ok2, "refund failed");
        }

        emit WellClaimed(wellId, commodityId, msg.sender, price);
    }

    /// @notice Settle extracted barrels to $GUSH. Callable only by the well operator.
    ///         The fee recipient takes `settlementFeeBps` of the payout.
    function gushWell(uint256 wellId) external returns (uint256 toOperator) {
        Well storage w = wells[wellId];
        require(w.exists, "no well");
        require(w.operator == msg.sender, "not operator");

        _accrue(wellId);
        uint256 owed = w.accrued;
        if (owed == 0) {
            emit Gushed(wellId, msg.sender, 0, 0);
            return 0;
        }

        // Pay only from the funded budget; never mint, never dip past budget.
        uint256 pay = owed > emissionBudget ? emissionBudget : owed;
        w.accrued = owed - pay; // carry forward any unpayable remainder
        emissionBudget -= pay;

        uint256 fee = (pay * settlementFeeBps) / BPS;
        toOperator = pay - fee;

        if (fee > 0) gush.safeTransfer(feeRecipient, fee);
        if (toOperator > 0) gush.safeTransfer(msg.sender, toOperator);

        emit Gushed(wellId, msg.sender, toOperator, fee);
    }

    /// @notice Burn $GUSH into a well to DEEPEN it and raise its base output.
    ///         The only sink in the system. Burned $GUSH is sent to 0xdead.
    function deepenWell(uint256 wellId, uint256 gushAmount) external {
        Well storage w = wells[wellId];
        require(w.exists, "no well");
        require(w.operator == msg.sender, "not operator");
        require(gushAmount > 0, "zero burn");

        // Checkpoint accrual at the OLD rate before depth changes.
        _accrue(wellId);

        // Real burn: move $GUSH out of circulation to the dead address.
        gush.safeTransferFrom(msg.sender, WELLHEAD_BURN, gushAmount);
        w.depth += gushAmount;

        emit Deepened(wellId, msg.sender, gushAmount, w.depth);
    }

    /// @notice Transfer a well to another operator. Settles nothing; pending accrual
    ///         travels with the well. Only the current operator may transfer.
    function transferWell(uint256 wellId, address to) external {
        Well storage w = wells[wellId];
        require(w.exists, "no well");
        require(w.operator == msg.sender, "not operator");
        require(to != address(0), "zero to");
        _accrue(wellId); // freeze accrual to the moment of transfer
        w.operator = to;
        emit WellTransferred(wellId, msg.sender, to);
    }

    // ─────────────────────────────── Accrual ─────────────────────────────────

    function _rate(Well storage w) internal view returns (uint256) {
        Commodity storage c = commodities[w.commodityId];
        // base * (1 + depth/DEPTH_UNIT) * volatility
        uint256 depthScaled = c.baseRatePerSec * (DEPTH_UNIT + w.depth) / DEPTH_UNIT;
        return depthScaled * c.volBps / BPS;
    }

    function _accrue(uint256 wellId) internal {
        Well storage w = wells[wellId];
        if (block.timestamp <= w.lastUpdate) return;
        uint256 elapsed = block.timestamp - w.lastUpdate;
        w.accrued += elapsed * _rate(w);
        w.lastUpdate = block.timestamp;
    }

    // ─────────────────────────────── Views ───────────────────────────────────

    function commodityCount() external view returns (uint256) {
        return commodities.length;
    }

    function wellCount() external view returns (uint256) {
        return wells.length;
    }

    /// @notice Current output of a well in $GUSH per second (depth × volatility applied).
    function wellRatePerSec(uint256 wellId) external view returns (uint256) {
        return _rate(wells[wellId]);
    }

    /// @notice Pending $GUSH ready to gush from a well, live to `block.timestamp`.
    function pendingGush(uint256 wellId) external view returns (uint256) {
        Well storage w = wells[wellId];
        if (!w.exists) return 0;
        uint256 acc = w.accrued;
        if (block.timestamp > w.lastUpdate) {
            acc += (block.timestamp - w.lastUpdate) * _rate(w);
        }
        return acc;
    }

    /// @notice How many wells remain claimable on a commodity.
    function wellsRemaining(uint256 commodityId) external view returns (uint256) {
        Commodity storage c = commodities[commodityId];
        return c.wellSupply - c.wellsClaimed;
    }
}
Chain explorer2035msChain node87ms