# Gully Chain Docs (full text) > Every page of https://docs.gullychain.xyz in sidebar order, as Markdown. Index: https://docs.gullychain.xyz/llms.txt. Contract registry: https://docs.gullychain.xyz/llms-contracts.txt. # GullyChain docs Source: https://docs.gullychain.xyz/ > Developer docs for GullyChain, an Arbitrum Orbit L3 by Gully Labs. The testnet is live: chain ID 485590, RPC, bridge, faucet, explorer and contract addresses. GullyChain is an **Arbitrum Orbit L3** built by Gully Labs. It runs Arbitrum Nitro, settles to Arbitrum and pays gas in ETH. Any EVM contract, wallet or tool works on it unchanged, and Stylus lets you write contracts in Rust. The **testnet is live** and settles to Arbitrum Sepolia. Mainnet will settle to Arbitrum One; it is not live yet. > [!LIVE] > Watch the chain in real time on the **[testnet stats page](https://gullychain.xyz/testnet/)**: block height, transactions and gas per block, a live block feed, batch posting and service status. ## Start here | If you want to | Read | |---|---| | Use the Gully Chain app: Shorts, memberships, memes, one-tap approvals, .gully names, Season 0, Telegram | [Getting started](https://docs.gullychain.xyz/getting-started/) | | Connect a wallet, get test ETH and deploy a first contract | [Quickstart](https://docs.gullychain.xyz/quickstart/) | | Everything to deploy and verify in one page: RPCs, Foundry, Hardhat, viem, every contract with its status | [Deploy on Gully Chain](https://docs.gullychain.xyz/deploy/) | | Chain ID, RPC URL, explorer and other settings | [Network reference](https://docs.gullychain.xyz/network/) | | Addresses of WETH, Permit2, EntryPoint, the bridge and more | [Contract addresses](https://docs.gullychain.xyz/contracts/) | | Move ETH or tokens between Arbitrum Sepolia and GullyChain | [Bridging](https://docs.gullychain.xyz/bridging/) | | Bridge USDC in, or redeem retired glUSD 1:1 for USDC.e | [Stablecoins](https://docs.gullychain.xyz/stablecoins/) | | Passkey smart accounts, session keys and sponsored gas | [Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/) | | Add Sign in with Gully to your app | [Gully ID sign-in](https://docs.gullychain.xyz/gully-id/) | | Run a multisig with passkey owners | [Gully Safe](https://docs.gullychain.xyz/safe/) | | Read the chain, the indexer or prices from code | [RPC and indexer API](https://docs.gullychain.xyz/rpc-api/), [Price oracle](https://docs.gullychain.xyz/oracle/) | | Write contracts in Rust | [Stylus](https://docs.gullychain.xyz/stylus/) | | See what is live and what is coming | [Status](https://docs.gullychain.xyz/status/) and the [Changelog](https://docs.gullychain.xyz/changelog/) | ## Testnet at a glance | Setting | Value | |---|---| | Network name | GullyChain Testnet | | Chain ID | `485590` (`0x768d6`) | | RPC | `https://rpc.gullychain.xyz`, with [fallbacks](https://docs.gullychain.xyz/network/#public-rpcs) | | Explorer | [testnet-explorer.gullychain.xyz](https://testnet-explorer.gullychain.xyz/) | | Bridge | [bridge.gullychain.xyz](https://bridge.gullychain.xyz/) | | Faucet | [faucet.gullychain.xyz](https://faucet.gullychain.xyz/) | | Token list | [gullychain.xyz/tokenlist.json](https://gullychain.xyz/tokenlist.json) | | Machine-readable | [/chain.json](https://docs.gullychain.xyz/chain.json), [/addresses.json](https://docs.gullychain.xyz/addresses.json), [/contracts.json](https://docs.gullychain.xyz/contracts.json), [/llms-contracts.txt](https://docs.gullychain.xyz/llms-contracts.txt), [/llms.txt](https://docs.gullychain.xyz/llms.txt), [/llms-full.txt](https://docs.gullychain.xyz/llms-full.txt) | | Sign-in | [gullyid.xyz](https://gullyid.xyz/) (Gully ID) | | Gas token | ETH (18 decimals) | | Parent chain | Arbitrum Sepolia (`421614`) | ## How the chain fits together Your app talks to GullyChain over standard EVM JSON-RPC. GullyChain is a layer 3: its sequencer posts transaction batches to Arbitrum Sepolia, and Arbitrum in turn settles to Ethereum. Mainnet will use Arbitrum One as the parent chain. What ships on top of the bare chain, and where each piece stands today: - **Bridge and tokens** (live): the Gully Bridge with a Hyperlane fast lane (native ETH) and the canonical Arbitrum bridge for ETH and ERC-20 tokens, plus WETH9, Permit2, Multicall3 and CreateX. See [Bridging](https://docs.gullychain.xyz/bridging/). - **Stablecoins** (live): USDC.e under the Circle Bridged USDC Standard is the stablecoin; glUSD is retired and redeemable 1:1. See [Stablecoins](https://docs.gullychain.xyz/stablecoins/). - **Smart accounts and sponsored gas** (live): Kernel v3.3 accounts with passkeys and session keys, a public bundler and an ERC-7677 paymaster. See [Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/). - **Gully ID and Gully Safe** (live): one passkey sign-in for every Gully app, and Safe 1.4.1 multisigs. See [Gully ID sign-in](https://docs.gullychain.xyz/gully-id/) and [Gully Safe](https://docs.gullychain.xyz/safe/). - **Uniswap v3 and Gully Swap** (live): the Uniswap v3 DEX with the Gully Swap router. See [Contract addresses](https://docs.gullychain.xyz/contracts/). - **.gully names** (live): readable names like `alice.gully`. See [.gully names](https://docs.gullychain.xyz/names/). - **Arcade and referrals** (live): free-to-play games with on-chain leaderboards, and on-chain referrals paid from platform fees. See [Arcade](https://docs.gullychain.xyz/arcade/) and [Referrals](https://docs.gullychain.xyz/referrals/). - **Gully Social** (live): profiles on .gully names, follows, posts, invites and a verified badge paid through Gully Pay. See [Gully Social](https://docs.gullychain.xyz/social/). - **Copy trading** (live): mirror a leader's trades from your own wallet with a revocable session key and on-chain limits. See [Copy trading](https://docs.gullychain.xyz/copy-trading/). - **Quests** (live): on-chain quests verified by the chain itself, with multi-step quests, streaks, soulbound badges and a leaderboard. See [Quests](https://docs.gullychain.xyz/quests/). - **Offerwall** (live): advertisers fund quests through Gully Pay, players earn USDC or points, publishers embed the wall at [offers.gullychain.xyz](https://offers.gullychain.xyz/). See [Offerwall](https://docs.gullychain.xyz/offerwall/). - **Real-world asset rails** (testnet rails live): ERC-3643 and ONCHAINID for licensed issuers. See [Real-world assets](https://docs.gullychain.xyz/rwa/). - **Gully Core** (live): Gully Chain's launchpad and DEX core. Launch a token in one transaction with its liquidity locked forever, anti-snipe opening fees and an optional creator tax. See [Gully Core](https://docs.gullychain.xyz/gully-core/). - **Sentry Keys** (live on testnet): claim a free testnet key at [sentry.gullychain.xyz](https://sentry.gullychain.xyz/) and run the watcher. See [Run a Sentry](https://docs.gullychain.xyz/sentry/). > [!WARNING] > **Two clocks.** On GullyChain `block.number` inside a contract is the **parent chain's** block number. Use `block.timestamp`, or `ArbSys(0x64).arbBlockNumber()` for the L3 block. See [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number). > [!NOTE] > The testnet may be reset as the chain moves toward mainnet. Do not keep anything on it that you cannot redeploy. # Getting started with the Gully Chain app Source: https://docs.gullychain.xyz/getting-started/ > A ten-minute tour of the Gully Chain app on testnet: sign up with a passkey, watch Shorts, join fan memberships, make memes and launch them as coins, approve small payments with one tap in Gully ID, claim a .gully name, play Season 0 and open Gully in Telegram. This guide is for people using the Gully Chain app at [app.gullychain.xyz](https://app.gullychain.xyz/). Building on the chain instead? Start with the [Quickstart](https://docs.gullychain.xyz/quickstart/) or the [developer portal](https://dev.gullychain.xyz/). > [!NOTE] > Gully Chain runs on **testnet**. Tokens on it have no real-world value, and the testnet may be reset before mainnet. ## 1. Join with a passkey Open [app.gullychain.xyz/welcome](https://app.gullychain.xyz/welcome) and create your **Gully ID**. A passkey (Face ID, a fingerprint or your device PIN) is your sign-in and your wallet key: there is no seed phrase to write down and no card. Your profile is your wallet, and gas is sponsored for your first transactions. You can also sign in at [gullyid.xyz](https://gullyid.xyz/) with Telegram or Farcaster, and install Gully ID as an app from your browser's menu. Need testnet ETH? Use the [faucet](https://faucet.gullychain.xyz/) (0.0005 ETH per address per day) or the [bridge](https://bridge.gullychain.xyz/). ## 2. Find your way around The app has five tabs: | Tab | What is there | |---|---| | **Home** | Your feed: posts, replies and likes from people you follow | | **Discover** | People, creators, tokens and quests, with one search box for all of them | | **Create** | Post, upload, make a meme or launch a coin | | **Inbox** | Messages, rooms, notifications and tips | | **Me** | Your profile, wallet, memberships, quests and settings | The **What's new** sheet in the app shows each release; the full history is in the [Changelog](https://docs.gullychain.xyz/changelog/). ## 3. Watch Shorts [Shorts](https://app.gullychain.xyz/shorts) are short vertical videos from creators. Swipe up for the next one, tip the creator, or share it: every Short has a share card and an embed code (see [Share and embed](https://docs.gullychain.xyz/embeds/)). Longer films and videos are under [Watch](https://app.gullychain.xyz/watch). ## 4. Join a creator: memberships and locked content Creators can sell **monthly memberships**. Members unlock the creator's **members-only posts and videos**; everyone else sees that the post is locked and can join from there. Payments settle in **USDC.e** to the creator's wallet. - **Fans:** join from a creator's profile or from one of their locked posts. Your memberships are under **Me** (renewals under your one-tap limit take one tap, see below). - **Creators:** set your price and perks in Studio at [/studio/memberships](https://app.gullychain.xyz/studio/memberships), then mark a post or video as members-only when you publish it. ## 5. Make a meme, Remix it, Launch it as a coin Open the meme maker at [/create/meme](https://app.gullychain.xyz/create/meme): pick an image, add your text and post it. On any meme you can: - **Remix:** re-caption, stitch or duet someone else's meme. The remix credits and links the original automatically, and a creator can turn remixes off. - **Launch as coin:** on your own meme, turn it into a token on Gully Chain. You review the launch and approve it with your passkey (launching a coin always needs the passkey). Browse memes and the meme contest at [/memes](https://app.gullychain.xyz/memes). ### Launch on Gully Core Any token, meme or not, launches on **Gully Core**, the chain's launchpad and DEX core. Open [/launch](https://app.gullychain.xyz/launch): pick a name, a ticker and a picture and launch in one transaction. The token trades from the first block, its liquidity is locked forever, and an opening fee that falls over the first minute makes sniping expensive (most of it comes back to you). Trade it with [Swap](https://app.gullychain.xyz/swap), follow it on its token page, and see the numbers in [Analytics](https://app.gullychain.xyz/analytics). Fees and limits: [Gully Core](https://docs.gullychain.xyz/gully-core/). ## 6. One-tap approvals in Gully ID You do not need your passkey for every small payment. In **Gully ID**, small, everyday spends take **one tap**: | Tier | What | How you approve | |---|---|---| | No prompt | Free actions: quest check-ins and claiming XP, badges and rewards | Nothing to approve | | One tap | Tips, small swaps from USDC.e, pay-per-view unlocks and membership renewals, to recipients you have paid before, under the app's daily limit | One button, no Face ID | | Passkey | Anything over the limit, a first payment to someone new, launching a coin, bridging, ETH, unknown contracts | The full review and your passkey | | Always passkey | Security changes: recovery, devices, raising your limit | Your passkey, every time | The **daily limit is $25 by default** (in USDC.e), adjustable per app from $0 to $250; $0 allows free actions only. It resets every UTC day. The rules are enforced **on chain** by your smart account (CallPolicy, a 7-day TimestampPolicy and GullySessionPolicy `0xFDEB7b7715200dBc94A058BA1254b863c08D070E`), so even a leaked session key cannot spend past them. See or revoke your connected apps and their limits in Gully ID under **Me → Connected apps**. Gully ID also has **Send** and **Receive**: Receive shows your address as a QR code to scan, and Send pays another account from your wallet. ## 7. Claim your .gully name A `.gully` name is a readable name for your wallet, like `you.gully`, used for your profile URL (`app.gullychain.xyz/@you`) and for payments. Claim it on the **ID** tab in [Gully ID](https://gullyid.xyz/) or in the app at [/names](https://app.gullychain.xyz/names). Registration is free and first come, first served on testnet. More in [.gully names](https://docs.gullychain.xyz/names/). ## 8. Season 0 **Season 0** runs in the app at [/season-0](https://app.gullychain.xyz/season-0) until **2026-11-26**. It is a set of on-chain quests: claim a Sentry Key, make your first swap, bridge to Gully Chain, launch a token, follow the Gully Chain Telegram channel and refer a friend. Completed quests count XP on the [quest leaderboard](https://app.gullychain.xyz/quests/leaderboard). > [!WARNING] > Early activity is recorded on chain, no airdrop is promised. Season 0 rewards are testnet XP and badges. How quests work under the hood: [Quests](https://docs.gullychain.xyz/quests/). ## 9. Gully in Telegram The **Telegram Mini App** puts Gully inside Telegram. Open it from a Gully bot's menu button (it lives at [app.gullychain.xyz/tg](https://app.gullychain.xyz/tg); in a normal browser that page explains how to open it). Sign in with your Telegram account and use your wallet without leaving the chat. You can pair it with your passkey account from your phone's browser, or back up a Telegram-first wallet with a passkey. Also on Telegram: | | | |---|---| | [Gully Chain News](https://t.me/GullyChain) | Releases, contracts, network status | | [Gully Chain Bot](https://t.me/GullyChainBot) | Non-custodial trading from your passkey account: `/buy`, `/sell`, `/copy` | | [Gully Quest Bot](https://t.me/GullyQuestBot) | Track quests and claim rewards | | [Gully Buy Bot](https://t.me/GullyBuyBot) | Posts every buy of your token in your group | The full list is on [Community and bots](https://docs.gullychain.xyz/community/). ## Coming soon > [!SOON] > These are not live yet: Gully Music, Radio, Watch series and Gully Pass; live video and chat; bridging from Ethereum, Base, BNB Chain, Solana and Arbitrum; native iOS > and Android apps; creator tiers ($25 to $500 a year); ads; Sign in with Apple. # Quickstart Source: https://docs.gullychain.xyz/quickstart/ > Start building on GullyChain in three steps: add GullyChain Testnet to your wallet, get free test ETH from the faucet or bridge, then deploy with Foundry. Three steps: add the network, get some test ETH, deploy. Test ETH is free and has no value. ## 1. Add the network The quickest way is the **Add to wallet** button on the [testnet page](https://gullychain.xyz/testnet/). It adds the network to MetaMask, Rabby and other browser wallets in one click. To add it by hand, use these values: | Field | Value | |---|---| | Network name | GullyChain Testnet | | RPC URL | `https://rpc.gullychain.xyz` (fallbacks: [Public RPCs](https://docs.gullychain.xyz/network/#public-rpcs)) | | Chain ID | `485590` | | Currency symbol | ETH | | Block explorer | `https://testnet-explorer.gullychain.xyz` | From a dapp, ask the wallet to add it with `wallet_addEthereumChain`: ```js await window.ethereum.request({ method: "wallet_addEthereumChain", params: [{ chainId: "0x768d6", // 485590 chainName: "GullyChain Testnet", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpcUrls: [ "https://rpc.gullychain.xyz", "https://rpc.gullyrpc.xyz/gullychain/evm/485590", "https://rpc2.gullychain.xyz", "https://testnet-rpc.gullychain.xyz", ], blockExplorerUrls: ["https://testnet-explorer.gullychain.xyz"], }], }); ``` ## 2. Get test ETH GullyChain uses ETH for gas. There are two ways to get it. ### Option A: the faucet The [Gully faucet](https://faucet.gullychain.xyz/) sends **0.0005 ETH per address per day** straight to your address on GullyChain. Sign in with [Gully ID](https://docs.gullychain.xyz/gully-id/) (a passkey, a wallet or email) and press claim. The recipient must be your Gully smart account, or an address that has already sent a transaction on GullyChain or Arbitrum Sepolia; one claim per account, address and IP every 24 hours. That is enough for a few contract deploys, and it is the fastest way to start. ### Option B: bridge from Arbitrum Sepolia For more ETH, bring it over from Arbitrum Sepolia: 1. Get Sepolia ETH from a public Sepolia faucet, for example the Google Cloud Web3 faucet or a proof-of-work faucet. Some faucets pay on Arbitrum Sepolia directly, so you can skip step 2. 2. On [bridge.arbitrum.io](https://bridge.arbitrum.io/), bridge from Sepolia to Arbitrum Sepolia. This takes about 10 to 15 minutes. 3. Open the [Gully Bridge](https://bridge.gullychain.xyz/), connect your wallet and deposit. ETH arrives on GullyChain in **about a minute**. The [Bridging](https://docs.gullychain.xyz/bridging/) page explains what happens under the hood and how to deposit from code. ## 3. Deploy a contract Point your tools at the RPC. Any EVM contract works. ### Foundry ```sh # check the connection: prints 485590 cast chain-id --rpc-url https://rpc.gullychain.xyz # deploy with a keystore account # (create one first with: cast wallet import dev --interactive) forge create src/Counter.sol:Counter \ --rpc-url https://rpc.gullychain.xyz \ --account dev --broadcast ``` You can name the endpoint in `foundry.toml` and pass `--rpc-url gully_testnet` instead: ```toml [rpc_endpoints] gully_testnet = "https://rpc.gullychain.xyz" ``` The [explorer](https://testnet-explorer.gullychain.xyz/) supports contract verification. You can upload the source in its UI after deploying. ### Hardhat ```ts // hardhat.config.ts import type { HardhatUserConfig } from "hardhat/config"; const config: HardhatUserConfig = { solidity: "0.8.24", networks: { gullyTestnet: { url: "https://rpc.gullychain.xyz", chainId: 485590, accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], }, }, }; export default config; ``` Deploy with your usual script or Ignition module and add `--network gullyTestnet`. Keep keys in environment variables or a secrets manager, never in the repo. ### viem ```ts import { defineChain, createPublicClient, createWalletClient, fallback, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; export const gullyTestnet = defineChain({ id: 485590, name: "GullyChain Testnet", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpcUrls: { default: { http: [ "https://rpc.gullychain.xyz", "https://rpc.gullyrpc.xyz/gullychain/evm/485590", "https://rpc2.gullychain.xyz", "https://testnet-rpc.gullychain.xyz", ], }, }, blockExplorers: { default: { name: "Gully Explorer", url: "https://testnet-explorer.gullychain.xyz" }, }, testnet: true, }); // every public RPC in order, the first healthy one wins (see /network/#public-rpcs) const transport = fallback( gullyTestnet.rpcUrls.default.http.map((url) => http(url, { timeout: 8_000, retryCount: 0 })), { rank: false, retryCount: 1 }, ); const publicClient = createPublicClient({ chain: gullyTestnet, transport }); console.log(await publicClient.getBlockNumber()); // deploy: abi and bytecode come from your compiler output const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const wallet = createWalletClient({ account, chain: gullyTestnet, transport }); const hash = await wallet.deployContract({ abi, bytecode, args: [] }); const receipt = await publicClient.waitForTransactionReceipt({ hash }); console.log("deployed at", receipt.contractAddress); ``` > [!NOTE] > Multicall3 is deployed at its canonical address `0xcA11…CA11`, so viem's `multicall` action and wagmi's `useReadContracts` work on GullyChain out of the box. See [Contract addresses](https://docs.gullychain.xyz/contracts/). ### curl ```sh curl -s https://rpc.gullychain.xyz \ -H "content-type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}' ``` ## Next steps - Look up WETH, Permit2 and bridge addresses on [Contract addresses](https://docs.gullychain.xyz/contracts/). - Read the [Network reference](https://docs.gullychain.xyz/network/) for what behaves differently from Ethereum, such as `block.number` and when blocks are produced. - Watch your transactions land on the [live stats page](https://gullychain.xyz/testnet/). # Deploy on Gully Chain Source: https://docs.gullychain.xyz/deploy/ > Everything to deploy and verify a contract on Gully Chain Testnet (chain 485590) in one page: RPCs, explorer, Sourcify verification, faucet, bridge, Foundry, Hardhat, viem and ethers config, every standard and Gully contract address with its live status, chain quirks and rate limits. One page with everything a team needs to ship on **Gully Chain Testnet** without asking us first. The same data is machine-readable: [/chain.json](https://docs.gullychain.xyz/chain.json) (wallet and chain-list parameters) and [/addresses.json](https://docs.gullychain.xyz/addresses.json) (every contract below, with its status). ## Network | Setting | Value | |---|---| | Chain ID | `485590` (hex `0x768d6`) | | Network name | Gully Chain Testnet | | RPC (HTTPS), primary | `https://rpc.gullychain.xyz` | | RPC (HTTPS), alternatives | `https://rpc.gullyrpc.xyz/gullychain/evm/485590`, `https://rpc2.gullychain.xyz`, `https://testnet-rpc.gullychain.xyz` | | RPC with your own key | `https://rpc.gullyrpc.xyz//evm/485590` ([Gully RPC](https://app.gullyrpc.xyz), higher limits) | | RPC (WebSocket) | Not public yet. Poll over HTTPS for now (viem and ethers do this by default); see [WebSocket](#websocket) | | Explorer | [testnet-explorer.gullychain.xyz](https://testnet-explorer.gullychain.xyz/) | | Contract verification | [verify.gullychain.xyz](https://verify.gullychain.xyz/) (Sourcify, API v2 at `https://verify.gullychain.xyz/v2/`, no key) | | Faucet | [faucet.gullychain.xyz](https://faucet.gullychain.xyz/) (sign in with [Gully ID](https://docs.gullychain.xyz/gully-id/), hCaptcha, small daily drip) | | Bridge | [bridge.gullychain.xyz](https://bridge.gullychain.xyz/) (Arbitrum Sepolia to Gully Chain in about a minute) | | Gas token | ETH, 18 decimals | | Parent chain | Arbitrum Sepolia (`421614`) | | Stack | Arbitrum Orbit L3, Nitro, ArbOS 51, Cancun EVM, Stylus | | Status | [status.gullylabs.xyz](https://status.gullylabs.xyz/) (RPCs, verifier, faucet and every standard contract, checked every minute) | > [!WARNING] > **Use `rpc.gullychain.xyz` first.** Some ISP security filters (Xfinity's, for one) block hostnames that start with `testnet-`, so a setup that only lists `testnet-rpc.gullychain.xyz` can fail on a home connection while it works everywhere else. `testnet-rpc` keeps working as an alternative. ### Machine-readable files | File | What is in it | |---|---| | [docs.gullychain.xyz/chain.json](https://docs.gullychain.xyz/chain.json) (also on [dev.gullychain.xyz/chain.json](https://dev.gullychain.xyz/chain.json)) | The [ethereum-lists/chains](https://github.com/ethereum-lists/chains) entry fields (`name`, `chain`, `rpc`, `faucets`, `nativeCurrency`, `shortName`, `chainId`, `networkId`, `explorers`, `parent`), plus `eip3085`: the exact object to pass to `wallet_addEthereumChain`, the service URLs and the chain quirks. | | [docs.gullychain.xyz/addresses.json](https://docs.gullychain.xyz/addresses.json) (also on dev.) | Every contract on this page: `name`, `group`, `address`, `chainId` (485590 or 421614), `kind` (`standard`, `gully`, `parent`), `status` (`live`, `missing`), `checkedAt`, and `updatedAt` for the file. | ```js // add the network from a dapp, straight from chain.json const chain = await (await fetch("https://docs.gullychain.xyz/chain.json")).json(); await window.ethereum.request({ method: "wallet_addEthereumChain", params: [chain.eip3085] }); ``` Both files are CORS-open and regenerated from the deploy records every time the docs are built. ## Get test ETH - **Faucet:** [faucet.gullychain.xyz](https://faucet.gullychain.xyz/). Sign in with Gully ID, pass the captcha, claim. Enough for several deploys. - **More than the faucet gives:** bridge Sepolia ETH in through [bridge.gullychain.xyz](https://bridge.gullychain.xyz/) (Arbitrum Sepolia faucets are listed on [Bridging](https://docs.gullychain.xyz/bridging/)), or email [team@gullylabs.xyz](mailto:team@gullylabs.xyz) with your Gully ID and what you are building: verified developer accounts get a larger faucet allowance. ## Foundry `foundry.toml`: ```toml [profile.default] solc = "0.8.28" evm_version = "cancun" optimizer = true optimizer_runs = 200 [rpc_endpoints] gully = "https://rpc.gullychain.xyz" gully_alt = "https://testnet-rpc.gullychain.xyz" ``` Deploy and verify in one command: ```sh forge create src/Counter.sol:Counter \ --rpc-url gully \ --private-key $PRIVATE_KEY \ --broadcast \ --verify --verifier sourcify --verifier-url https://verify.gullychain.xyz/ ``` With a script (salted `CREATE2` deploys go through the Arachnid factory, so they land at the same address as on other chains): ```sh forge script script/Deploy.s.sol --rpc-url gully --broadcast \ --verify --verifier sourcify --verifier-url https://verify.gullychain.xyz/ ``` Verify a contract that is already deployed (no API key, no constructor arguments: Sourcify reads them from the creation transaction): ```sh forge verify-contract
src/Counter.sol:Counter \ --chain-id 485590 \ --rpc-url https://rpc.gullychain.xyz \ --verifier sourcify \ --verifier-url https://verify.gullychain.xyz/ \ --watch ``` Use a current Foundry (`foundryup`): the server speaks the Sourcify API v2 only. Check a result with `curl https://verify.gullychain.xyz/v2/contract/485590/
`. More, including Windows path issues and the web form: [Verify your contract](https://docs.gullychain.xyz/verify/). ## Hardhat ```ts // hardhat.config.ts (network part; the verify plugin settings are on /verify/#hardhat) export default { solidity: { version: "0.8.28", settings: { evmVersion: "cancun", optimizer: { enabled: true, runs: 200 } } }, networks: { gully: { url: "https://rpc.gullychain.xyz", chainId: 485590, accounts: [process.env.PRIVATE_KEY!] }, }, }; ``` ```sh npx hardhat run scripts/deploy.ts --network gully npx hardhat verify --network gully
``` Verification needs a Sourcify v2 capable plugin: see [Verify your contract](https://docs.gullychain.xyz/verify/#hardhat). Any Hardhat version can upload `artifacts/build-info/*.json` on [verify.gullychain.xyz](https://verify.gullychain.xyz/). ## viem ```ts import { createPublicClient, createWalletClient, defineChain, fallback, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; export const gullyTestnet = defineChain({ id: 485590, name: "Gully Chain Testnet", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpcUrls: { default: { http: ["https://rpc.gullychain.xyz", "https://testnet-rpc.gullychain.xyz"] } }, blockExplorers: { default: { name: "Gully Explorer", url: "https://testnet-explorer.gullychain.xyz" } }, contracts: { multicall3: { address: "0xcA11bde05977b3631167028862bE2a173976CA11" } }, }); const transport = fallback(gullyTestnet.rpcUrls.default.http.map((url) => http(url)), { rank: false }); export const publicClient = createPublicClient({ chain: gullyTestnet, transport }); export const walletClient = createWalletClient({ chain: gullyTestnet, transport, account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`) }); // deploy: const hash = await walletClient.deployContract({ abi, bytecode, args: [] }); ``` The full four-endpoint fallback list is on [Network reference](https://docs.gullychain.xyz/network/#viem). ## ethers v6 ```ts import { ContractFactory, JsonRpcProvider, Network, Wallet } from "ethers"; const network = Network.from(485590); const provider = new JsonRpcProvider("https://rpc.gullychain.xyz", network, { staticNetwork: network }); const wallet = new Wallet(process.env.PRIVATE_KEY!, provider); const contract = await new ContractFactory(abi, bytecode, wallet).deploy(); await contract.waitForDeployment(); console.log(await contract.getAddress()); ``` A `FallbackProvider` over every endpoint: [Network reference](https://docs.gullychain.xyz/network/#ethers-v6). ## Standard contracts The contracts that tooling expects at the **same address on every chain**. Status is the result of an `eth_getCode` check at that address; the [status page](https://status.gullylabs.xyz/) re-checks every one of them each minute (group "Chain readiness"). #### Deterministic deployers | Contract | Canonical address | Status | |---|---|---| | CREATE2 factory (Arachnid / Nick)
Used by forge script for salted CREATE2 deploys. | `0x4e59b44847b379578588920cA78FbF26c0B4956C` | Live | | ERC-2470 singleton factory | `0xce0042B868300000d44A59004Da54A005ffdcf9f` | Live | | Zoltu deterministic deployer | `0x7A0D94F55792C434d74a40883C6ed8545E406D12` | Live | | CreateX (CREATE2 / CREATE3) | `0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed` | Live | | ImmutableCreate2Factory (0age) | `0x0000000000FFe8B47B3e2130213B802212439497` | Live | | Safe singleton factory
Deployed per chain by the Safe team from their own key; requested. Use the Arachnid factory or CreateX meanwhile. | `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` | Not deployed | #### Utilities | Contract | Canonical address | Status | |---|---|---| | Multicall3
viem multicall and wagmi useReadContracts work unchanged. | `0xcA11bde05977b3631167028862bE2a173976CA11` | Live | | Permit2 | `0x000000000022D473030F116dDEE9F6B43aC78BA3` | Live | | ERC-1820 registry | `0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24` | Live | | ERC-6551 registry (token bound accounts) | `0x000000006551c19487814612e58FE06813775758` | Live | | DelegateRegistry v2 (delegate.xyz) | `0x00000000000000447e69651d841bD8D104Bed493` | Live | | EAS 1.3.0 (Ethereum Attestation Service)
EAS has no single canonical address; this is the Gully Chain deployment. | `0x412a5d2f2a1f2f8e8e7e9023371d9ace11a23aaa` | Live | | EAS SchemaRegistry 1.3.0 | `0x0fdec4B85Af441415763e06e82fB783c371FC8B1` | Live | #### ERC-4337 | Contract | Canonical address | Status | |---|---|---| | EntryPoint v0.6
The public bundler serves v0.7. | `0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789` | Live | | EntryPoint v0.7
Public bundler and paymaster: docs /account-abstraction/. | `0x0000000071727De22E5E9d8BAf0edAc6f37da032` | Live | | EntryPoint v0.8 | `0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108` | Live | | SimpleAccountFactory v0.6 | `0x9406Cc6185a346906296840746125a0E44976454` | Live | | SimpleAccountFactory v0.7 | `0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985` | Live | | SimpleAccountFactory v0.8 | `0x13E9ed32155810FDbd067D4522C492D6f68E5944` | Live | | LightAccountFactory v2.0.0 (Alchemy) | `0x0000000000400CdFef5E2714E63d8040b700BC24` | Live | | Kernel v3.3 (ZeroDev) | `0xd6CEDDe84be40893d153Be9d467CD6aD37875b28` | Live | | KernelFactory v3.3 (ZeroDev) | `0x2577507b78c2008Ff367261CB6285d44ba5eF2E9` | Live | | Safe4337Module 0.3.0 | `0x75cf11467937ce3F2f357CE24ffc3DBF8fD5c226` | Live | | SafeModuleSetup 0.3.0 | `0x2dd68b007B46fBe91B9A7c3EDa5A7a1063cB5b47` | Live | | P256 verifier (Daimo) | `0xc2b78104907F722DABAc4C69f826a522B2754De4` | Live | #### Safe 1.4.1 | Contract | Canonical address | Status | |---|---|---| | Safe 1.4.1 | `0x41675C099F32341bf84BFc5382aF534df5C7461a` | At Gully's address `0x639245e8476E03e789a244f279b5843b9633b2E7` | | SafeL2 1.4.1 | `0x29fcB43b46531BcA003ddC8FCB67FFE91900C762` | At Gully's address `0x76667330c237Fb40f28d74563cdAAae4b06C23Ec` | | SafeProxyFactory 1.4.1 | `0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67` | At Gully's address `0xd9d2Ba03a7754250FDD71333F444636471CACBC4` | | CompatibilityFallbackHandler 1.4.1 | `0xfd0732Dc9E303f09fCEf3a7388Ad10A83459Ec99` | At Gully's address `0xcB4a8d3609A7CCa2D9c063a742f75c899BF2f7b5` | | MultiSend 1.4.1 | `0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526` | At Gully's address `0x7B21BBDBdE8D01Df591fdc2dc0bE9956Dde1e16C` | | MultiSendCallOnly 1.4.1 | `0x9641d764fc13c8B624c04430C7356C1C7C8102e2` | At Gully's address `0x32228dDEA8b9A2bd7f2d71A958fF241D79ca5eEC` | | SignMessageLib 1.4.1 | `0xd53cd0aB83D845Ac265BE939c57F53AD838012c9` | At Gully's address `0x309C7b0A0D2f250Be322739753386911E1187C4E` | | CreateCall 1.4.1 | `0x9b35Af71d77eaf8d7e40252370304687390A1A52` | At Gully's address `0x8BbCaE989A0Bdf15c8E783357a0E5848e36233d0` | | SimulateTxAccessor 1.4.1 | `0x3d4BA2E0884aa488718476ca2FB8Efc291A46199` | At Gully's address `0xB59bD9861a97F9c309B7b73338503507580625D2` | | SafeWebAuthnSharedSigner 0.2.1 | `0x94a4F6affBd8975951142c3999aEAB7ecee555c2` | At Gully's address `0xB3a6Aa3eDDD715dbD84aD465Ab0f98919eBB6d5C` | | SafeWebAuthnSignerFactory 0.2.1 | `0x1d31F259eE307358a26dFb23EB365939E8641195` | At Gully's address `0xfF25690FC38De1572c2C8075966Bb813f60a095F` | #### NFT marketplaces | Contract | Canonical address | Status | |---|---|---| | Seaport 1.6 | `0x0000000000000068F116a894984e2DB1123eB395` | Live | | Seaport ConduitController | `0x00000000F9490004C11Cef243f5400493c00Ad63` | Live | The canonical Safe 1.4.1 addresses stay empty until the Safe team deploys their singleton factory on Gully Chain (it needs Safe's own key). The same audited creation code is live at Gully's addresses, shown in the Status column; pass them to Safe tooling explicitly (see [Gully Safe](https://docs.gullychain.xyz/safe/)). ## Gully contracts Gully Chain's own deployments: tokens, Uniswap v3, the oracle, names, the testnet launchpad, accounts, the token bridge and the Hyperlane routes. Everything else (Quests, Pay, Sentry, RWA rails, Offerwall) is on [Contract addresses](https://docs.gullychain.xyz/contracts/). #### Tokens | Contract | Address | |---|---| | WETH9 (canonical WETH9 code, Gully address) | `0x26aCCCb2e98ca9e067E58668Aa3B101beF432754` | | USDC.e (Bridged USDC, Circle standard, 6 dp) | `0x65Ba03c6FA90Ed549f465D4c8f2e784D6eEB7E76` | | USDC.e implementation (FiatTokenV2_2) | `0xdCda1B0EfD3b83aC8fA766bCB262a6e8c677c8BE` | | USDC.e MasterMinter | `0x0197877efae59Ac6723084fF1c8D0b73212F089c` | | L2 USDC gateway (sole USDC.e minter) | `0xd9d07510cEEfeeaF538bDDbe4ee1B76E9F1A71B3` | | glUSD (Gully USD, 6 dp; retired, redeem-only) | `0xDBE84bE6496Fb3d07F601548555ec7Acc4CeBa8F` | | glUSD PSM (redeem glUSD for USDC.e 1:1; deposits paused) | `0xe1Ae51036ede1b244c532A81FaC196f19fa5E28e` | #### Uniswap v3 | Contract | Address | |---|---| | UniswapV3Factory | `0x1787a3bA8C8D7a2439cfA2EFaFc683ECAC623950` | | SwapRouter02 | `0xf49b65b9912fd017fDb91D21eE9bC9992F8cF05c` | | NonfungiblePositionManager | `0x90aDCE86fce80E9fACD436efBb4C8A25D3d38f75` | | QuoterV2 | `0x808f5DE34f215712F780DB0eA91F7530f883A04e` | | TickLens | `0x8746BFA894889A2aB87FF06F1e69B495F14ED38A` | | UniswapInterfaceMulticall | `0x2CD6FA084e314C4Ce0D57d77231515D1f022b61d` | | V3Migrator | `0x50AE8Ff4EB11dAD103fCE65a9F2e48dc1746cf64` | | UniswapV3Staker | `0x1e4e1E496A3b35A1414C5F615eb4920C93a16143` | | NonfungibleTokenPositionDescriptor (proxy) | `0x5ffaCCa457988b75E6B62E79C799Eea85Eb10Af3` | | GullyFeeController (factory owner) | `0x47214e56806Daa1cdA5981E2F1AFE8FDfF19D93b` | | GullySwapRouter (0.25% interface fee) | `0x1283a251E34296675CC5130A2B02871384c0436a` | #### Oracle (testnet only) | Contract | Address | |---|---| | GullyPriceFeed (RedStone pull) | `0x4c64c79ee59a83842a22c14712D66bfef48eb301` | | ETH / USD adapter (AggregatorV3) | `0x732b8a31E19827B6c81db7a433fd120e302862c8` | | BTC / USD adapter (AggregatorV3) | `0xE7Df3ec99314C0716510DAcd5B61a089Cf95130c` | | USDC / USD adapter (AggregatorV3) | `0x7cEbF1d241165302b9a0bc2CFD24020ACB7AE44e` | #### .gully names | Contract | Address | |---|---| | ENS registry | `0xe0bE69254ce3916A38b2d266f6A7325e62e96576` | | .gully registrar | `0x3eb64A442EB656C66376A0458162a0b00093492B` | | Public resolver | `0x9E8328918d40e45FBD40D422c854c554d6b45D37` | | Reverse registrar | `0xF9D030660E04bdBBC3F0818f7a1F4523bD5bA12F` | #### Launchpad | Contract | Address | |---|---| | GullyLaunchpad v2.1 (testnet launchpad; Gully Core replaces it) | `0xCe2c3Ac523EfF3Bec8D3894f7e5C5F519638326b` | | GullyLPLocker v2 | `0x272a78b26B289c50632dCB29270aa2a07dAa5709` | | GullyLaunchpad v2.0 (existing tokens) | `0x3378b659f6ddA7F13D87599B383b3995f82D0974` | | GullyLPLocker v1 | `0xBAb80bf7CA383461e573Dc503c70083c0415d58B` | #### Smart accounts | Contract | Address | |---|---| | WebAuthnValidator (passkey root key) | `0x7ab16Ff354AcB328452F1D445b3Ddee9a91e9e69` | | WebAuthnSigner (extra devices) | `0x65DEeC8fEe717dc044D0CFD63cCf55F02cCaC2b3` | | ECDSASigner (session keys) | `0x6A6F069E2a08c2468e7724Ab3250CdBFBA14D4FF` | | FactoryStaker (meta factory) | `0x3fe1D99661BBD711a434045df5262e594Dd6cA9a` | | SudoPolicy | `0x67b436caD8a6D025DF6C82C5BB43fbF11fC5B9B7` | | CallPolicy | `0x85770b902D1e503D5f5141d9eaC16d0d08eEaDd2` | | RateLimitPolicy | `0xf63d4139B25c836334edD76641356c6b74C86873` | | TimestampPolicy | `0xB9f8f524bE6EcD8C945b1b87f9ae5C192FdCE20F` | #### Gully Safe | Contract | Address | |---|---| | SafeToL2Setup 1.4.1 | `0x5DC954024c42433BF567eb072992A83b4d480A0a` | | SafeToL2Migration 1.4.1 | `0xf91b2B39B185395502Da5DD797bB659A169ba2E4` | | TokenCallbackHandler 1.4.1 | `0x63117fd9761850f4aC685457E484A01D752D5cC4` | #### Token bridge (Gully Chain side) | Contract | Address | |---|---| | Gateway router | `0x32C680cA4c27A3566fE5Dfd4643fE420eE1039B7` | | Standard ERC-20 gateway | `0x5CbA5BFD52beA26Fb65c26Fa452f290cB8610fE2` | | Custom gateway | `0x27530E706c67F210753081508302d69ba1693A41` | | WETH gateway | `0xB8BAAd59F553707534F546983912486562FA0Eb3` | | Bridged WETH (Arbitrum Sepolia WETH) | `0x3292dE74305DF64dbe082c6834fa841353eB2415` | | Upgrade executor | `0x2d5E1C784b64715ED5F4191FEAe0F402A401Cd7D` | #### Apps | Contract | Address | |---|---| | GullyArcade | `0xe573789b235314661DEdDA08a18Ca261c069c872` | | GullyReferrals | `0x42B46EA814024683B346cCEAc2124A054F4544b7` | | GullyRewardsDistributor | `0x1F299b4EDecf58749f6f51Fab663a2509C6D11C6` | #### Hyperlane | Contract | Address | |---|---| | Mailbox | `0x5b875dac092FcA7cE0DfEe8B7C1dbBD2c2a0cfDe` | | MerkleTreeHook | `0xB2cD98D3Fb515506e3A2c91222131Ec9cC8b4Dd3` | | ValidatorAnnounce | `0x4E311b13cdE4ce8B4cA5830006B35E2CD220b2E0` | | InterchainAccountRouter | `0xAE10F17aFf0ed91630202939b5ff65F4C6404909` | | Native ETH warp router (fast lane, HypNative) | `0xB1943191df824138bd0784C60077c6610F380810` | | Native ETH warp router (Arbitrum Sepolia side) | `0x9E40F1702977A0a48Fa275522Ba6877E209DE631` | ### On Arbitrum Sepolia #### Rollup core (Arbitrum Sepolia) | Contract | Address | |---|---| | Rollup | `0x85D80C06Fa5334E8Cd1C51F3F39D477E5dc35E0D` | | Inbox (deposits, retryables) | `0x7B8499f1C058c9bdE2Bc9BdFEBE40364232C52B5` | | Sequencer inbox | `0x483f77f692635d4D8a8147D0f732A016614Ce685` | | Bridge | `0x2073106fd3fc844Bbde31f5Bf0BB91cf1e2d6C8A` | | Outbox (withdrawals) | `0x976C651fe5E63E45C8C28449507F51548922f68c` | | Challenge manager | `0x625aAFe602c82FA2E409BB3c6c073E6aD2cf999D` | #### Token bridge (Arbitrum Sepolia side) | Contract | Address | |---|---| | Gateway router | `0xfbd7503009AB4ee5A1f980a2fCDEE4C7BEB6b2B9` | | Standard ERC-20 gateway | `0x8E35E523bFd709d577A77F749c831cB045bCabd0` | | Custom gateway | `0xA90752f7057dc1BFe2677f1791c5084535A4E42a` | | WETH gateway | `0xEB602d8Fc5F5d87DA629201905bE51885165EC4f` | | L1 USDC gateway (escrows USDC behind USDC.e) | `0xF904064BE100489a200EB754E591362C7Ced2D5b` | ## Quirks > [!WARNING] > **`block.number` is not Gully Chain's block number.** Inside a contract it returns the L1 (Ethereum Sepolia) block number, as on every Arbitrum chain. Use `block.timestamp` for time, or `ArbSys(0x64).arbBlockNumber()` for the L3 block. Details: [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number). - **Blocks only when there are transactions.** No fixed block time; a quiet chain can go minutes without a block. Do not use new blocks as a clock or a health check. - **Gas includes the parent-chain data cost.** Always estimate (`eth_estimateGas`; Foundry, Hardhat, viem and ethers do it by default). Never hard-code gas limits copied from Ethereum. - **Cancun EVM** (`PUSH0`, `MCOPY`, transient storage). Set `evm_version = "cancun"` or older. Max contract size 24,576 bytes, init code 49,152 bytes. - **Stylus:** contracts in Rust, C and C++ run next to Solidity. See [Stylus](https://docs.gullychain.xyz/stylus/). - **Keyless pre-EIP-155 transactions are accepted**, so published deterministic deployers (Arachnid, ERC-1820, Multicall3, CreateX) can be replayed. Your own transactions should still be EIP-155 signed (every tool does this by default). - **Arbitrum precompiles** are available: `ArbSys` at `0x64`, `ArbGasInfo` at `0x6c`, `ArbWasm` at `0x71`. - **No `debug_*` / `trace_*`** on the public RPCs. ## Rate limits | Endpoint | Limit per IP | |---|---| | `rpc.gullychain.xyz`, `testnet-rpc.gullychain.xyz` | 100 requests/s | | `rpc2.gullychain.xyz` | 50 requests/s, burst 100 | | Gully RPC keyless (`rpc.gullyrpc.xyz/gullychain/...`) | 25 requests/s | | Gully RPC with your key | Your plan's limit | - Send **single JSON-RPC requests**. Batches work but count per call and are the first thing to hit a limit; keep them small. - Over the limit you get HTTP 429 or a JSON-RPC rate-limit error: back off and retry, or move to the next endpoint. - Never send the same signed transaction to two endpoints in parallel. Retrying it on the next endpoint after a failure is fine. ## WebSocket There is no public WebSocket RPC yet: `eth_subscribe` is not available on the public endpoints. viem's `watchBlocks`, `watchContractEvent` and ethers' `provider.on(...)` fall back to HTTPS polling, which works on every endpoint above. A `wss://rpc.gullychain.xyz/ws` endpoint is prepared and will be listed here, in [/chain.json](https://docs.gullychain.xyz/chain.json) and on the [status page](https://status.gullylabs.xyz/) when it is live. ## Get help - **Email** [team@gullylabs.xyz](mailto:team@gullylabs.xyz): bugs, higher RPC limits, a bigger faucet allowance, a contract you need deployed. - **Discord** [GullyChain](https://discord.com/invite/tY2ErsNNBp) and **Telegram** [t.me/GullyChain](https://t.me/GullyChain) (news) and [t.me/GullyChainDeploys](https://t.me/GullyChainDeploys) (new deploys). - Is something down? Check [status.gullylabs.xyz](https://status.gullylabs.xyz/) first. What to include in a report: [Support](https://docs.gullychain.xyz/support/). # Network reference Source: https://docs.gullychain.xyz/network/ > GullyChain Testnet settings: chain ID 485590, public RPCs with fallbacks, explorer, bridge, faucet, Arbitrum Sepolia as parent chain, gas, block production and rate limits. ## Testnet settings | Setting | Value | |---|---| | Network name | GullyChain Testnet | | Chain ID | `485590` (hex `0x768d6`) | | RPC (HTTPS) | `https://rpc.gullychain.xyz`, with fallbacks: see [Public RPCs](#public-rpcs) | | Explorer | [testnet-explorer.gullychain.xyz](https://testnet-explorer.gullychain.xyz/) | | Bridge | [bridge.gullychain.xyz](https://bridge.gullychain.xyz/) | | Faucet | [faucet.gullychain.xyz](https://faucet.gullychain.xyz/) (0.0005 ETH per address per day, sign in with [Gully ID](https://docs.gullychain.xyz/gully-id/)) | | Token list | [gullychain.xyz/tokenlist.json](https://gullychain.xyz/tokenlist.json), see [Token list](https://docs.gullychain.xyz/token-list/) | | Contract verification | [verify.gullychain.xyz](https://verify.gullychain.xyz/) (Sourcify), guide: [Verify your contract](https://docs.gullychain.xyz/verify/) | | Indexer API | [indexer.gullychain.xyz](https://indexer.gullychain.xyz/), see [RPC and indexer API](https://docs.gullychain.xyz/rpc-api/) | | Live stats | [gullychain.xyz/testnet](https://gullychain.xyz/testnet/) | | Gas token | ETH, 18 decimals | | Parent chain | Arbitrum Sepolia, chain ID `421614` | | Settlement path | GullyChain, then Arbitrum Sepolia, then Sepolia | | Stack | Arbitrum Orbit, Nitro v3.12, ArbOS 51 at genesis | | Data availability | Rollup mode: transaction data is posted to Arbitrum Sepolia (not AnyTrust) | | Sequencer | Single sequencer, first come, first served ordering | | Max contract size | 24,576 bytes (init code 49,152 bytes), the same as Ethereum | A mainnet that settles to Arbitrum is planned. It is not live, and it will have its own chain ID. ## Public RPCs Every endpoint below serves the same chain (`485590`) with the standard Ethereum JSON-RPC (`eth_*`, `net_*`, `web3_*`) over HTTPS, CORS on, no key. Use them **in this order, with a fallback transport**: if one is down, filtered by your ISP or rate limited, your client moves on to the next. | # | Endpoint | Note | Limit per IP | |---|---|---|---| | 1 | `https://rpc.gullychain.xyz` | Canonical public RPC. eRPC in front of the nodes, with a direct-node fallback. Put this first (wallets use the first URL). | 100 req/s | | 2 | `https://rpc.gullyrpc.xyz/gullychain/evm/485590` | Gully RPC gateway, keyless project, on a different server. For more, use your own [Gully RPC](https://app.gullyrpc.xyz) key. | 25 req/s | | 3 | `https://rpc2.gullychain.xyz` | Direct to the nodes, bypasses eRPC, so it keeps answering when eRPC has trouble. | 50 req/s | | 4 | `https://testnet-rpc.gullychain.xyz` | Legacy endpoint, kept working. Some ISPs filter hostnames that start with `testnet-`. | 100 req/s | | - | `/rpc` on any `*.gullychain.xyz` site | Same-origin path for our own web apps (app., bridge., explorer., docs., dev., gullychain.xyz). Browser apps on those hosts try it first. | 100 req/s | - **Rate limits apply.** The endpoints are shared, so bursts get HTTP 429 or a JSON-RPC rate-limit error. Cache what you can, avoid tight polling loops, and back off. For a project that needs more, use a [Gully RPC](https://app.gullyrpc.xyz) key or email [team@gullylabs.xyz](mailto:team@gullylabs.xyz). - **No debug or trace methods.** `debug_*` and `trace_*` are not exposed on the public endpoints. - **Batch requests** (a JSON array of calls) work. Keep batches small. - **No public WebSocket yet.** `eth_subscribe` is not available; viem and ethers watchers poll over HTTPS. `wss://rpc.gullychain.xyz/ws` is prepared: see [Deploy on Gully Chain](https://docs.gullychain.xyz/deploy/#websocket). - **Never send the same signed transaction to two endpoints in parallel.** Retrying it on the next endpoint after a failure is fine. ### viem ```ts import { createPublicClient, defineChain, fallback, http } from "viem"; export const gullyTestnet = defineChain({ id: 485590, name: "GullyChain Testnet", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpcUrls: { default: { http: [ "https://rpc.gullychain.xyz", "https://rpc.gullyrpc.xyz/gullychain/evm/485590", "https://rpc2.gullychain.xyz", "https://testnet-rpc.gullychain.xyz", ], }, }, blockExplorers: { default: { name: "Gully Explorer", url: "https://testnet-explorer.gullychain.xyz" } }, }); // rank: false keeps the order (first healthy endpoint wins) and saves the ranking pings const transport = fallback( gullyTestnet.rpcUrls.default.http.map((url) => http(url, { timeout: 8_000, retryCount: 0 })), { rank: false, retryCount: 1 }, ); export const client = createPublicClient({ chain: gullyTestnet, transport }); ``` With wagmi, use the same transport: `transports: { [gullyTestnet.id]: transport }`. ### ethers v6 ```ts import { FallbackProvider, JsonRpcProvider, Network } from "ethers"; const network = Network.from(485590); const urls = [ "https://rpc.gullychain.xyz", "https://rpc.gullyrpc.xyz/gullychain/evm/485590", "https://rpc2.gullychain.xyz", "https://testnet-rpc.gullychain.xyz", ]; export const provider = new FallbackProvider( urls.map((url, i) => ({ provider: new JsonRpcProvider(url, network, { staticNetwork: network }), priority: i + 1, weight: 1, stallTimeout: 2000, })), network, { quorum: 1 }, ); ``` ## Blocks are made only when there are transactions Nitro chains produce a block only when there is a transaction to include. On a quiet testnet the chain can go minutes without a new block. That is normal and not downtime, and it means: - Do not use "a new block arrived" as a clock or a health check. Check `eth_chainId` or `eth_blockNumber` instead. - `waitForTransactionReceipt` and similar helpers still return quickly, because your own transaction triggers a block. - Block timestamps can jump: there is no fixed block time. ## block.number is not the L3 block number > [!WARNING] > **Two clocks.** As on every Arbitrum chain, `block.number` inside a contract does **not** return Gully Chain's own block number. It returns the **L1** block number that Arbitrum passes down: Ethereum Sepolia's height on the testnet (measured 2026-10-26: `block.number` = 12,001,018 while Ethereum Sepolia was at 12,001,021, Arbitrum Sepolia at 323 M and Gully Chain at about 660), and Ethereum's on mainnet. It advances on that chain's schedule (about 12 s) and stays the same across several Gully Chain blocks. Code that measures time in blocks (vesting, auctions, cooldowns, launch windows, rate limits) will behave differently than on Ethereum, and an indexer that compares a contract's stored block number with `eth_blockNumber` will be comparing two different clocks. - Use `block.timestamp` for time-based logic where you can. - To read GullyChain's own block number from a contract, call `arbBlockNumber()` on the ArbSys precompile at `0x0000000000000000000000000000000000000064`. ```solidity interface ArbSys { function arbBlockNumber() external view returns (uint256); } uint256 l3Block = ArbSys(address(0x64)).arbBlockNumber(); ``` The JSON-RPC `eth_blockNumber`, transaction receipts and the explorer show Gully Chain's own block numbers. Indexers that read a contract's `block.number` (for example from an event field) should configure L1 (Ethereum Sepolia on the testnet) as that contract's block clock. ## Stablecoins and app-layer contracts USDC.e (glUSD retired, redeem-only), Kernel passkey accounts with a public bundler and paymaster, Gully Safe, Uniswap v3, the launchpad, .gully names, Gully Quests, the Arcade, referrals, the native ETH fast lane, a testnet price feed and ERC-3643 RWA rails are all live on the testnet. Addresses: [Contract addresses](https://docs.gullychain.xyz/contracts/). Guides: [Stablecoins](https://docs.gullychain.xyz/stablecoins/), [Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/). ## Gas and fees Gas is paid in ETH. GullyChain uses Arbitrum's fee model: a transaction pays for execution on GullyChain plus its share of the cost of posting data to the parent chain. Because the data cost is folded into gas, the gas used by a transaction is higher than on Ethereum for the same call. - Always estimate with `eth_estimateGas` (Foundry, Hardhat, viem and ethers do this by default). Do not hard-code gas limits copied from Ethereum. - The gas price normally sits at the chain's minimum base fee. Read it with `eth_gasPrice`; the [testnet page](https://gullychain.xyz/testnet/) shows it live. - EIP-1559 transactions (type 2) and legacy transactions both work. Sign with the chain ID (EIP-155); unprotected transactions may be rejected. ## EVM compatibility GullyChain runs the Arbitrum Nitro EVM, which supports the Cancun opcode set (including `MCOPY` and transient storage). Solidity, Vyper and the usual tools work as-is. The Arbitrum precompiles (`ArbSys` at `0x64`, `ArbGasInfo` at `0x6c` and others) are available. Contracts written in Rust run on [Stylus](https://docs.gullychain.xyz/stylus/). ## Parent-chain contracts The rollup, inbox, outbox and token bridge contracts on Arbitrum Sepolia are listed on [Contract addresses](https://docs.gullychain.xyz/contracts/#on-arbitrum-sepolia). # Contract addresses Source: https://docs.gullychain.xyz/contracts/ > Every contract on GullyChain Testnet and Arbitrum Sepolia: stablecoins, passkey accounts, the Gully Core launchpad and DEX, Gully Swap, .gully names, Arcade and the bridge. Standard contracts sit at the **same addresses as on Ethereum mainnet** wherever they were deployed with a deterministic deployer, so existing tooling finds them. Every address links to the [explorer](https://testnet-explorer.gullychain.xyz/) and has a copy button. Everything on this page is on **GullyChain Testnet (chain ID 485590)** unless it says Arbitrum Sepolia. The standard contracts with their live status, and the same list as JSON, are on [Deploy on Gully Chain](https://docs.gullychain.xyz/deploy/#standard-contracts) and [/addresses.json](https://docs.gullychain.xyz/addresses.json). Nearly every GullyChain contract on this page is **source-verified** on [verify.gullychain.xyz](https://verify.gullychain.xyz/) (self-hosted Sourcify), so the explorer shows its source, ABI and Read/Write forms. The [registry](#registry) at the end lists the few that are not, and why. To verify your own, see [Verify your contract](https://docs.gullychain.xyz/verify/). **For AI agents, wallets and tools:** the [registry](#registry) is also published as [/contracts.json](https://docs.gullychain.xyz/contracts.json) (JSON: name, category, address, chain, owner/admin, source repo + path + commit, licence, audit status, Sourcify match, ABI link, docs link, description) and [/llms-contracts.txt](https://docs.gullychain.xyz/llms-contracts.txt) (plain text in the llms.txt style). The docs index for language models is [/llms.txt](https://docs.gullychain.xyz/llms.txt). > [!WARNING] > **Two clocks: `block.number` is not GullyChain's block number.** As on every Arbitrum chain, `block.number` inside a contract returns the **parent chain's** block number, not the L3's. Contracts that count blocks (vesting, auctions, cooldowns, launch windows) must use `block.timestamp`, or read the L3 block number with `ArbSys(0x64).arbBlockNumber()`. See [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number). > [!NOTE] > Everything here is **testnet only**: unaudited Gully contracts, test tokens with no value, and admin roles held by a Gully Labs testnet key. The testnet may be reset. ## On GullyChain ### Stablecoins | Contract | Address | |---|---| | USDC.e, "Bridged USDC (Gully Labs)", 6 decimals | `0x65Ba03c6FA90Ed549f465D4c8f2e784D6eEB7E76` | | USDC.e implementation (Circle FiatTokenV2_2) | `0xdCda1B0EfD3b83aC8fA766bCB262a6e8c677c8BE` | | USDC.e MasterMinter | `0x0197877efae59Ac6723084fF1c8D0b73212F089c` | | L2 USDC gateway (sole minter of USDC.e) | `0xd9d07510cEEfeeaF538bDDbe4ee1B76E9F1A71B3` | | USDC ProxyAdmin (GullyChain) | `0x3eb9a1ac3Ae8A6769aae85C687B633542BA702fF` | | glUSD, "Gully USD", 6 decimals (**retired** 2026-10-28: redeem-only, use USDC.e) | `0xDBE84bE6496Fb3d07F601548555ec7Acc4CeBa8F` | | glUSD PSM (redeem-only: glUSD to USDC.e 1:1; deposits paused) | `0xe1Ae51036ede1b244c532A81FaC196f19fa5E28e` | How these work, and how to bridge USDC in: [Stablecoins](https://docs.gullychain.xyz/stablecoins/). ### Tokens and approvals | Contract | Address | |---|---| | WETH9 | `0x26aCCCb2e98ca9e067E58668Aa3B101beF432754` | | Permit2 | `0x000000000022D473030F116dDEE9F6B43aC78BA3` | WETH9 is a clone of the canonical WETH9 contract, deployed fresh on GullyChain. Gully Core, all Uniswap v3 pools and the legacy launchpads use it. It is not the same token as the bridged WETH further down. ### Smart accounts (Kernel v3.3 and passkeys) | Contract | Address | |---|---| | Kernel v3.3 (account implementation) | `0xd6CEDDe84be40893d153Be9d467CD6aD37875b28` | | KernelFactory v3.3 | `0x2577507b78c2008Ff367261CB6285d44ba5eF2E9` | | FactoryStaker (meta factory, staked in the EntryPoint) | `0x3fe1D99661BBD711a434045df5262e594Dd6cA9a` | | WebAuthnValidator 0.0.3 (passkey as the root key) | `0x7ab16Ff354AcB328452F1D445b3Ddee9a91e9e69` | | WebAuthnSigner 0.0.4 (extra devices, recovery passkey) | `0x65DEeC8fEe717dc044D0CFD63cCf55F02cCaC2b3` | | ECDSASigner (session keys, linked wallets) | `0x6A6F069E2a08c2468e7724Ab3250CdBFBA14D4FF` | | SudoPolicy | `0x67b436caD8a6D025DF6C82C5BB43fbF11fC5B9B7` | | CallPolicy 0.0.5 | `0x85770b902D1e503D5f5141d9eaC16d0d08eEaDd2` | | RateLimitPolicy | `0xf63d4139B25c836334edD76641356c6b74C86873` | | TimestampPolicy | `0xB9f8f524bE6EcD8C945b1b87f9ae5C192FdCE20F` | The Kernel contracts are ZeroDev's open-source (MIT) code, deployed through the CREATE2 factory from the same creation code as on other chains. See [Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/). ### ERC-4337 core | Contract | Address | |---|---| | EntryPoint v0.6 | `0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789` | | EntryPoint v0.7 | `0x0000000071727De22E5E9d8BAf0edAc6f37da032` | | EntryPoint v0.8 | `0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108` | | SimpleAccountFactory v0.6 | `0x9406Cc6185a346906296840746125a0E44976454` | | SimpleAccountFactory v0.7 | `0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985` | | SimpleAccountFactory v0.8 | `0x13E9ed32155810FDbd067D4522C492D6f68E5944` | | LightAccountFactory v2.0.0 (Alchemy) | `0x0000000000400CdFef5E2714E63d8040b700BC24` | | Safe4337Module 0.3.0 | `0x75cf11467937ce3F2f357CE24ffc3DBF8fD5c226` | | SafeModuleSetup 0.3.0 | `0x2dd68b007B46fBe91B9A7c3EDa5A7a1063cB5b47` | | P256 verifier (Daimo) | `0xc2b78104907F722DABAc4C69f826a522B2754De4` | The EntryPoints and account factories are the eth-infinitism and Alchemy contracts at their canonical addresses, deployed from the same creation code and salts as on Ethereum mainnet. The public bundler and paymaster endpoints are on [Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/#endpoints). ### Deployers and registries | Contract | Address | |---|---| | Arachnid deterministic deployment proxy (CREATE2) | `0x4e59b44847b379578588920cA78FbF26c0B4956C` | | CreateX | `0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed` | | ImmutableCreate2Factory (0age) | `0x0000000000FFe8B47B3e2130213B802212439497` | | ERC-2470 SingletonFactory | `0xce0042B868300000d44A59004Da54A005ffdcf9f` | | Multicall3 | `0xcA11bde05977b3631167028862bE2a173976CA11` | | ERC-1820 registry | `0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24` | | ERC-6551 registry (token-bound accounts) | `0x000000006551c19487814612e58FE06813775758` | | DelegateRegistry v2 (delegate.xyz) | `0x00000000000000447e69651d841bD8D104Bed493` | All of these sit at their canonical addresses. The Safe singleton factory (`0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7`) is not deployed yet: Safe signs it per chain, and the request is open. Until then, use the [Gully Safe](#gully-safe-safe-141-and-passkeys) 1.4.1 deployment. ### NFT marketplace (Seaport) | Contract | Address | |---|---| | Seaport 1.6 | `0x0000000000000068F116a894984e2DB1123eB395` | | ConduitController | `0x00000000F9490004C11Cef243f5400493c00Ad63` | OpenSea's Seaport 1.6 and ConduitController at their canonical addresses, deployed with Seaport's own deployment calldata. ### Attestations (EAS) | Contract | Address | |---|---| | EAS 1.3.0 | `0x412A5d2F2A1f2F8e8e7E9023371d9ACe11A23aAa` | | SchemaRegistry 1.3.0 | `0x0fdec4B85Af441415763e06e82fB783c371FC8B1` | Ethereum Attestation Service has no canonical address, so these addresses are specific to GullyChain. The bytecode is the official EAS 1.3.0 release, the same code EAS deployed on Arbitrum Sepolia. ### Gully Core (launchpad and DEX) **Gully Core** is Gully Chain's launchpad and DEX core, live on testnet: every new launch goes through it. The main entry points are below; all 44 Gully Core contracts, with the fee numbers read from chain, are on [Gully Core](https://docs.gullychain.xyz/gully-core/#contract-addresses) and in the [registry](#registry) (product `Gully Core`). | Contract | Address | What it does | |---|---|---| | LaunchpadKitV2 | `0xd46543Fcb42878868eBA0C62ea1F7801a357B12D` | one-transaction launches; launch fee 0.0001 ETH | | GullyCoreLaunchAndBuy | `0x3A447F552146Aa05262fd98603C9B1394267ce5B` | launch and the creator's first buy in one transaction | | GullyCoreLPLocker (CL) | `0x0Ca509787bf2C6a241761586d02885b9719aca5f` | locks launch liquidity forever, splits its fees | | GullyCoreBinLPLocker | `0x444719a68d039639655EDC943F1826cC2835c5a5` | the same for Bin legs | | LaunchGuardHook (CL) | `0xAc79571DB68bF84012Ea986d25Bd09c6de6d4935` | anti-snipe opening fee and creator tax | | UniversalRouter | `0xb6ab6f0D23c769329DB4b3CFB947fDe3a9e797A5` | swaps on the Gully Core DEX | | Vault | `0x90c882D9C307c2bF7E961bC279b0929f92997dD4` | holds every Gully Core pool's tokens | ### Legacy launchpads > [!WARNING] > **Deprecated: new launches use [Gully Core](https://docs.gullychain.xyz/gully-core/).** These launchpads stay on chain so existing tokens keep > trading and graduating and their lockers keep paying fees. In the registry they have status `deprecated` and product > `Gully launchpad (legacy)`. | Contract | Address | Notes | |---|---|---| | GullyLaunchpadV3 | `0x2d723cd02061e3F2E0e0B2dc20C0549c66C462de` | legacy (v3: curve, fair launch, vesting); existing tokens keep trading | | GullyFairLaunch | `0x4AFb193A303Ba9840fB1e35f45fB5B000036B275` | legacy, part of v3 | | GullyLPLocker (v3) | `0x864B659F90b69d6B28A5C70C2d0e5502Ce71485C` | legacy; keeps collecting fees for its locks | | GullyLaunchpad v2.1 | `0xCe2c3Ac523EfF3Bec8D3894f7e5C5F519638326b` | legacy; existing tokens keep trading and graduating | | GullyLPLocker v2 (for v2.1) | `0x272a78b26B289c50632dCB29270aa2a07dAa5709` | locks graduated LP forever; pool fees split **50% creator, 50% platform** | | GullyLaunchpad v2.0 | `0x3378b659f6ddA7F13D87599B383b3995f82D0974` | legacy | | GullyLPLocker v1 (for v2.0) | `0xBAb80bf7CA383461e573Dc503c70083c0415d58B` | pool fees go to the platform | The legacy launchpads are bonding curves (1% trade fee) that graduate into a full-range Uniswap v3 1% pool. ### Uniswap v3 and Gully Swap | Contract | Address | |---|---| | UniswapV3Factory | `0x1787a3bA8C8D7a2439cfA2EFaFc683ECAC623950` | | SwapRouter02 | `0xf49b65b9912fd017fDb91D21eE9bC9992F8cF05c` | | NonfungiblePositionManager | `0x90aDCE86fce80E9fACD436efBb4C8A25D3d38f75` | | QuoterV2 | `0x808f5DE34f215712F780DB0eA91F7530f883A04e` | | TickLens | `0x8746BFA894889A2aB87FF06F1e69B495F14ED38A` | | UniswapInterfaceMulticall | `0x2CD6FA084e314C4Ce0D57d77231515D1f022b61d` | | V3Migrator | `0x50AE8Ff4EB11dAD103fCE65a9F2e48dc1746cf64` | | UniswapV3Staker | `0x1e4e1E496A3b35A1414C5F615eb4920C93a16143` | | NonfungibleTokenPositionDescriptor (proxy) | `0x5ffaCCa457988b75E6B62E79C799Eea85Eb10Af3` | | ProxyAdmin (Uniswap v3) | `0x812892978376f4E8D4404A6eB4449DF20eB8A679` | | GullyFeeController (owns the factory) | `0x47214e56806Daa1cdA5981E2F1AFE8FDfF19D93b` | | GullySwapRouter (0.25% interface fee) | `0x1283a251E34296675CC5130A2B02871384c0436a` | These are the standard Uniswap v3 contracts, deployed with Uniswap's own deploy tool. `UniswapInterfaceMulticall` is Uniswap's helper, not Multicall3. ### .gully names | Contract | Address | |---|---| | ENS registry | `0xe0bE69254ce3916A38b2d266f6A7325e62e96576` | | `.gully` registrar (first come, first served, testnet) | `0x3eb64A442EB656C66376A0458162a0b00093492B` | | Public resolver | `0x9E8328918d40e45FBD40D422c854c554d6b45D37` | | Reverse registrar | `0xF9D030660E04bdBBC3F0818f7a1F4523bD5bA12F` | See [.gully names](https://docs.gullychain.xyz/names/). ### Arcade and referrals | Contract | Address | |---|---| | GullyArcade (seasons, attested scores, prize pots) | `0xe573789b235314661DEdDA08a18Ca261c069c872` | | GullyReferrals (referral registry) | `0x42B46EA814024683B346cCEAc2124A054F4544b7` | | GullyRewardsDistributor (weekly Merkle rewards in WETH) | `0x1F299b4EDecf58749f6f51Fab663a2509C6D11C6` | See [Arcade](https://docs.gullychain.xyz/arcade/) and [Referrals](https://docs.gullychain.xyz/referrals/). ### Price feed (testnet only) | Contract | Address | |---|---| | GullyPriceFeed (RedStone pull: ETH, BTC, USDC) | `0x4c64c79ee59a83842a22c14712D66bfef48eb301` | | ETH / USD adapter (AggregatorV3-style) | `0x732b8a31E19827B6c81db7a433fd120e302862c8` | | BTC / USD adapter | `0xE7Df3ec99314C0716510DAcd5B61a089Cf95130c` | | USDC / USD adapter | `0x7cEbF1d241165302b9a0bc2CFD24020ACB7AE44e` | The feed verifies RedStone's signed price packages (primary production data service, 3 signers, at most 60 seconds old, 8 decimals), which the caller appends to the transaction's calldata. Its consumer code is under RedStone's **BUSL-1.1** licence, which allows non-production use only, so this feed is **for the testnet only**. A production price source will be announced before mainnet. ### Real-world asset rails (ERC-3643) | Contract | Address | |---|---| | TREXFactory | `0x0FF2771EC18fC9dbDb7d3B231a94D13b68b7e4f1` | | TREXGateway (approved issuers deploy here) | `0xA4682fA7Ef1E787a38229ab378CD7cA16f1839D4` | | TREX implementation authority | `0xA1F8855EdcE9069953877AE7ECA0398179eb87af` | | IAFactory (an issuer's own implementation authority) | `0xB558a2F403eE13582440Fb794334B5EFfb63eE34` | | ONCHAINID IdFactory | `0x81fF68AD45723351A577725BC4145524313AC422` | | ONCHAINID Gateway (self-service identities) | `0xd79BCA8D5a3f1046bC0Cb48884B842d17C91b512` | | ONCHAINID implementation authority | `0xc0848a69910b88eF9e2429539f6aC2A1AeB9801D` | | Country module (deny and allow lists) | `0x2Fd0347270F9df26cB242b3825B02229c68fEa5D` | | Max balance module | `0xA810EEE1E8E393fb79F305AA69d1006C419883dC` | | Max holders module | `0xfB9b8dc234f2362e5337f31c420856953eF9B6Cc` | | Gully testnet KYC claim issuer (manual, testnet only) | `0x34291C44d75FeeEd27d875e32159E2d5B268F6e1` | | TEST-TBILL token (test asset, no value) | `0x7644b56E58e06471C2767FD4291fFB995deE06f6` | | TEST-TBILL identity registry | `0xC92560D047A7ee4A455aD197D2481DD773756016` | | TEST-TBILL compliance | `0x6234dfc53BcBBE037894a280E1BF88162b485be0` | | TEST-TBILL mock NAV oracle | `0xB9f178D2DC79350245c11CA3Cd01b1eAF2315b55` | | TEST-TBILL subscription desk (free test units) | `0x227AC9bEF3E57F8B351094ab8110B41F919491F9` | See [Real-world assets](https://docs.gullychain.xyz/rwa/). ### Gully Safe (Safe 1.4.1 and passkeys) | Contract | Address | |---|---| | Safe 1.4.1 (singleton) | `0x639245e8476E03e789a244f279b5843b9633b2E7` | | SafeL2 1.4.1 (singleton, events for indexers) | `0x76667330c237Fb40f28d74563cdAAae4b06C23Ec` | | SafeProxyFactory 1.4.1 | `0xd9d2Ba03a7754250FDD71333F444636471CACBC4` | | CompatibilityFallbackHandler 1.4.1 | `0xcB4a8d3609A7CCa2D9c063a742f75c899BF2f7b5` | | MultiSend 1.4.1 | `0x7B21BBDBdE8D01Df591fdc2dc0bE9956Dde1e16C` | | MultiSendCallOnly 1.4.1 | `0x32228dDEA8b9A2bd7f2d71A958fF241D79ca5eEC` | | SignMessageLib 1.4.1 | `0x309C7b0A0D2f250Be322739753386911E1187C4E` | | CreateCall 1.4.1 | `0x8BbCaE989A0Bdf15c8E783357a0E5848e36233d0` | | SimulateTxAccessor 1.4.1 | `0xB59bD9861a97F9c309B7b73338503507580625D2` | | SafeToL2Setup 1.4.1 | `0x5DC954024c42433BF567eb072992A83b4d480A0a` | | SafeToL2Migration 1.4.1 | `0xf91b2B39B185395502Da5DD797bB659A169ba2E4` | | TokenCallbackHandler 1.4.1 | `0x63117fd9761850f4aC685457E484A01D752D5cC4` | | SafeWebAuthnSharedSigner 0.2.1 (passkey owners) | `0xB3a6Aa3eDDD715dbD84aD465Ab0f98919eBB6d5C` | | SafeWebAuthnSignerFactory 0.2.1 | `0xfF25690FC38De1572c2C8075966Bb813f60a095F` | These are Safe's own audited contracts (safe-smart-account v1.4.1, safe-modules passkey 0.2.1), unmodified creation code and salts, deployed by Gully Labs through the Arachnid CREATE2 factory. The addresses **differ from Safe's canonical ones** because the Safe singleton factory is not on GullyChain; pass them explicitly to Safe tooling (for example `safeSingletonAddress` and `safeProxyFactoryAddress` in permissionless.js). The Safe app at [safe.gullychain.xyz](https://safe.gullychain.xyz/) uses them. The Safe 4337 module, module setup and P256 verifier above are at their canonical addresses. ### Deterministic deployers | Contract | Address | |---|---| | CREATE2 factory (Arachnid / Nick's) | `0x4e59b44847b379578588920cA78FbF26c0B4956C` | | ERC-2470 singleton factory | `0xce0042B868300000d44A59004Da54A005ffdcf9f` | | Zoltu deployer | `0x7A0D94F55792C434d74a40883C6ed8545E406D12` | | ERC-1820 registry | `0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24` | | Multicall3 | `0xcA11bde05977b3631167028862bE2a173976CA11` | | CreateX | `0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed` | Multicall3 (2026-10-25) and CreateX (2026-10-27) sit at their canonical addresses, deployed from their published pre-signed transactions, so viem's `multicall` action, wagmi's `useReadContracts` and CreateX-based deploy scripts (`CREATE2`/`CREATE3` with the usual salts) work unchanged. Foundry uses the Arachnid factory for `CREATE2` deployments (`forge script` with a `salt`), so salted deploys land at the same address as on other chains. ### Apps: Quests, social, copy trading, bridge router, Sentry | Contract | Address | |---|---| | Gully Quests QuestRegistry | `0xE3E57e15A9973281A8de2B3bedd512BE8C3813Bb` | | Gully Quests reward escrow | `0xbAcaB79c8F22cA82eeC6ee2D6200Fb9FBc7EcEfD` | | Gully Quests reputation (XP) | `0x723243B39F5ff4b5414dcD0d0A8Ad62E4c412dAd` | | Gully Quests badges | `0xEAfFB05b1aD22659918A3fcF28EB566464EB8B06` | | Gully Offerwall OfferwallManager (campaign budgets on Gully Quests, publisher shares, refunds; see [Offerwall](https://docs.gullychain.xyz/offerwall/)) | `0xD6a8c4151a7ED9865a540D20BDD42073DC9c74Bf` | | Gully Offerwall AttestedVerifier (the offerwall's own attester; allowed on QuestRegistry) | `0x68bcaA36c3c2fA4cF6c7D51A2Ac21abfFDF93338` | | GullyVerified (social verification) | `0xE521eCfb4F0385f1eb674b26Cb504dCCA128B198` | | GullyCopyFees (copy trading fees) | `0xA9d429eb1b137764B0d4964e437AF50989bdFea3` | | GullyBridgeRouter (integrator fee + Gully fee, never holds funds) | `0x1F1968116a605a0D7486f2Fb132B4F0Ac74D6B29` | | Hyperlane native ETH router (fast lane, live) | `0xB1943191df824138bd0784C60077c6610F380810` | | Gully Bridged ETH, gETH (retired Hyperlane route, redeem only) | `0x7Dd1Aa3d8598A3edB43EB43ddcb5BCE4AbfBb702` | | Gully Sentry Key, tGSK (ERC-721, testnet) | `0xa24bF9f0eA1AE5F5226d8F7e714cEa3537aa30Ac` | | SentrySale (testnet: free tier only, open; see [Run a Sentry](https://docs.gullychain.xyz/sentry/)) | `0x8eef397b2A8cb66e71D5C931a102c8Be29b36595` | | SentryRewards | `0x2911b6A19350b72A158Af338729adDb5FeE29A21` | The Quests verifiers are listed on [Quests](https://docs.gullychain.xyz/quests/). Sentry Keys on testnet are free and have no value; there is no paid sale. ### Gully Pay Gully Pay's payment contracts on GullyChain (gully-labs/gull-pay). The features that use them are rolling out behind flags; the splitter and escrow are checked for solvency on the [status board](https://status.gullylabs.xyz/). | Contract | Address | |---|---| | GullySplitter (payment splits) | `0x34aDBe4bd54d52e35f3c00C8FF0bFd9F5F04E908` | | GullyEscrow (held payments, releases and refunds) | `0x1d9eD6236d0bC6a29Fb85466c98c8D55Dd20aD7a` | | Agent wallet factory | `0xb64E7257a4223d7Ca0D382cd1F363AD363202fF7` | | Agent wallet implementation | `0x245fBbbB585AC104BAF4472757E36366890f4403` | | Treasury vault, gtGLUSD (**retired**: withdraw-only, testnet) | `0x783d3efF1637546db5B62B8e54bCc9884dc5E91f` | | Treasury strategy (testnet simulation) | `0xF74106d3D726c3127d3AeA255f87344439DE8261` | | GullySwapAndPay (pay in any token, settle in the merchant's) | `0xdE76Ed2165c1708526d76738a274F4291F83E020` | ### Token bridge (GullyChain side) | Contract | Address | |---|---| | Gateway router | `0x32C680cA4c27A3566fE5Dfd4643fE420eE1039B7` | | Standard ERC-20 gateway | `0x5CbA5BFD52beA26Fb65c26Fa452f290cB8610fE2` | | Custom gateway | `0x27530E706c67F210753081508302d69ba1693A41` | | WETH gateway | `0xB8BAAd59F553707534F546983912486562FA0Eb3` | | L2 USDC gateway (USDC only) | `0xd9d07510cEEfeeaF538bDDbe4ee1B76E9F1A71B3` | | Bridged WETH | `0x3292dE74305DF64dbe082c6834fa841353eB2415` | | Multicall (token bridge helper) | `0xc0Dee8709648264495af14c65fEA2Ae7a728E01a` | | Upgrade executor | `0x2d5E1C784b64715ED5F4191FEAe0F402A401Cd7D` | Bridged WETH is the GullyChain version of Arbitrum Sepolia's WETH, minted when WETH is deposited through the WETH gateway. The "Multicall" row is the token bridge's own helper contract, not Multicall3. ### Arbitrum precompiles These exist on every Arbitrum chain, including GullyChain: | Precompile | Address | |---|---| | ArbSys (L3 block number via `arbBlockNumber()`, withdrawals, messages to the parent chain) | `0x0000000000000000000000000000000000000064` | | ArbGasInfo (fee parameters) | `0x000000000000000000000000000000000000006C` | | ArbRetryableTx (retryable tickets) | `0x000000000000000000000000000000000000006E` | | ArbWasm (Stylus) | `0x0000000000000000000000000000000000000071` | ## On Arbitrum Sepolia These contracts live on the parent chain. Addresses link to Arbiscan. ### Rollup core | Contract | Address | |---|---| | Rollup | `0x85D80C06Fa5334E8Cd1C51F3F39D477E5dc35E0D` | | Inbox (deposits, retryable tickets) | `0x7B8499f1C058c9bdE2Bc9BdFEBE40364232C52B5` | | Sequencer inbox (batches) | `0x483f77f692635d4D8a8147D0f732A016614Ce685` | | Bridge | `0x2073106fd3fc844Bbde31f5Bf0BB91cf1e2d6C8A` | | Outbox (withdrawals) | `0x976C651fe5E63E45C8C28449507F51548922f68c` | | Rollup event inbox | `0x199CB32548910316fd99130660989c153B5bBF50` | | Challenge manager | `0x625aAFe602c82FA2E409BB3c6c073E6aD2cf999D` | The rollup was created at Arbitrum Sepolia block 322,568,124. ### Token bridge (Arbitrum Sepolia side) | Contract | Address | |---|---| | Gateway router | `0xfbd7503009AB4ee5A1f980a2fCDEE4C7BEB6b2B9` | | Standard ERC-20 gateway | `0x8E35E523bFd709d577A77F749c831cB045bCabd0` | | Custom gateway | `0xA90752f7057dc1BFe2677f1791c5084535A4E42a` | | WETH gateway | `0xEB602d8Fc5F5d87DA629201905bE51885165EC4f` | | L1 USDC gateway (escrows the USDC behind USDC.e) | `0xF904064BE100489a200EB754E591362C7Ced2D5b` | | USDC (Circle, Arbitrum Sepolia) | `0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d` | | WETH (Arbitrum Sepolia) | `0x980B62Da83eFf3D4576C647993b0c1D7faf17c73` | | Multicall (token bridge helper) | `0xce1CAd780c529e66e3aa6D952a1ED9A6447791c1` | ## Not deployed yet These common contracts are **not on GullyChain yet**. Calls to their usual addresses will fail. | Contract | Usual address | Why, and the plan | |---|---|---| | Safe singleton factory | `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` | Deployed per chain by the Safe team; requested in [safe-singleton-factory#1484](https://github.com/safe-fndn/safe-singleton-factory/issues/1484). Until then the Safe contracts run at Gully's own addresses ([Gully Safe](#gully-safe-safe-141-and-passkeys) above), and Safe's canonical 1.4.1 addresses stay empty. | The [Status](https://docs.gullychain.xyz/status/) page tracks what lands next. If you need one of these for testing now, deploy your own copy and use its address. ## Registry Every contract we know of on GullyChain Testnet, plus Gully Chain's own contracts on Arbitrum Sepolia, in one table: the curated tables above, every deploy record in the Gully repos, the verification inventory and the proxy implementations and admins they point to. Each row links to the explorer and to the contract's page on our Sourcify, and has a copy button and an ABI link (Gully's own ABI file where one exists, otherwise the verified ABI from Sourcify). Type in the box to filter by name, category, address, repo, `verified`/`unverified` or `custom-unaudited`. **Audit** is honest: *Upstream, audited* is code deployed unmodified from a project with published audits (Uniswap, Safe, Circle, Hyperlane, OffchainLabs, ERC-4337, Kernel...). *Gully, unaudited* is code Gully Labs wrote: none of it has an independent audit yet. Owners and admins are read on-chain (`owner()` and the EIP-1967 admin slot) and are in the JSON. The data is rebuilt by `node l3/registry/build.mjs` in gully-ops (deploy records + `eth_getCode`/`owner()` reads on `rpc.gullychain.xyz` + Sourcify lookups); `l3/bin/verify-all.sh` submits any unverified contract to our Sourcify. The full contract registry: https://docs.gullychain.xyz/llms-contracts.txt > [!NOTE] > **Not verified, and why.** Hand-assembled deployers (Arachnid CREATE2 proxy, Zoltu deployer) and EIP-1167 / MetaProxy clones carry no Solidity metadata, so there is nothing to verify; each clone's implementation is verified. CallPolicy 0.0.5 (ZeroDev) was deployed from a build whose source is not public. Two early contracts (blocks 17 and 47) match no source or deploy record and are listed as *unidentified*. # Verify your contract Source: https://docs.gullychain.xyz/verify/ > Source-verify GullyChain Testnet contracts on verify.gullychain.xyz (self-hosted Sourcify) with Foundry, Hardhat or the web page, so the Gully Explorer shows the source, ABI and Read/Write tabs. GullyChain runs its own **[Sourcify](https://sourcify.dev/)** server at **[verify.gullychain.xyz](https://verify.gullychain.xyz/)** for chain **485590**. Verify a contract once and the [Gully Explorer](https://testnet-explorer.gullychain.xyz/) shows a **Verified** badge plus a Contract tab with the source files, ABI, compiler settings and **Read / Write contract** forms. Sourcify recompiles your sources with the exact compiler settings from the metadata and compares the result with the bytecode on chain: - **Exact match** (Sourcify "perfect"): bytecode and the metadata hash match, so the sources are byte-for-byte the ones that were compiled. - **Match** ("partial"): the bytecode matches but the metadata differs (comments, file paths, or `bytecode_hash = "none"`). Every Gully contract and every standard contract on the chain (Uniswap v3, Safe 1.4.1, Kernel, EntryPoint, Permit2, Multicall3, CreateX, WETH9, Hyperlane, the Arbitrum token bridge) is already verified there. | | | |---|---| | Verifier URL | `https://verify.gullychain.xyz/` | | API | Sourcify API v2: `https://verify.gullychain.xyz/v2/` | | Chain ID | `485590` | | API key | none needed | ## Foundry Use `forge verify-contract` with the Sourcify verifier. You don't need an API key or constructor arguments: Sourcify reads them from the creation transaction. ```sh forge verify-contract
src/Counter.sol:Counter \ --chain-id 485590 \ --verifier sourcify \ --verifier-url https://verify.gullychain.xyz/ \ --rpc-url https://rpc.gullychain.xyz \ --watch ``` To verify while deploying, add the same flags to `forge create` or `forge script`: ```sh forge script script/Deploy.s.sol --rpc-url https://rpc.gullychain.xyz --broadcast \ --verify --verifier sourcify --verifier-url https://verify.gullychain.xyz/ ``` Build with the same `foundry.toml` you deployed with (solc version, optimizer runs, `evm_version`, `via_ir`), or the bytecode won't match. > [!NOTE] > On Windows, forge can send a broken file path. If you get `cannot resolve file` or `contract_not_found_in_compiler_output`, run the command from WSL, or upload the metadata on the web page (below). ## Hardhat Hardhat's verify plugin (`@nomicfoundation/hardhat-verify`) supports Sourcify. The server only speaks the **Sourcify API v2**, so use a plugin version that calls `/v2/verify` (the Hardhat 3 plugin); older ones call the removed v1 API and fail with a 404. Point it at the GullyChain server in `hardhat.config.ts`: ```ts import "@nomicfoundation/hardhat-verify"; export default { solidity: { version: "0.8.28", settings: { optimizer: { enabled: true, runs: 200 }, evmVersion: "cancun" } }, networks: { gullychain: { url: "https://rpc.gullychain.xyz", chainId: 485590, accounts: [process.env.PRIVATE_KEY!] }, }, sourcify: { enabled: true, apiUrl: "https://verify.gullychain.xyz", browserUrl: "https://testnet-explorer.gullychain.xyz", }, etherscan: { enabled: false }, }; ``` ```sh npx hardhat verify --network gullychain
``` Any Hardhat version can also use the `artifacts/build-info/*.json` file: its `input` is the standard JSON input you can upload on the web page. ## On the web page 1. Open [verify.gullychain.xyz](https://verify.gullychain.xyz/) and enter the contract address (and the creation transaction hash if you want a creation-bytecode match too). 2. Pick one of two ways: - **metadata.json + sources**: drop the metadata (Foundry: the `rawMetadata` field of `out/.sol/.json`, or the whole artifact file) and every source file it lists. - **Standard JSON input**: upload the solc input file, then give the full compiler version (for example `0.8.28+commit.7893614a`) and the `path:ContractName`. 3. Press **Verify**. The page polls the job and links to the contract in the explorer. The **Look up** tab shows the status, compiler settings and proxy → implementation link of any verified address. ## Proxies Verify both contracts: the proxy and its implementation. Sourcify detects EIP-1967, transparent, UUPS, beacon, Safe and ZeppelinOS proxies and records the implementation (`proxyResolution` in the API). The explorer then offers **As proxy**, which reads and writes the proxy with the implementation's ABI. ## Use the API ```sh # status and match level curl https://verify.gullychain.xyz/v2/contract/485590/
# everything: sources, ABI, compiler settings, std JSON input, proxy resolution curl "https://verify.gullychain.xyz/v2/contract/485590/
?fields=all" # every verified contract on the chain (paged, 200 per page) curl "https://verify.gullychain.xyz/v2/contracts/485590?limit=200" ``` The API answers CORS for `*.gullychain.xyz` and localhost. The full reference is the [Sourcify API v2 docs](https://docs.sourcify.dev/docs/api/). ## When it doesn't match - **`no_match` / `bytecode_length_mismatch`**: the settings differ from the ones you deployed with. Check the solc version, optimizer runs, `evm_version`, `via_ir` and the library addresses. - **`extra_file_input_bug`**: the original build had extra files in the same compiler run. Upload the original standard JSON input (Hardhat `build-info`) instead of the metadata. - **Only "Match"**: the build used `bytecode_hash = "none"` or a different file layout. The source is still verified; keep the default `bytecode_hash` (ipfs) for an exact match next time. - **Contract created by a factory**: you get a runtime match only. That is expected, because the server has no trace API to find the inner creation. # RPC and indexer API Source: https://docs.gullychain.xyz/rpc-api/ > Every way to read GullyChain Testnet: the five public JSON-RPC endpoints in fallback order, keyed Gully RPC access, the indexer REST and GraphQL API (tokens, candles, trades, holders, feed, names, quests, XP, streaks, badges) and the /price/eth endpoint. ## JSON-RPC GullyChain speaks the standard Ethereum JSON-RPC. There are five public ways in, all serving chain `485590`, CORS on, no key. Use them **in this order with a fallback transport**; wallets use the first one. | # | Endpoint | Note | |---|---|---| | 1 | `https://rpc.gullychain.xyz` | Canonical public RPC (eRPC in front of the nodes). | | 2 | `https://rpc.gullyrpc.xyz/gullychain/evm/485590` | The Gully RPC gateway's keyless GullyChain project, on a different server. | | 3 | `https://rpc2.gullychain.xyz` | Straight to the nodes, bypassing eRPC. | | 4 | `https://testnet-rpc.gullychain.xyz` | Legacy endpoint, kept working. Some networks filter hostnames that start with `testnet-`. | | - | `/rpc` (same origin) | On gullychain.xyz and the Gully web apps. Browser code on those hosts tries it first. | Limits per IP, the viem and ethers fallback setup and the rules for retries are on [Network reference](https://docs.gullychain.xyz/network/#public-rpcs). ```bash curl -s https://rpc.gullychain.xyz \ -H "content-type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}' # {"jsonrpc":"2.0","id":1,"result":"0x768d6"} ``` ## Keyed access: Gully RPC For a project that needs its own limits and usage numbers, create a key on **[Gully RPC](https://app.gullyrpc.xyz)** (open sign-up, free tier). GullyChain Testnet is a network on the Gully RPC gateway, so your endpoint is: ```text https://rpc.gullyrpc.xyz//evm/485590 ``` The portal shows requests, errors and latency per key. Every chain Gully Labs runs is served through Gully RPC the same way. ## Indexer API `https://indexer.gullychain.xyz` indexes launches, curve trades, swaps, names, transfers and quests, and serves them as JSON. It is public, read-only and CORS-enabled. `GET /` lists every route. | Route | Returns | |---|---| | `GET /head` | `{ chainId, block, timestamp }` of the last indexed block | | `GET /status`, `GET /ready` | indexer state and readiness | | `GET /tokens` | every launchpad and listed token with price, volume and curve progress | | `GET /tokens/:addr` | one token | | `GET /tokens/:addr/candles?tf=1m\|5m\|15m\|1h\|4h\|1d&limit=` | OHLCV candles | | `GET /tokens/:addr/trades?limit=&before=` | trades, newest first, paged with `before` | | `GET /tokens/:addr/holders?limit=` | holders and balances | | `GET /feed?limit=&before=&address=` | the activity feed (launches, trades, swaps, names), optionally for one address | | `GET /names/:addr`, `GET /names?addresses=a,b` | primary `.gully` names | | `GET /logs?since=`, `GET /logs/transfers/:token?since=` | raw indexed logs and transfers | | `GET /quests?status=&verifier=&creator=&asset=&limit=&offset=` | Gully Quests, filtered | | `GET /quests/stats` | totals: quests, active, completions, pools per asset | | `GET /quests/:id`, `GET /quests/:id/completions?limit=&before=` | one quest and its completions | | `GET /accounts/:a/quests` | an account's quests and completions | | `GET /quests/trending?limit=` | quests with the most recent completions | | `GET /quests/leaderboard?season=current\|all\|&limit=` | the XP leaderboard: rank, name, XP, level, completions, check-ins, badges, best streak | | `GET /quests/:id/analytics` | completions over time for one quest | | `GET /accounts/:a/xp`, `GET /streaks/:a`, `GET /badges/:a` | an account's XP, daily streak and soulbound badges | | `POST /graphql` | the same data over GraphQL | ```bash curl -s https://indexer.gullychain.xyz/head # {"chainId":485590,"block":1718,"timestamp":1793146783} curl -s "https://indexer.gullychain.xyz/feed?limit=20" ``` > [!NOTE] > Numbers in responses (`block`, `timestamp`, amounts) are GullyChain blocks and wei strings. GullyChain makes blocks only when there are transactions, so a quiet `head` is normal. Poll at most every few seconds and cache what you can. ## Price endpoint `GET https://gullychain.xyz/price/eth` returns the mainnet ETH price in USD, cached, for display (the explorer and the app use it to show USD values): ```json {"symbol":"ETH","usd":2344.08,"source":"coingecko","ts":1793146177} ``` For an on-chain price, see [Price oracle](https://docs.gullychain.xyz/oracle/). ## Other public data - **Token list:** [gullychain.xyz/tokenlist.json](https://gullychain.xyz/tokenlist.json), see [Token list](https://docs.gullychain.xyz/token-list/). - **Contract verification:** [verify.gullychain.xyz](https://verify.gullychain.xyz/), a self-hosted Sourcify for chain 485590. Guide: [Verify your contract](https://docs.gullychain.xyz/verify/). - **Explorer:** [testnet-explorer.gullychain.xyz](https://testnet-explorer.gullychain.xyz/). - **Uptime:** [status.gullylabs.xyz](https://status.gullylabs.xyz/) checks every public host each minute. # Token list Source: https://docs.gullychain.xyz/token-list/ > The GullyChain token lists in the Uniswap token-lists format: add them to a wallet or DEX by URL, see which tokens they contain, how they are versioned and how to get a token listed. GullyChain publishes two **token lists** in the standard [Uniswap token-lists](https://github.com/Uniswap/token-lists) format. Wallets, DEX front ends and portfolio tools load them by URL to show GullyChain tokens with the right name, symbol, decimals and logo. | List | URL | What is on it | |---|---|---| | **Gully Chain** (default) | `https://gullychain.xyz/tokenlist.json` | curated: WETH9, gETH, USDC.e (featured), glUSD (deprecated) and reviewed launchpad tokens | | **Gully Chain Extended** | `https://gullychain.xyz/tokenlist-extended.json` | the default list plus every active launchpad token | Logos are at `https://gullychain.xyz/tokens/logos/485590/
.png` (or `.svg`). All of them are served with `Access-Control-Allow-Origin: *` and a five-minute cache, so a web app can fetch them directly. The lists are built and reviewed in the public repo [gully-labs/token-lists](https://github.com/gully-labs/token-lists). ## What is in the default list All tokens are on GullyChain Testnet (chain ID `485590`). Name, symbol and decimals are read from each contract on chain when the list is built, never typed in by hand. | Token | Address | Tags | |---|---|---| | WETH (Wrapped Ether, WETH9) | `0x26aCCCb2e98ca9e067E58668Aa3B101beF432754` | `wrapped` (native wrapped) | | gETH (Gully Bridged ETH) | `0x7Dd1Aa3d8598A3edB43EB43ddcb5BCE4AbfBb702` | `bridged` | | USDC.e (Bridged USDC, Circle Bridged USDC Standard) | `0x65Ba03c6FA90Ed549f465D4c8f2e784D6eEB7E76` | `stablecoin`, `bridged` | | glUSD (Gully USD, retired: redeem 1:1 for USDC.e) | `0xDBE84bE6496Fb3d07F601548555ec7Acc4CeBa8F` | `stablecoin`, `deprecated` | | FROG, MOSS, LABRAT | launchpad launches | `launchpad` | - **WETH9** is the one wrapped ETH on GullyChain: Gully Swap, Uniswap v3 and the launchpad all use it. Wrap and unwrap native ETH with `deposit()` and `withdraw()`. - **gETH** is ETH bridged from Arbitrum Sepolia over the earlier Hyperlane warp route, **retired 2026-10-28** (redeem only: the fast lane now delivers native ETH; see [Bridging](https://docs.gullychain.xyz/bridging/#retired-routes-geth-and-hypeth-redeem-only)). Its entry carries a `bridgeInfo` extension pointing at the Arbitrum Sepolia side (chain `421614`). - **USDC.e** is the chain's stablecoin (6 decimals, tag `featured`). glUSD (6 decimals) is retired and tagged `deprecated` until its supply is 0. USDC.e carries a `bridgeInfo` extension pointing at Circle's USDC on Arbitrum Sepolia. See [Stablecoins](https://docs.gullychain.xyz/stablecoins/). - The Arbitrum token-bridge WETH (`0x3292dE74305DF64dbe082c6834fa841353eB2415`, also symbol WETH, never used) is left out on purpose so a token picker shows one WETH. ## The extended list The extended list adds every token launched on the Gully Chain launchpad (and on [Gully Core](https://docs.gullychain.xyz/gully-core/) once it is live) that the indexer shows as active (at least 2 holders and 3 trades, or graduated to a Gully Swap pool). Tags: `launchpad`, and `graduated` once it has its pool. A token with a published Gully Security report with critical or high findings is left out. Launch tokens on the testnet are test tokens with no value, and the list does not vouch for them. ## Use it **Uniswap-style interfaces:** open the token selector, choose *Manage* then *Lists*, and paste the URL. **Wallets:** add a single token by address on GullyChain Testnet; symbol and decimals fill in from the contract. **From code:** ```ts const LIST = "https://gullychain.xyz/tokenlist.json"; const list = await fetch(LIST).then((r) => r.json()); const tokens = list.tokens.filter((t) => t.chainId === 485590); const stables = tokens.filter((t) => t.tags?.includes("stablecoin")); ``` Ship a copy of the list with your app as a fallback for when the fetch fails. ## Versioning The lists follow the token-lists versioning rules: - **major**: a token was removed; - **minor**: a token was added (for example a new launch); - **patch**: a token's metadata changed (name, logo, tags). `timestamp` changes only when the version changes. Every build is validated against the official token-lists JSON schema, and every token is read back from the chain, before it is published. ## Get a token listed Launchpad tokens join the extended list on their own once they are active. For the default list, open a pull request on [gully-labs/token-lists](https://github.com/gully-labs/token-lists) (the [contributing guide](https://github.com/gully-labs/token-lists/blob/main/CONTRIBUTING.md) has the details): 1. Verify the contract source on the [explorer](https://testnet-explorer.gullychain.xyz). 2. Add the address and tags to `gully/config.json` and a 256x256 logo at `logos/485590/
.png`. 3. Run `node build.mjs` and `node validate.mjs --onchain` in `gully/tools`: the build reads name, symbol and decimals from the chain and bumps the version. 4. Open the PR with the add-token template. CI repeats every check on chain; a reviewer checks liquidity, holders and Gully Security before merging. # Bridging Source: https://docs.gullychain.xyz/bridging/ > Bridge between Arbitrum Sepolia and GullyChain two ways: the Hyperlane fast lane (native ETH in about a minute, both directions) and the canonical Arbitrum bridge for ETH and ERC-20 tokens, with deposits, withdrawals and retryable tickets. The **[Gully Bridge](https://bridge.gullychain.xyz/)** (also at testnet-bridge.gullychain.xyz) has two lanes: | Lane | What moves | Time | Trust | |---|---|---|---| | **Fast lane** (Hyperlane) | ETH on Arbitrum Sepolia ↔ **native ETH** on GullyChain | about a minute, **both ways** | Hyperlane messaging, verified by 2 of Gully's 3 validators and delivered by Gully's relayer | | **Canonical** (Arbitrum rollup bridge) | ETH, ERC-20 tokens, USDC | deposits about a minute; withdrawals after the confirmation period | the rollup itself, no extra trust | This page explains what happens underneath and how to do it from code. All addresses are on [Contract addresses](https://docs.gullychain.xyz/contracts/). **USDC** has its own gateway pair and arrives as USDC.e under the Circle Bridged USDC Standard: see [Stablecoins](https://docs.gullychain.xyz/stablecoins/). ## Fast lane: Hyperlane native ETH > [!LIVE] > **Live since 2026-10-28.** Warp route `ETH/arbitrumsepolia-gullychaintestnet-native`: real ETH on both sides. The fast lane is a Hyperlane warp route with a native ETH router on each chain. ETH you send on Arbitrum Sepolia is locked in the route's router there, and the router on GullyChain pays you the same amount of **native ETH**, the chain's gas token, in about a minute. The way back works the same: send ETH on GullyChain, receive ETH on Arbitrum Sepolia. There is no seven-day wait in either direction and no wrapped token. | Contract | Address | |---|---| | ETH router on GullyChain (HypNative) | `0xB1943191df824138bd0784C60077c6610F380810` | | ETH router on Arbitrum Sepolia (HypNative) | `0x9E40F1702977A0a48Fa275522Ba6877E209DE631` | | 2-of-3 multisig ISM on Arbitrum Sepolia (Gully's validators) | `0xFaeD30bBc77780df26Bd931d92bdee7B53e1e931` | | Hyperlane Mailbox on GullyChain | `0x5b875dac092FcA7cE0DfEe8B7C1dbBD2c2a0cfDe` | | Hyperlane Mailbox on Arbitrum Sepolia | `0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8` | - **Liquidity.** Each router can only pay out the ETH it holds (a seed plus earlier transfers into it). The bridge checks the destination router before you send; if the amount is larger, it suggests the canonical lane instead, so a transfer never waits for liquidity. - **Security.** Messages to Arbitrum Sepolia are checked by a **2-of-3** multisig ISM of Gully's three validators; messages to GullyChain use the Mailbox default ISM (Hyperlane's Arbitrum Sepolia validator). Gully's relayer pays for delivery. On testnet the three validators run on one server; mainnet runs them with separate operators. The core contracts are Hyperlane's own audited code. - **From code**, call `transferRemote(destinationDomain, recipient, amount)` on the router of the chain you send from (domains: `421614` Arbitrum Sepolia, `485590` GullyChain), with `value` = amount + `quoteGasPayment(destinationDomain)` (or sum the native entries of `quoteTransferRemote`). ### Retired routes: gETH and hypETH (redeem only) Before 2026-10-28 the fast lane minted **gETH** ("Gully Bridged ETH", ERC-20) on GullyChain; an earlier route used hypETH. Both are retired: the bridge no longer sends new deposits through them, but **every gETH and hypETH can still be redeemed 1:1 for ETH on Arbitrum Sepolia**. Open the [Gully Bridge](https://testnet-bridge.gullychain.xyz/) with the wallet that holds it and press **Redeem for ETH**. The routes stay enrolled and relayed, and are checked by the same 2-of-3 validators. | Contract | Address | |---|---| | gETH on GullyChain (retired, redeem only) | `0x7Dd1Aa3d8598A3edB43EB43ddcb5BCE4AbfBb702` | | gETH's ETH router on Arbitrum Sepolia | `0x3Aa770313a4c8aa6F9B1055fDBfd9dbC4051bad0` | The rest of this page covers the canonical lane. > [!WARNING] > **Two clocks.** Confirmation periods, retryable lifetimes and anything else the bridge counts in blocks are counted in the **parent chain's** blocks. Inside a GullyChain contract, `block.number` is also the parent chain's block number, not the L3's. Use `block.timestamp` or `ArbSys(0x64).arbBlockNumber()`; see [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number). ## Deposits: Arbitrum Sepolia to GullyChain ### ETH An ETH deposit is a call to `depositEth()` on the rollup's **Inbox** on Arbitrum Sepolia, sending the ETH as value. The same address receives the ETH on GullyChain once the chain reads the message from the parent chain, which takes **about a minute**. ```ts import { createWalletClient, custom, parseEther } from "viem"; import { arbitrumSepolia } from "viem/chains"; const INBOX = "0x7B8499f1C058c9bdE2Bc9BdFEBE40364232C52B5"; // on Arbitrum Sepolia const wallet = createWalletClient({ chain: arbitrumSepolia, transport: custom(window.ethereum) }); const [account] = await wallet.requestAddresses(); const hash = await wallet.writeContract({ account, address: INBOX, abi: [{ type: "function", name: "depositEth", stateMutability: "payable", inputs: [], outputs: [{ type: "uint256" }] }], functionName: "depositEth", value: parseEther("0.01"), }); ``` The deposit goes to the address that sent it. If the sender is a contract, its address is aliased on GullyChain (the standard Arbitrum address alias), so deposit from an EOA unless you know you need otherwise. ### ERC-20 tokens ERC-20 deposits go through the **gateway router** on Arbitrum Sepolia. The router picks the gateway for the token (the standard gateway for ordinary tokens), the gateway locks your tokens, and a matching token is minted to you on GullyChain. The first deposit of a token also deploys its GullyChain version. Deposits arrive in about a minute. The Arbitrum SDK handles the approval, gas estimation and retryable ticket for you. Register GullyChain once, then use `Erc20Bridger`: ```ts // @arbitrum/sdk v4 (uses ethers v5 signers and providers) import { registerCustomArbitrumNetwork, Erc20Bridger, EthBridger } from "@arbitrum/sdk"; const gully = registerCustomArbitrumNetwork({ name: "GullyChain Testnet", chainId: 485590, parentChainId: 421614, confirmPeriodBlocks: 150, isCustom: true, isTestnet: true, ethBridge: { bridge: "0x2073106fd3fc844Bbde31f5Bf0BB91cf1e2d6C8A", inbox: "0x7B8499f1C058c9bdE2Bc9BdFEBE40364232C52B5", sequencerInbox: "0x483f77f692635d4D8a8147D0f732A016614Ce685", outbox: "0x976C651fe5E63E45C8C28449507F51548922f68c", rollup: "0x85D80C06Fa5334E8Cd1C51F3F39D477E5dc35E0D", }, tokenBridge: { parentGatewayRouter: "0xfbd7503009AB4ee5A1f980a2fCDEE4C7BEB6b2B9", parentErc20Gateway: "0x8E35E523bFd709d577A77F749c831cB045bCabd0", parentCustomGateway: "0xA90752f7057dc1BFe2677f1791c5084535A4E42a", parentWethGateway: "0xEB602d8Fc5F5d87DA629201905bE51885165EC4f", parentWeth: "0x980B62Da83eFf3D4576C647993b0c1D7faf17c73", parentMultiCall: "0xce1CAd780c529e66e3aa6D952a1ED9A6447791c1", childGatewayRouter: "0x32C680cA4c27A3566fE5Dfd4643fE420eE1039B7", childErc20Gateway: "0x5CbA5BFD52beA26Fb65c26Fa452f290cB8610fE2", childCustomGateway: "0x27530E706c67F210753081508302d69ba1693A41", childWethGateway: "0xB8BAAd59F553707534F546983912486562FA0Eb3", childWeth: "0x3292dE74305DF64dbe082c6834fa841353eB2415", childMultiCall: "0xc0Dee8709648264495af14c65fEA2Ae7a728E01a", }, }); const erc20Bridger = new Erc20Bridger(gully); // 1. approve the gateway once per token await (await erc20Bridger.approveToken({ erc20ParentAddress: TOKEN, parentSigner })).wait(); // 2. deposit, then wait for the tokens on GullyChain const tx = await erc20Bridger.deposit({ amount: 1_000_000n, erc20ParentAddress: TOKEN, parentSigner, // signer on Arbitrum Sepolia childProvider, // provider for https://rpc.gullychain.xyz }); const receipt = await tx.wait(); await receipt.waitForChildTransactionReceipt(childProvider); ``` `EthBridger` from the same SDK does ETH deposits and withdrawals with the same network object. ## Withdrawals: GullyChain to Arbitrum Sepolia > [!LIVE] > **Canonical withdrawals are live.** The chain's validator is staked on Arbitrum Sepolia since 2026-10-27 and assertions are being confirmed, so a withdrawal can be claimed on the Outbox once the assertion that includes it is confirmed. For ETH that you need back quickly, use the [fast lane](#fast-lane-hyperlane-native-eth) instead. A withdrawal has three stages: 1. **Start it on GullyChain.** For ETH, call `withdrawEth(destination)` on the ArbSys precompile at `0x…64` with the ETH as value. For tokens, use the gateway router on GullyChain (or `Erc20Bridger.withdraw`). This burns the funds on GullyChain and creates an outgoing message. 2. **Wait for confirmation.** The sequencer posts the batch to Arbitrum Sepolia, the validator posts an assertion that includes it, and the assertion must sit unchallenged for the rollup's **confirmation period of 150 blocks**. The rollup counts blocks with `block.number` on Arbitrum Sepolia, which follows Ethereum Sepolia's block number, so 150 blocks is roughly 30 minutes once the assertion is posted. 3. **Claim it on Arbitrum Sepolia.** Execute the message on the **Outbox**. The SDK does this with `getChildToParentMessages`, `waitUntilReadyToExecute` and `execute`. ```ts // start an ETH withdrawal on GullyChain with viem await wallet.writeContract({ address: "0x0000000000000000000000000000000000000064", // ArbSys abi: [{ type: "function", name: "withdrawEth", stateMutability: "payable", inputs: [{ name: "destination", type: "address" }], outputs: [{ type: "uint256" }] }], functionName: "withdrawEth", args: [account], value: parseEther("0.001"), }); ``` The 150-block period is the testnet's setting. Mainnet's period will be published before launch. ## Retryable tickets Anything sent from Arbitrum Sepolia to a contract on GullyChain, including every ERC-20 deposit, travels as a **retryable ticket**: - You pay on Arbitrum Sepolia for a submission fee plus the L3 gas the call will need. Unused value is refunded to a refund address on GullyChain. - GullyChain tries to run the call automatically as soon as the message arrives (the **auto-redeem**). - If the auto-redeem fails, for example because the gas price rose or too little gas was given, the ticket is **not lost**. Anyone can retry it on GullyChain through the `ArbRetryableTx` precompile (`redeem(ticketId)` at `0x…6E`) for up to seven days, and the lifetime can be extended. The Arbitrum SDK estimates the fees and waits for the redeem for you. Plain ETH deposits through `depositEth()` are not retryables; they credit the ETH directly. # Stablecoins Source: https://docs.gullychain.xyz/stablecoins/ > USDC.e is the stablecoin on GullyChain Testnet (Circle Bridged USDC Standard, bridged from Arbitrum Sepolia). glUSD is retired and redeemable 1:1 for USDC.e. **USDC.e is the stablecoin on GullyChain.** Every Gully product (Gully Pay checkout and x402, Gully Swap, Creators, Quests, the faucet) prices and settles in USDC.e, with **6 decimals**. | Token | Address | What it is | |---|---|---| | **USDC.e** ("Bridged USDC (Gully Labs)") | `0x65Ba03c6FA90Ed549f465D4c8f2e784D6eEB7E76` | Circle's USDC from Arbitrum Sepolia, bridged to GullyChain through a dedicated USDC gateway pair. | | glUSD ("Gully USD"), **retired** | `0xDBE84bE6496Fb3d07F601548555ec7Acc4CeBa8F` | Retired on 2026-10-28. No new glUSD can be minted; every glUSD stays redeemable 1:1 for USDC.e. | | glUSD PSM | `0xe1Ae51036ede1b244c532A81FaC196f19fa5E28e` | Redeem-only: `redeem(amount, to)` burns glUSD and pays USDC.e. | Both are in the [token list](https://docs.gullychain.xyz/token-list/): USDC.e with the `stablecoin` and `featured` tags, glUSD tagged `deprecated` until its supply reaches 0. > [!WARNING] > **Testnet only.** These are test tokens with no value. USDC.e is bridged by Gully Labs and is **not issued by Circle**; its backing is the USDC held in the bridge's escrow on Arbitrum Sepolia. ## USDC.e: Circle Bridged USDC Standard USDC.e follows Circle's [Bridged USDC Standard](https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md), using the same USDC gateways Offchain Labs ships for Arbitrum Orbit chains: - The token on GullyChain is **Circle's own FiatToken code** (FiatTokenV2_2 behind a FiatTokenProxy), so it behaves exactly like USDC: `permit` (EIP-2612), `transferWithAuthorization` (EIP-3009) and 6 decimals. - The **L2 USDC gateway** `0xd9d07510cEEfeeaF538bDDbe4ee1B76E9F1A71B3` is its only minter. It mints on deposit and burns on withdrawal. - The **L1 USDC gateway** on Arbitrum Sepolia `0xF904064BE100489a200EB754E591362C7Ced2D5b` escrows the USDC, so every USDC.e is backed 1:1 by USDC locked there. - Because it follows the standard, Circle could later take the token over and turn it into native USDC at the **same address**, with the same holders. That is an option for Circle, not a promise. The standard ERC-20 gateway is **not** used for USDC: deposits of USDC through the router go to the USDC gateway automatically. ### Bridge USDC from Arbitrum Sepolia 1. **Get test USDC** on Arbitrum Sepolia from Circle's faucet, [faucet.circle.com](https://faucet.circle.com/) (choose USDC and Arbitrum Sepolia). The Arbitrum Sepolia USDC address is `0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d`. 2. **Keep a little Arbitrum Sepolia ETH** for gas and the retryable ticket fee (about 0.0001 ETH). 3. **Deposit through the gateway router.** The Arbitrum SDK's `Erc20Bridger` approves the right gateway and sizes the retryable for you. Use the network object from [Bridging](https://docs.gullychain.xyz/bridging/#erc-20-tokens): ```ts const USDC_ARB_SEPOLIA = "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d"; const erc20Bridger = new Erc20Bridger(gully); // registered as on the Bridging page // approves the L1 USDC gateway (the router picks it for USDC) await (await erc20Bridger.approveToken({ erc20ParentAddress: USDC_ARB_SEPOLIA, parentSigner })).wait(); const tx = await erc20Bridger.deposit({ amount: 5_000_000n, // 5 USDC (6 decimals) erc20ParentAddress: USDC_ARB_SEPOLIA, parentSigner, // signer on Arbitrum Sepolia childProvider, // provider for https://rpc.gullychain.xyz }); await (await tx.wait()).waitForChildTransactionReceipt(childProvider); ``` USDC.e arrives on GullyChain after the deposit message is read from Arbitrum Sepolia, usually within minutes. **Withdrawing** works the other way: approve the **L2 USDC gateway** for the amount (it pulls and burns the USDC.e), then call `outboundTransfer(, , , 0x)` on the GullyChain gateway router `0x32C680cA4c27A3566fE5Dfd4643fE420eE1039B7`. The USDC is released on Arbitrum Sepolia through the Outbox after the confirmation period; see [Withdrawals](https://docs.gullychain.xyz/bridging/#withdrawals-gullychain-to-arbitrum-sepolia). ## glUSD is retired: redeem it for USDC.e On 2026-10-28 Gully Labs retired glUSD and moved every product to USDC.e. What that means for a holder: - **Nothing is lost.** glUSD was always fully backed: the PSM holds one USDC.e for every glUSD. - **Redeem at any time, 1:1, no fee.** `redeem` cannot be paused, so this works forever. In the Gully ID wallet use **Earn → Redeem glUSD to USDC.e**, or call the PSM yourself: ```ts const PSM = "0xe1Ae51036ede1b244c532A81FaC196f19fa5E28e"; await wallet.writeContract({ address: PSM, abi: [{ type: "function", name: "redeem", stateMutability: "nonpayable", inputs: [{ name: "amount", type: "uint256" }, { name: "to", type: "address" }], outputs: [] }], functionName: "redeem", args: [amount, account], // burns `amount` glUSD from you (no approve needed), pays USDC.e to `account` }); ``` - **Redeem-by date: 2026-11-11 00:00 UTC.** After that date Gully Labs also sends every address still holding glUSD the same amount of USDC.e. Your glUSD stays redeemable after that too. - **No new glUSD.** PSM deposits are paused. Gully Pay, Creators, Quests, Swap and the faucet no longer take or pay glUSD. The gtGLUSD treasury vault is withdraw-only. ## Legal notes - **Testnet only.** These are test tokens on a testnet and have no value. - **USDC.e is not Circle-issued.** It is a bridged form of USDC; Circle does not issue it or stand behind it. - **glUSD** was a testnet technical preview. It is retired, it will not go to mainnet, and it was never an offer of a payment stablecoin. - **Admin roles.** On the testnet, the token roles (USDC.e owner, pauser, blacklister, gateway owners) are held by a Gully Labs testnet key. They move to multisigs before any mainnet. # Accounts and passkeys Source: https://docs.gullychain.xyz/account-abstraction/ > Smart accounts on GullyChain Testnet: ZeroDev Kernel accounts with passkey login and session keys, a public ERC-4337 bundler and a paymaster for sponsored gas. > [!LIVE] > **Live on testnet.** Kernel v3.3 smart accounts, passkey login, session keys and sponsored gas all work on GullyChain Testnet today, through a public ERC-4337 bundler and an ERC-7677 paymaster. GullyChain builds smart accounts in from the start, so a new user needs **no seed phrase** (a passkey such as Face ID, Touch ID or a security key is the account's key) and **no ETH** for a first transaction (gas can be sponsored). ## What is live | Piece | What it does | |---|---| | **Kernel v3.3 accounts** | ZeroDev's open-source (MIT) ERC-7579 modular smart account, deployed through its factory on EntryPoint v0.7. | | **Passkeys** | The WebAuthn validator makes a passkey the account's root key. The WebAuthn signer adds extra devices and a recovery passkey. P-256 signatures are checked on chain. | | **Session keys** | An ordinary key (ECDSA signer) can be given limited powers: only certain contracts and functions (call policy), a number of uses per time window (rate-limit policy) and an expiry (timestamp policy). Games and apps can act for the user without a passkey prompt each time. | | **Bundler** | A public ERC-4337 bundler (Alto) for EntryPoint v0.7. | | **Paymaster** | An ERC-7677 paymaster service that sponsors gas for approved apps, backed by a verifying paymaster on EntryPoint v0.7. | The GullyChain app at [app.gullychain.xyz](https://app.gullychain.xyz/) uses these accounts for sign-in with a passkey and sponsored transactions. ## Endpoints | Service | URL | Notes | |---|---|---| | ERC-4337 bundler | `https://testnet-bundler.gullychain.xyz` | EntryPoint v0.7 `0x0000000071727De22E5E9d8BAf0edAc6f37da032`. Standard `eth_sendUserOperation`, `eth_estimateUserOperationGas` and friends. | | ERC-7677 paymaster | `https://testnet-paymaster.gullychain.xyz` | `pm_getPaymasterStubData` and `pm_getPaymasterData`. Needs an **API key per app**: pass it as `?apikey=` on the URL or as `apiKey` in the ERC-7677 context. Sponsorship has per-account rate limits and a per-operation gas cap. | To get a paymaster API key for your app, email [team@gullylabs.xyz](mailto:team@gullylabs.xyz) with the app name and what it will sponsor. Without a key you can still use the bundler and pay gas from the account's own ETH (use the [faucet](https://faucet.gullychain.xyz/)). ## Contracts | Contract | Address | |---|---| | Kernel v3.3 (implementation) | `0xd6CEDDe84be40893d153Be9d467CD6aD37875b28` | | KernelFactory v3.3 | `0x2577507b78c2008Ff367261CB6285d44ba5eF2E9` | | FactoryStaker (meta factory) | `0x3fe1D99661BBD711a434045df5262e594Dd6cA9a` | | WebAuthnValidator 0.0.3 | `0x7ab16Ff354AcB328452F1D445b3Ddee9a91e9e69` | | WebAuthnSigner 0.0.4 | `0x65DEeC8fEe717dc044D0CFD63cCf55F02cCaC2b3` | | ECDSASigner | `0x6A6F069E2a08c2468e7724Ab3250CdBFBA14D4FF` | | SudoPolicy | `0x67b436caD8a6D025DF6C82C5BB43fbF11fC5B9B7` | | CallPolicy 0.0.5 | `0x85770b902D1e503D5f5141d9eaC16d0d08eEaDd2` | | RateLimitPolicy | `0xf63d4139B25c836334edD76641356c6b74C86873` | | TimestampPolicy | `0xB9f8f524bE6EcD8C945b1b87f9ae5C192FdCE20F` | | EntryPoint v0.7 | `0x0000000071727De22E5E9d8BAf0edAc6f37da032` | | EntryPoint v0.8 | `0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108` | The Safe 4337 module, SafeModuleSetup and the P256 verifier are also deployed (see [Contract addresses](https://docs.gullychain.xyz/contracts/#erc-4337-core)). Safe accounts work too, on the Safe 1.4.1 contracts at Gully's own addresses: see [Gully Safe](https://docs.gullychain.xyz/safe/). The bundler accepts user operations for **EntryPoint v0.7**; EntryPoint v0.8 is deployed for tooling that needs it. To sign users in to your app with the same passkey, and get their smart-account address as a claim, use [Gully ID](https://docs.gullychain.xyz/gully-id/). ## How a sponsored transaction works 1. **The app builds a UserOperation** for the user's Kernel account. If the account does not exist yet, the operation includes the data to deploy it through the Kernel factory, with the passkey validator as its root. 2. **The paymaster signs it.** The app asks the paymaster service to sponsor the operation (ERC-7677). The service checks the app's API key and its limits and returns a short-lived signature. 3. **The user signs it** with their passkey, or with a session key the account has approved. 4. **The bundler submits it** to EntryPoint v0.7. The EntryPoint deploys the account if needed, runs the call and charges the gas to the paymaster's deposit instead of the user. ## Example: a passkey account with sponsored gas Libraries that speak ERC-4337 and ERC-7677 work as they do on other chains. This sketch uses ZeroDev's SDK on top of viem; any Kernel v3.3 client that lets you set the bundler and paymaster URLs works the same way. ```ts import { createPublicClient, http, zeroAddress } from "viem"; import { createKernelAccount, createKernelAccountClient, createZeroDevPaymasterClient } from "@zerodev/sdk"; import { KERNEL_V3_3, getEntryPoint } from "@zerodev/sdk/constants"; import { toPasskeyValidator, toWebAuthnKey, WebAuthnMode, PasskeyValidatorContractVersion } from "@zerodev/passkey-validator"; const entryPoint = getEntryPoint("0.7"); const publicClient = createPublicClient({ chain: gullyTestnet, transport: http() }); // gullyTestnet: see Quickstart const webAuthnKey = await toWebAuthnKey({ passkeyName: "alice", mode: WebAuthnMode.Register /* plus your passkey server */ }); const passkey = await toPasskeyValidator(publicClient, { webAuthnKey, entryPoint, kernelVersion: KERNEL_V3_3, validatorContractVersion: PasskeyValidatorContractVersion.V0_0_3_PATCHED, }); const account = await createKernelAccount(publicClient, { plugins: { sudo: passkey }, entryPoint, kernelVersion: KERNEL_V3_3, }); const paymaster = createZeroDevPaymasterClient({ chain: gullyTestnet, transport: http("https://testnet-paymaster.gullychain.xyz/?apikey=YOUR_KEY"), }); const client = createKernelAccountClient({ account, chain: gullyTestnet, bundlerTransport: http("https://testnet-bundler.gullychain.xyz"), paymaster, }); await client.sendTransaction({ to: zeroAddress, value: 0n, data: "0x" }); ``` Check the exact option names against the SDK version you install. The addresses the SDK needs (Kernel v3.3, its factory, the WebAuthn validator) are the standard ones listed above. ## Good to know - **Passkeys are bound to a domain.** A passkey belongs to the website (relying party) that created it. Plan your domain before your users create accounts. - **Keep a recovery path.** Add a second passkey or a recovery wallet through the WebAuthn signer or ECDSA signer, so losing one device does not lose the account. - **Time-based policies use `block.timestamp`.** Session-key expiry and rate limits work in seconds. Do not build your own block-count windows: on GullyChain `block.number` is the parent chain's block number (see [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number)). - **Testnet.** Accounts, sponsorship limits and API keys on the testnet may be reset. # Gully ID sign-in Source: https://docs.gullychain.xyz/gully-id/ > Add Sign in with Gully to any app with standard OpenID Connect at gullyid.xyz. Passkey, wallet or email sign-in, and claims for the user's GullyChain wallet, .gully name and on-chain reputation. > [!LIVE] > **Live at [gullyid.xyz](https://gullyid.xyz/) since 2026-10-27** (it moved from id.gullychain.xyz, which now forwards sign-ins). Open sign-up, no waitlist, free up to 1,000 monthly active users. Gully ID is the one sign-in across every Gully product: the GullyChain app, the faucet, the bridge, the explorer, Gully Pay, Gully RPC and Gully Studio. It is a standard **OpenID Connect** provider, so any OIDC library works. Users sign in with a **passkey**, a **wallet** (SIWE) or **email**. Every user gets a smart-account wallet on GullyChain, and your app can ask for that wallet, the user's `.gully` name and their on-chain reputation as claims. ## Quickstart 1. **Sign in to the [console](https://gullyid.xyz/developers/console)** with your own Gully ID. 2. **Create an app.** Pick a **public** client for code that runs in the browser or a mobile app (authorization code with PKCE, no secret), or a **confidential** client for a server (a client secret, shown once). Redirect URIs must be `https` and match exactly; `http` is allowed only for `localhost`. 3. **Add the button.** Load `https://gullyid.xyz/sdk.js`, or use any OIDC library. 4. **Read the claims** from the id_token, or from `/userinfo`. | Setting | Value | |---|---| | Issuer | `https://gullyid.xyz/` | | Discovery | [`https://gullyid.xyz/.well-known/openid-configuration`](https://gullyid.xyz/.well-known/openid-configuration) | | Authorization | `https://gullyid.xyz/oauth2/auth` | | Token | `https://gullyid.xyz/oauth2/token` | | JWKS | `https://gullyid.xyz/.well-known/jwks.json` | | Userinfo | `https://gullyid.xyz/userinfo` | | Browser SDK | `https://gullyid.xyz/sdk.js` | | Full guide | [gullyid.xyz/developers/sign-in-with-gully](https://gullyid.xyz/developers/sign-in-with-gully) | ## Browser: the SDK ```html ``` `signIn()` opens a popup by default. `signIn({ mode: "redirect" })` uses a full-page redirect (call `gully.handleRedirect()` on your callback page), and `signIn({ mode: "passkey" })` tries a passkey prompt straight away. `gully.signOut()` ends the session. ## Any OIDC library (PKCE) ```text GET https://gullyid.xyz/oauth2/auth?response_type=code&client_id=YOUR_CLIENT_ID &redirect_uri=https://app.example.com/auth/callback&scope=openid%20profile%20wallet &state=RANDOM&nonce=RANDOM&code_challenge=S256(VERIFIER)&code_challenge_method=S256 POST https://gullyid.xyz/oauth2/token grant_type=authorization_code&code=...&redirect_uri=...&code_verifier=VERIFIER&client_id=YOUR_CLIENT_ID ``` Confidential clients authenticate the token request with HTTP Basic (`client_id:client_secret`). > [!WARNING] > **Verify tokens on your server** before you grant anything of value. Check the signature against the JWKS, and `iss` (`https://gullyid.xyz/`), `aud` (your client id), `exp` and `nonce`. Decoding a token in the browser is for display only. ## Scopes and claims | Scope | Claims | |---|---| | `openid` | `sub` (stable per user and app), `amr` (`passkey`, `wallet`, `email`, `google`, `x`) | | `profile` | `name`, `picture` | | `email` | `email`, `email_verified` | | `wallet` | `wallet: { chainId: 485590, address, kind }`, the user's GullyChain smart account | | `gully_name` | `gully_name`, for example `alice.gully`, or `null` | | `reputation` | `reputation: { verified, hasGullyName, accountAgeBlocks, quests: { completed, ids }, xp, badges, available }`, read from GullyChain | | `offline_access` | a refresh token (30 days, rotated) | The `reputation` claim is built from on-chain state: the GullyVerified check, the `.gully` name, Gully Quests completions, XP and soulbound badges (see [Quests](https://docs.gullychain.xyz/quests/)). Users see every item on the consent screen, with the value that would be shared. Gully ID never gives an app a passkey or a way to move funds: the `wallet` claim is an address, not a key. ## Gully Wallet and one-tap approvals Sign in with Gully gives you who the user is. For on-chain actions, load the **Gully Wallet SDK** (`https://gullyid.xyz/wallet.js`): an EIP-1193 provider (`window.gully`, also announced over EIP-6963) with `wallet_sendCalls` batches, `personal_sign` and `eth_signTypedData_v4`. Small spends from a connected app take **one tap** under a daily limit ($25 a day by default, $0 to $250 per app), enforced on chain by a session key with GullySessionPolicy `0xFDEB7b7715200dBc94A058BA1254b863c08D070E`. Everything else asks for the passkey. Code and the approval tiers: [developer portal, Gully ID one-tap](https://dev.gullychain.xyz/integrate/#gully-id); the full guide is at [gullyid.xyz/developers/wallet-sdk](https://gullyid.xyz/developers/wallet-sdk). ## Other sign-in methods Telegram and Farcaster sign-in are live next to passkey, wallet and email. > [!SOON] > Google, X and Sign in with Apple are coming soon. ## Plans | Plan | Price | Monthly active users | |---|---|---| | Free | $0 | 1,000 | | Build | $29 / month | 10,000 | | Scale | $199 / month | 100,000 | Billing goes through [Gully Pay](https://gullypay.xyz). Going over a plan never locks your users out: you get a notice and time to upgrade. ## Buttons Use the official buttons from the guide, or the CSS button: `` with ``. # Gully Safe Source: https://docs.gullychain.xyz/safe/ > Gully Safe on GullyChain Testnet: Safe 1.4.1 multisig wallets at safe.gullychain.xyz, the unmodified Safe contracts at Gully's own addresses, passkey signers, the Safe 4337 module and how to point Safe tooling at them. > [!LIVE] > **Live on testnet.** [safe.gullychain.xyz](https://safe.gullychain.xyz/) runs the Safe{Wallet} app, Gully's own Safe backend and the Safe 1.4.1 contracts on GullyChain Testnet (chain 485590). Test funds only. Gully Safe is a Safe multisig for teams, treasuries and DAOs on GullyChain: several owners, a confirmation threshold, batched transactions and an on-chain record of every confirmation. It is the Safe product you know, branded for GullyChain. ## What runs where | Piece | What | |---|---| | App | [safe.gullychain.xyz](https://safe.gullychain.xyz/): a fork of the Safe{Wallet} web app with GullyChain as its network | | Backend | Gully's own Safe transaction service, config service and client gateway, indexing chain 485590 | | Contracts | Safe 1.4.1 and the Safe passkey modules, **unmodified** code and salts, at Gully's own addresses (below) | | Sponsored gas | Safe accounts can run as ERC-4337 accounts through the Safe 4337 module, the Alto bundler and the Gully paymaster ([Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/)) | ## Why the addresses differ Safe's canonical addresses come from Safe's signed singleton factory, which the Safe team deploys per chain on request. It is **not on GullyChain yet** ([Not deployed yet](https://docs.gullychain.xyz/contracts/#not-deployed-yet)). So Gully Labs replayed the exact canonical deployments (same creation code, same salts) through the Arachnid CREATE2 factory. The code is byte-for-byte Safe's audited code; only the deployer, and therefore the address, differs. > [!WARNING] > Pass the Gully addresses to Safe tooling explicitly. Libraries that look up Safe's canonical addresses for a chain ID will not find GullyChain, and calls to the canonical 1.4.1 addresses on chain 485590 hit empty accounts. ## Contracts | Contract | Address | |---|---| | Safe 1.4.1 (singleton) | `0x639245e8476E03e789a244f279b5843b9633b2E7` | | SafeL2 1.4.1 (singleton used by every Gully Safe) | `0x76667330c237Fb40f28d74563cdAAae4b06C23Ec` | | SafeProxyFactory 1.4.1 | `0xd9d2Ba03a7754250FDD71333F444636471CACBC4` | | CompatibilityFallbackHandler 1.4.1 | `0xcB4a8d3609A7CCa2D9c063a742f75c899BF2f7b5` | | MultiSend 1.4.1 | `0x7B21BBDBdE8D01Df591fdc2dc0bE9956Dde1e16C` | | MultiSendCallOnly 1.4.1 | `0x32228dDEA8b9A2bd7f2d71A958fF241D79ca5eEC` | | SignMessageLib 1.4.1 | `0x309C7b0A0D2f250Be322739753386911E1187C4E` | | CreateCall 1.4.1 | `0x8BbCaE989A0Bdf15c8E783357a0E5848e36233d0` | | SafeWebAuthnSharedSigner 0.2.1 (passkey owners) | `0xB3a6Aa3eDDD715dbD84aD465Ab0f98919eBB6d5C` | | SafeWebAuthnSignerFactory 0.2.1 | `0xfF25690FC38De1572c2C8075966Bb813f60a095F` | | Safe4337Module 0.3.0 (canonical address) | `0x75cf11467937ce3F2f357CE24ffc3DBF8fD5c226` | | SafeModuleSetup 0.3.0 (canonical address) | `0x2dd68b007B46fBe91B9A7c3EDa5A7a1063cB5b47` | The rest of the suite (SimulateTxAccessor, SafeToL2Setup, SafeToL2Migration, TokenCallbackHandler) is on [Contract addresses](https://docs.gullychain.xyz/contracts/#gully-safe-safe-141-and-passkeys). ## Passkey owners The Safe passkey modules are deployed, so a passkey can be a Safe owner: `SafeWebAuthnSignerFactory` creates a signer contract for a passkey's public key, and `SafeWebAuthnSharedSigner` lets a new Safe use a passkey owner from its first transaction. P-256 signatures verify through the RIP-7212 precompile (`0x…0100`, GullyChain runs ArbOS 51) with the Daimo verifier at `0xc2b78104907F722DABAc4C69f826a522B2754De4` as the fallback. ## Use Gully Safe from code With permissionless.js on viem, pass the Gully addresses: ```ts import { toSafeSmartAccount } from "permissionless/accounts"; const safe = await toSafeSmartAccount({ client: publicClient, // a viem client on chain 485590 owners: [owner], version: "1.4.1", entryPoint: { address: "0x0000000071727De22E5E9d8BAf0edAc6f37da032", version: "0.7" }, safeSingletonAddress: "0x76667330c237Fb40f28d74563cdAAae4b06C23Ec", // SafeL2 1.4.1 safeProxyFactoryAddress: "0xd9d2Ba03a7754250FDD71333F444636471CACBC4", multiSendAddress: "0x7B21BBDBdE8D01Df591fdc2dc0bE9956Dde1e16C", multiSendCallOnlyAddress: "0x32228dDEA8b9A2bd7f2d71A958fF241D79ca5eEC", safe4337ModuleAddress: "0x75cf11467937ce3F2f357CE24ffc3DBF8fD5c226", safeModuleSetupAddress: "0x2dd68b007B46fBe91B9A7c3EDa5A7a1063cB5b47", }); ``` Then use it with a smart account client on the [bundler and paymaster](https://docs.gullychain.xyz/account-abstraction/#endpoints), exactly like a Kernel account. Check the option names against the permissionless.js version you install. ## Not available yet - **Spending limits.** The Safe AllowanceModule is not deployed, so the spending-limit feature is off in the app. - **Canonical addresses.** If the Safe team deploys its singleton factory on GullyChain, the canonical addresses can be deployed next to these. Existing Gully Safes keep working at their addresses. # Gully Sentry: claim, run, check Source: https://docs.gullychain.xyz/sentry/ > Gully Sentry on GullyChain Testnet: claim a free Sentry Key with Gully ID or a wallet, start the watcher that checks every GullyChain assertion on Arbitrum Sepolia with one Docker command, connect it on the Run page and watch the live check. > [!LIVE] > **Live on testnet.** [sentry.gullychain.xyz](https://sentry.gullychain.xyz/) mints free testnet Sentry Keys. Testnet keys have **no monetary value**, cannot be bought or sold for money, and never convert into mainnet keys or tokens. There is no paid sale. > [!NOTE] > **In a hurry?** [Run a watcher in 5 minutes](https://docs.gullychain.xyz/sentry-watcher/) is the short version of this page, with a troubleshooting table. A Sentry Key is a licence to run the **Gully Sentry watcher**: a small program that reads every assertion GullyChain's validator posts to the rollup on Arbitrum Sepolia, compares it with GullyChain itself, and signs a heartbeat for each key every 10 minutes. A wrong block hash or send root is a mismatch: the watcher alerts (webhook or Telegram) and reports it. The flow is the same on the site and in the terminal: **claim** a key with Gully ID or a wallet, start the watcher with **one Docker command**, **connect** it to your key on [Run a sentry](https://sentry.gullychain.xyz/run/), and watch the **live check** turn green. ## 1. Claim a free key Open [sentry.gullychain.xyz](https://sentry.gullychain.xyz/) and press **Sign in with Gully ID**, then **Claim my free key**. - **With [Gully ID](https://docs.gullychain.xyz/gully-id/)** (recommended) the key goes to your **Gully Wallet**, the passkey wallet that comes with your Gully ID. You approve with your passkey: no extension, no gas. - **With a browser wallet** (Rabby, MetaMask), choose *or use a browser wallet instead*. You sign one message; Gully Labs pays the mint gas. Note your **key number** (for example `12`). The site shows it after the claim, and **Find my key** on [Run a sentry](https://sentry.gullychain.xyz/run/) looks it up again. | Rule | Why | |---|---| | One free key per Gully ID account | Enforced on-chain: the mint order id is bound to your Gully ID | | One free key per wallet | Enforced on-chain (`maxTotal = 1`) | | The wallet needs history: at least one transaction on GullyChain or Arbitrum Sepolia, or it is your Gully wallet | Same rule as the [faucet](https://faucet.gullychain.xyz/); stops throwaway-address farming | | Not offered in sanctioned regions | Compliance | Direct calls to the sale contract are refused (`NotEligible`): free keys only come through the site. ## 2. Start the watcher (one command) The watcher is one JavaScript file, served from the Sentry site with its SHA-256. It needs Docker (or Node.js 20+), about 100 MB of memory and no funds. Replace `` with your key number and run: ```sh docker run -d --restart unless-stopped --name gully-sentry -v gully-sentry:/data \ -e SENTRY_KEY_FILE=/data/operator.key \ -e SENTRY_KEY_CONTRACT=0xa24bF9f0eA1AE5F5226d8F7e714cEa3537aa30Ac -e SENTRY_TOKEN_IDS= \ node:22-alpine sh -c 'cd /data && ([ -f gully-sentry.mjs ] || (wget -qO g.mjs https://sentry.gullychain.xyz/downloads/gully-sentry.mjs && wget -qO- https://sentry.gullychain.xyz/downloads/gully-sentry.mjs.sha256 | sed "s/gully-sentry.mjs/g.mjs/" | sha256sum -c - && mv g.mjs gully-sentry.mjs)) && node gully-sentry.mjs init && exec node gully-sentry.mjs run' ``` It downloads the watcher once, checks its SHA-256 (nothing runs if it does not match), creates the watcher's own key and starts. `--restart unless-stopped` brings it back after a reboot. Then show the watcher's address: ```sh docker logs gully-sentry 2>&1 | grep "Operator address" ``` That **operator address** is a hot key that only signs heartbeats; your Sentry Key never leaves your wallet. No Docker? [Run a sentry](https://sentry.gullychain.xyz/run/) has the same one-line command for **Mac / Linux** and **Windows PowerShell** (Node.js 20+), with the checksum pinned in it. Use your own RPC for the strongest check: add `-e SENTRY_L3_RPC=https://rpc.gullyrpc.xyz//evm/485590` ([Gully RPC](https://gullyrpc.xyz/)) or the URL of your own Nitro node. ## 3. Connect it to your key On [Run a sentry](https://sentry.gullychain.xyz/run/), step 2, paste the operator address and press **Connect**. That is one approval from the wallet that holds the key: - **Gully Wallet:** approve with your passkey; gas is covered. - **Browser wallet:** one transaction that needs a tiny amount of free testnet gas from the [faucet](https://faucet.gullychain.xyz/). You can change or remove the operator at any time; it is cleared automatically if the key moves to another wallet. ## 4. Live check: your key and the chain 1. **Your key.** Step 3 on [Run a sentry](https://sentry.gullychain.xyz/run/) checks your key every 15 seconds and turns green with **Connected** at the first heartbeat (about 2 minutes after you connect). It shows the last heartbeat and its verdict (`ok`, `mismatch`, `stale` or `unreachable`); `docker logs -f gully-sentry` shows the same per heartbeat. The data is public JSON: `https://sentry.gullychain.xyz/api/v1/keys//status`. The [operator leaderboard](https://sentry.gullychain.xyz/#leaderboard) ranks keys by uptime over 24 hours and 7 days. 2. **The network.** The [network view](https://sentry.gullychain.xyz/network/) charts watchers online per 10-minute slot over 24 hours, the operators running them and the chain check. The live numbers also appear in the Sentry tab on [gullychain.xyz](https://gullychain.xyz/#sentry). 3. **The chain check.** `https://sentry.gullychain.xyz/api/v1/chain/health` compares the newest assertions on Arbitrum Sepolia with the collector's own GullyChain node. [status.gullylabs.xyz](https://status.gullylabs.xyz/) alerts when it is not `ok`, when the free mint closes, or when the free-minter wallet runs low. | Public endpoint | What it returns | |---|---| | `GET /api/v1/network/stats` | `activeKeys`, `operators`, verdict counts and the 24 h series (one heartbeat per key per slot) | | `GET /api/v1/sale/stats` | keys minted, supply left, phase (testnet: free tier, public) | | `GET /api/v1/chain/health` | `verdict`, a one-line summary, the L3 head and the age of the newest assertion | | `GET /api/v1/keys//status` | the last heartbeat of one key | ## Contracts (GullyChain Testnet, 485590) | Contract | Address | |---|---| | Gully Sentry Key, tGSK (ERC-721, soulbound until unlock) | `0xa24bF9f0eA1AE5F5226d8F7e714cEa3537aa30Ac` | | SentrySale (free tier only, KYC gate on for direct buys) | `0x8eef397b2A8cb66e71D5C931a102c8Be29b36595` | | SentryRewards (epoch Merkle distributor, no reward model live yet) | `0x2911b6A19350b72A158Af338729adDb5FeE29A21` | All three are verified on [verify.gullychain.xyz](https://verify.gullychain.xyz/). Rewards are not promised; see the [risk disclosure](https://sentry.gullychain.xyz/risk/). # Run a Gully Sentry watcher in 5 minutes Source: https://docs.gullychain.xyz/sentry-watcher/ > Quickstart for Gully Sentry on GullyChain Testnet: claim a free Sentry Key with Gully ID, start the watcher with one command, connect it to your key and watch it go live. > [!LIVE] > **Testnet.** Sentry Keys are free and have **no monetary value**. A running watcher puts your key on the public operator leaderboard and counts toward testnet XP and badges. Mainnet rewards are not decided, and nothing here promises any. Your sentry is a small program that checks every summary GullyChain posts to Arbitrum Sepolia (an *assertion*) against **your own view of the chain**, and signs a heartbeat for your key every 10 minutes. It needs Docker (or Node.js 20+), about 100 MB of memory and no funds. The full guide is [Gully Sentry: claim, run, check](https://docs.gullychain.xyz/sentry/). The fastest path is the site itself: [sentry.gullychain.xyz](https://sentry.gullychain.xyz/) walks you through the same three steps and checks the result live. This page is the same flow for the terminal. ## 1. Claim your free key (1 minute) Open [sentry.gullychain.xyz](https://sentry.gullychain.xyz/) and press **Sign in with Gully ID**, then **Claim my free key**. - **With Gully ID** your key goes to your **Gully Wallet**, the passkey wallet that comes with your Gully ID. You approve with your passkey: no extension, no gas. - **With a browser wallet** (Rabby, MetaMask), choose *or use a browser wallet instead*. You sign one message; Gully Labs pays the mint gas. Note your **key number** (for example `12`). The site shows it after the claim, and **Find my key** on [Run a sentry](https://sentry.gullychain.xyz/run/) looks it up again. ## 2. Start the watcher (one command) Replace `` with your key number and run: ```sh docker run -d --restart unless-stopped --name gully-sentry -v gully-sentry:/data \ -e SENTRY_KEY_FILE=/data/operator.key \ -e SENTRY_KEY_CONTRACT=0xa24bF9f0eA1AE5F5226d8F7e714cEa3537aa30Ac -e SENTRY_TOKEN_IDS= \ node:22-alpine sh -c 'cd /data && ([ -f gully-sentry.mjs ] || (wget -qO g.mjs https://sentry.gullychain.xyz/downloads/gully-sentry.mjs && wget -qO- https://sentry.gullychain.xyz/downloads/gully-sentry.mjs.sha256 | sed "s/gully-sentry.mjs/g.mjs/" | sha256sum -c - && mv g.mjs gully-sentry.mjs)) && node gully-sentry.mjs init && exec node gully-sentry.mjs run' ``` It downloads the watcher once, checks its SHA-256, creates the watcher's own key and starts. Then show the watcher's address: ```sh docker logs gully-sentry 2>&1 | grep "Operator address" ``` That **operator address** is a hot key that only signs heartbeats; your Sentry Key never leaves your wallet. `--restart unless-stopped` brings the watcher back after a reboot. No Docker? The [Run a sentry](https://sentry.gullychain.xyz/run/) page has the same one-line command for **Mac / Linux** and **Windows PowerShell** (Node.js 20+), with the checksum pinned in it. For the strongest check, point the watcher at a node you trust: add `-e SENTRY_L3_RPC=https://rpc.gullyrpc.xyz//evm/485590` ([Gully RPC](https://gullyrpc.xyz/)) or the URL of your own Nitro node. ## 3. Connect it to your key (1 minute) On [Run a sentry](https://sentry.gullychain.xyz/run/), step 2, paste the operator address and press **Connect**. That is one approval from the wallet that holds the key: - **Gully Wallet:** approve with your passkey; gas is covered. - **Browser wallet:** one transaction that needs a tiny amount of free testnet gas from the [faucet](https://faucet.gullychain.xyz/). You can change or remove the operator at any time; it is cleared automatically if the key moves to another wallet. ## 4. See it go live (about 2 minutes) - Step 3 on [Run a sentry](https://sentry.gullychain.xyz/run/) checks your key every 15 seconds and turns green with **Connected** at the first heartbeat. - `docker logs -f gully-sentry` shows each heartbeat and its verdict (`ok`, `mismatch`, `stale` or `unreachable`). - The [operator leaderboard](https://sentry.gullychain.xyz/#leaderboard) ranks keys by uptime over 24 hours and 7 days. It shows your `.gully` name if you have one, otherwise a short address. Uptime is the share of 10-minute slots in which your watcher sent a usable heartbeat. Keep the container running to stay near 100%. | Problem | Fix | |---|---| | `not operator for key(s)` in the logs | Step 3 is not done for this key yet, or the key moved to another wallet. Connect it again; the watcher retries every minute | | `sha256sum: WARNING: 1 computed checksum did NOT match` | The download was damaged or changed. Nothing ran; remove the container (`docker rm -f gully-sentry`) and start again | | The watcher runs but no heartbeat shows up | Your machine's clock may be off by more than 10 minutes (heartbeats are refused). Turn on network time | | Verdict `unreachable` | The watcher cannot reach GullyChain or Arbitrum Sepolia. Check the RPC URLs and your network | | Verdict `mismatch` | The chain disagrees with your node. The watcher has already reported it; tell us in [Telegram](https://t.me/GullyChain) | # .gully names Source: https://docs.gullychain.xyz/names/ > .gully names on GullyChain Testnet: readable names like alice.gully on ENS contracts, with forward and reverse resolution and free first-come registration. > [!LIVE] > **Live on testnet.** Register a `.gully` name in the GullyChain app at [app.gullychain.xyz](https://app.gullychain.xyz/). Testnet registration is free and first come, first served. `.gully` names give addresses a readable name, like `alice.gully`, that works across the chain: in wallets, in the explorer and in apps. They also serve as [referral codes](https://docs.gullychain.xyz/referrals/). ## Contracts `.gully` names use **ENS's own contracts** (`@ensdomains/ens-contracts`), deployed on GullyChain with `.gully` as the top-level name: | Contract | Role | Address | |---|---|---| | ENS registry | Records who owns each name and which resolver it uses. | `0xe0bE69254ce3916A38b2d266f6A7325e62e96576` | | Public resolver | Stores a name's records: its address, text records and content hash. | `0x9E8328918d40e45FBD40D422c854c554d6b45D37` | | Reverse registrar | Lets an address claim its primary name, so apps can show `alice.gully` instead of `0x…`. | `0xF9D030660E04bdBBC3F0818f7a1F4523bD5bA12F` | | `.gully` registrar | Hands out names under `.gully` (first come, first served on the testnet). | `0x3eb64A442EB656C66376A0458162a0b00093492B` | Because these are the standard ENS contracts, ENS-aware libraries resolve `.gully` names once they are pointed at the GullyChain registry. The simplest way is to call the registry and the resolver directly: ```ts import { namehash } from "viem/ens"; const REGISTRY = "0xe0bE69254ce3916A38b2d266f6A7325e62e96576"; const node = namehash("alice.gully"); const resolver = await client.readContract({ address: REGISTRY, abi: ensRegistryAbi, functionName: "resolver", args: [node] }); const addr = await client.readContract({ address: resolver, abi: publicResolverAbi, functionName: "addr", args: [node] }); ``` ## Testnet and mainnet registration - **Testnet:** registration is **first come, first served and free**, so developers can try names without friction. - **Mainnet:** a free first-come registrar invites squatting, so mainnet will use a **commit-reveal registrar with pricing and reserved names** before `.gully` opens. Names registered on the testnet do not carry over to mainnet. # Price oracle Source: https://docs.gullychain.xyz/oracle/ > Prices on GullyChain Testnet: the GullyPriceFeed RedStone pull feed for ETH, BTC and USDC with Chainlink-style adapters, how to read and update it, the /price/eth endpoint for USD display, and what changes before mainnet. > [!WARNING] > **Testnet only.** The feed verifies RedStone's signed price packages with RedStone's consumer code, which is licensed **BUSL-1.1** (non-production use). A production price source will be announced before mainnet. Do not secure real value with this feed. GullyChain has no push oracle yet. Parent-chain feeds (Chainlink, Pyth, API3 on Arbitrum Sepolia) cannot be read from an L3 contract in the same transaction, so the testnet runs **RedStone in pull mode**: the transaction that needs a price carries RedStone's signed packages in its calldata, and the contract verifies them on chain. ## Contracts | Contract | Address | |---|---| | GullyPriceFeed v1.0.0 (ETH, BTC, USDC) | `0x4c64c79ee59a83842a22c14712D66bfef48eb301` | | ETH / USD adapter (AggregatorV3-style) | `0x732b8a31E19827B6c81db7a433fd120e302862c8` | | BTC / USD adapter | `0xE7Df3ec99314C0716510DAcd5B61a089Cf95130c` | | USDC / USD adapter | `0x7cEbF1d241165302b9a0bc2CFD24020ACB7AE44e` | - Prices have **8 decimals**. Packages must come from RedStone's primary production data service, signed by at least **3 signers**, and be **at most 60 seconds** old. - Feed ids are `bytes32("ETH")`, `bytes32("BTC")` and `bytes32("USDC")`. ## Reading a price **Stored price.** `updatePrices()` verifies the packages in its calldata and stores them. Anyone can call it. `latestPrice(feedId)` returns the last stored `(value, timestamp, round)`, and each adapter exposes it as `latestRoundData()` for code written against Chainlink's `AggregatorV3Interface`. > [!NOTE] > Nobody updates the stored price on a schedule. It moves only when a transaction calls `updatePrices()`, so always check `updatedAt` (or use `priceIfFresh`) before you rely on it. **Fresh price in your transaction.** `livePrice(feedId)` verifies the packages appended to the current call and returns the price without storing it. `priceIfFresh(feedId, maxAge)` returns the stored price, or reverts `StalePrice` if it is older than `maxAge` seconds. From a browser or script, wrap the contract with RedStone's EVM connector so each call carries the packages: ```ts // @redstone-finance/evm-connector 0.9.0 (1.0.0 does not install from npm) import { WrapperBuilder } from "@redstone-finance/evm-connector"; const wrapped = WrapperBuilder.wrap(priceFeed).usingDataService({ dataServiceId: "redstone-primary-prod", uniqueSignersCount: 3, dataPackagesIds: ["ETH", "BTC", "USDC"], }); await wrapped.updatePrices(); // store fresh prices on chain const [value] = await wrapped.livePrice(ETH); // or read without storing ``` A contract that calls `livePrice` must pass the calldata suffix through, so it is simplest to have the user's transaction call `updatePrices()` first and then read `priceIfFresh`. ## USD prices for display Gully web apps show USD values with the same-origin endpoint **`/price/eth`** on gullychain.xyz: ```bash curl -s https://gullychain.xyz/price/eth # {"symbol":"ETH","usd":2344.08,"source":"coingecko","ts":1793146177} ``` It is the mainnet ETH price, cached, for display only. Test ETH has no value. See [RPC and indexer API](https://docs.gullychain.xyz/rpc-api/#price-endpoint). ## Real-world assets The TEST-TBILL demo asset has its own **mock NAV oracle** (AggregatorV3-style, 8 decimals) that accrues a fixed 4.5% a year. See [Real-world assets](https://docs.gullychain.xyz/rwa/). ## Before mainnet Consumers code against the AggregatorV3 adapters, so the source behind them can change without touching Gully Core or a lending market. The plan for mainnet: a licensed RedStone feed or a push feed from Chainlink or API3, a staleness bound, and a second source to compare against. # Stylus (Rust contracts) Source: https://docs.gullychain.xyz/stylus/ > Write GullyChain contracts in Rust with Arbitrum Stylus: install cargo-stylus, check and deploy against the GullyChain Testnet RPC, and call them with viem. **Stylus** is part of Arbitrum Nitro. It runs contracts compiled to WebAssembly next to the EVM, so you can write contracts in Rust (and other languages that compile to WASM). Stylus contracts and Solidity contracts can call each other, share the same state and use the same addresses and ABI. Stylus is built into ArbOS from version 32. GullyChain started at **ArbOS 51**, so Stylus is available on the testnet with nothing extra to enable. The ArbWasm precompile that activates Stylus programs is at `0x0000000000000000000000000000000000000071`. > [!NOTE] > Gully Labs has not yet published its own end-to-end Stylus example for this chain. The steps below are Arbitrum's standard `cargo-stylus` flow pointed at the GullyChain RPC. If something fails that works on Arbitrum Sepolia, tell us at [team@gullylabs.xyz](mailto:team@gullylabs.xyz). ## Set up You need Rust (via rustup), the WASM target, and `cargo-stylus`: ```sh rustup target add wasm32-unknown-unknown cargo install --force cargo-stylus ``` Docker is also needed for reproducible builds and for verification. ## Create a project ```sh cargo stylus new counter cd counter ``` This creates a small counter contract using the `stylus-sdk` crate. ## Check against GullyChain `cargo stylus check` builds the contract and asks the chain whether it would activate: size limits, allowed WASM features and the activation cost. ```sh cargo stylus check --endpoint https://rpc.gullychain.xyz ``` ## Deploy Deploying a Stylus contract is two transactions: one stores the WASM, one **activates** it through ArbWasm. `cargo stylus deploy` sends both. You need test ETH on GullyChain for gas and the activation fee (see [Quickstart](https://docs.gullychain.xyz/quickstart/#2-get-test-eth)). ```sh # estimate first cargo stylus deploy \ --endpoint https://rpc.gullychain.xyz \ --private-key-path ./key.txt \ --estimate-gas # then deploy and activate cargo stylus deploy \ --endpoint https://rpc.gullychain.xyz \ --private-key-path ./key.txt ``` Keep the key file outside the repo, and use a throwaway testnet key. The command prints the contract address; look it up on the [explorer](https://testnet-explorer.gullychain.xyz/). ## Call it A Stylus contract has a normal Solidity ABI. Export it and call the contract with any EVM tool: ```sh cargo stylus export-abi cast call
"number()(uint256)" --rpc-url https://rpc.gullychain.xyz cast send
"increment()" --rpc-url https://rpc.gullychain.xyz --account dev ``` ## Things to know - **Activation is per chain.** A program activated on Arbitrum Sepolia is not activated on GullyChain; deploy it here. - **Reactivation.** Activated programs expire after a period set by ArbOS (one year by default) and after some ArbOS upgrades, and then need `cargo stylus activate` again. Follow Arbitrum's Stylus docs for the current rules. - **The same Arbitrum rules apply.** `block.number` and gas behave as described on the [Network reference](https://docs.gullychain.xyz/network/). # Gully Social Source: https://docs.gullychain.xyz/social/ > Gully Social on GullyChain Testnet: on-chain profiles on .gully names, follows, posts, likes, invites, the verified badge paid through Gully Pay, and share cards for X. Public read API at social.gullychain.xyz. > [!LIVE] > **Live on testnet** in the [GullyChain app](https://app.gullychain.xyz/explore). The API is at `https://social.gullychain.xyz`. Gully Social is the social layer of the GullyChain app. Your profile is your wallet: the avatar, banner, bio and links are text records on your [.gully name](https://docs.gullychain.xyz/names/), so they live on chain. The social service stores only the social graph (follows, posts, likes) and the image files you upload. | | | |---|---| | App | [app.gullychain.xyz](https://app.gullychain.xyz/): Explore, the Following feed, Invites, Get verified | | API | `https://social.gullychain.xyz` (browser CORS: the app only; public reads work from any server) | | Health | `GET https://social.gullychain.xyz/healthz` | | Sign-in | a device key in the browser, authorised once by your wallet or passkey account. No invite code needed | | Verified badge | GullyVerified `0xE521eCfb4F0385f1eb674b26Cb504dCCA128B198` | ## What you can do - **Follow** people and read the Following feed, or browse everyone on Explore (most followed, newest, verified, points). - **Post** up to 280 characters with an image, reply and like. - **Invite** friends with your five codes. Invites earn points and the early badge; they never gate anything. - **Get verified**: post a code from your X account, pay through Gully Pay (card checkout, or x402 on GullyChain in ETH, WETH or USDC.e), and the attester signs your badge, which can be recorded on chain in GullyVerified. Payments go straight to Gully Pay's settlement address: the service and the contract never hold funds. - **Share** a profile or post on X: `app.gullychain.xyz/s//` serves a page with a 1200x630 card in the GullyChain kit. ## Public read API No key needed. Addresses are GullyChain accounts. | Request | Returns | |---|---| | `GET /v1/profiles/:address` | followers, following, posts, points, early, the active verified badge or `null` | | `POST /v1/profiles/batch` with `{ "addresses": [...] }` (up to 100) | `{ [address]: { followers, verified, early } }` | | `GET /v1/people?sort=followers&limit=50` | people for Explore (`sort`: `followers`, `new`, `verified`, `points`) | | `GET /v1/posts?author=&feed=&cursor=` | top-level posts, 30 a page (`feed=
`: who that address follows, plus itself) | | `GET /v1/posts/:id` | a post and its replies | | `GET /v1/verified/:address` | the badge, or 404 | | `GET /v1/verify/config` | badge plans, prices and accepted payment assets | ```sh curl -s "https://social.gullychain.xyz/v1/people?sort=followers&limit=5" ``` Writes (follow, post, like, upload, verify) need the app's signed device-key header, so build on the app or ask in [Support](https://docs.gullychain.xyz/support/) for an integration. ## Limits Posts: 20 an hour per account. Uploads: 30 an hour; avatar up to 1 MB and 1024 px a side, banner up to 2 MB, post images up to 2 MB and 2048 px (PNG, JPEG, WebP or GIF, checked from the file bytes). The service is on the [status board](https://status.gullylabs.xyz/). # Share links and embeds for creators Source: https://docs.gullychain.xyz/embeds/ > Share your GullyChain tracks, videos, Shorts, live streams, profile, quests and token launches with rich cards on X, Facebook, Instagram, WhatsApp, Telegram, TikTok and iMessage, and embed the player on your own site or link-in-bio. > [!LIVE] > **Live in the app.** Share cards, story images, the embeddable player and oEmbed work for tracks, videos, Shorts, live streams, profiles, posts, tokens and quests. Developers: the endpoints are also on the [developer portal](https://dev.gullychain.xyz/integrate/#embeds). Every share link has the form `https://app.gullychain.xyz/s//`. Paste it anywhere: link previews show a card with your avatar and name, the title, the cover art, a LIVE badge while you stream, and a QR code. When someone opens the link, the GullyChain app opens if they have it installed. Otherwise the web page opens. ## Share from the app Press **Share** on a track, video, Short, live stream, profile, post, quest or token page. The menu has these options: | Option | What happens | |---|---| | Share via… | Your phone's share sheet. On phones that can share files, the story image comes along, so Instagram and TikTok show up too | | Copy link | Copies your share link, with your referral code | | WhatsApp, Telegram, X, Facebook, Messages | Opens that app with the text and the link filled in | | Share to Stories | Saves the 1080x1920 story image and copies the link. Post the image to your Instagram or TikTok story and add a **link sticker** with the link | | Copy embed code | The ` ``` | Player | Size | |---|---| | `track` | 100% x 152 | | `video` | 640 x 360 | | `short` | 360 x 640 | | `live` | 640 x 360 | The player has a **Listen on Gully Chain** or **Watch on Gully Chain** link back to your page. Free titles play right in the embed. Members-only, rentals and collector titles show a button that opens Gully Chain, where people pay through Gully Pay. The player runs no trackers and loads only its own script. Any site may frame it. ### oEmbed Link-in-bio tools, Notion, WordPress and other CMSes that support oEmbed embed your links on their own. The endpoint: ``` GET https://app.gullychain.xyz/oembed?url=https://app.gullychain.xyz/track/TRACK_ID&maxwidth=600 ``` | Link type | oEmbed type | |---|---| | Tracks | `rich` | | Videos, Shorts and live streams | `video` | | Everything else | `link`, with the card as `thumbnail_url` | Share pages and app pages also announce the endpoint with ``. Only `format=json` is supported; `maxwidth` and `maxheight` size the player and the thumbnail. A URL that is not a Gully Chain item answers `404`. ## Share counts `GET https://social.gullychain.xyz/v1/share/counts?kind=track&id=TRACK_ID` returns (shape shown for an item nobody has shared yet): - how many times the item was shared, per network - how many people opened its share links, per `utm_source` ```json { "shares": 0, "visits": 0, "byNetwork": {}, "visitsBySource": {} } ``` To count a share from your own share button, `POST https://social.gullychain.xyz/v1/share/event` with `{"kind": "track", "id": "TRACK_ID", "network": "x"}`. Networks: `native`, `copy`, `x`, `facebook`, `whatsapp`, `telegram`, `instagram`, `tiktok`, `imessage`, `sms`, `story`, `embed`, `qr`, `other`. It is rate limited per IP (120 an hour). # Copy trading Source: https://docs.gullychain.xyz/copy-trading/ > Non-custodial copy trading on GullyChain Testnet: follow a leader, set per-trade and daily limits, and a revocable session key mirrors their trades from your wallet. 0.5% fee, 20% to the leader, capped on chain. > [!LIVE] > **Live on testnet** at [app.gullychain.xyz/copy](https://app.gullychain.xyz/copy). Testnet ETH only: nothing here has real value. Pick a trader from the leaderboard, choose one of your wallets, set your limits, and the app installs a **session key** on that wallet. The copy engine watches the leader's trades and mirrors each one into your wallet, within the limits the key's on-chain policy allows. The engine never holds funds. | | | |---|---| | App | [app.gullychain.xyz/copy](https://app.gullychain.xyz/copy): leaderboard, copy setup, My copies | | Engine API | `https://copy.gullychain.xyz` | | Health | `GET https://copy.gullychain.xyz/health` | | Fees | GullyCopyFees `0xA9d429eb1b137764B0d4964e437AF50989bdFea3` | | Wallets | up to 5 smart-account wallets per passkey ([Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/)) | > [!WARNING] > Copy trading can lose money, and past results are not a forecast. Copies run **after** the leader's trade lands, so you trade later and at a different price; the delay of every copy is shown in your copy log. The full text is at `GET https://copy.gullychain.xyz/disclosures`. ## How a copy runs 1. **Pick a leader.** Leaders are ranked from their real GullyChain trades: realised PnL, volume, win rate over closed positions. 2. **Pick a wallet** (same passkey, wallets #1 to #5). Trades, fees and gas come from that wallet only. 3. **Set your size and limits**: a fixed amount or a percentage of the leader's size, a cap per trade, a cap per day, an expiry. 4. **Confirm.** One passkey signature installs the session key; the engine copies the leader's next trade. 5. **Stop or revoke** any time. Stop erases the key on the engine; Revoke removes it from your wallet on chain at once. ## What the session key can and cannot do The limits are enforced on chain by the key's call policy and spend policy, not by the engine: - **Can:** buy and sell on the launchpad, swap on Gully Swap with your wallet as the recipient and listed tokens only, approve those venues, and pay the copy fee to the leader you picked. Each trade stays under your per-trade cap and each day under your daily cap. - **Cannot:** send ETH or tokens anywhere, approve anyone else, call any other contract, change your account, pay a different leader, sign messages as you, or act after expiry or after you revoke. ## Fees 0.5% of the copied ETH amount per trade, paid in the same operation as the trade, so a copy happens with its fee or not at all. 20% of each fee goes to the leader, who can claim it any time. The contract caps the fee at 1% and the leader share at 50%: no owner can go above them. A Gully Pay plan can later lower or waive the fee for a follower; it can never raise it. ## Engine API (public reads) | Request | Returns | |---|---| | `GET /leaders?limit=` | the leaderboard: trades, volume, realised PnL, win rate, followers, fees earned | | `GET /leaders/:address` | one leader | | `GET /copies?follower=
` | that follower's copies | | `GET /copies/:id/log?limit=` | a copy's log, with the delay of each copied trade | | `GET /disclosures` | the risk text the app shows before the first copy | ```sh curl -s "https://copy.gullychain.xyz/leaders?limit=10" ``` The engine is on the [status board](https://status.gullylabs.xyz/). # Quests Source: https://docs.gullychain.xyz/quests/ > Gully Quests on Gully Chain Testnet. On-chain quests that the chain verifies itself (names, launchpad trades, swaps, bridge deposits, arcade scores, referrals, token holdings), plus Quests v2 (multi-step quests, hold-for-time, quest chains, daily streaks, soulbound badges, the XP leaderboard), escrowed reward pools, a 5% funding fee and no stuck funds. > [!LIVE] > **Live on testnet since 2026-10-26, Quests v2 since 2026-10-27.** Complete quests in the GullyChain app at [app.gullychain.xyz/quests](https://app.gullychain.xyz/quests), create your own at [/quests/new](https://app.gullychain.xyz/quests/new), and see the XP ranking on the [leaderboard](https://app.gullychain.xyz/quests/leaderboard). Live totals: [indexer.gullychain.xyz/quests/stats](https://indexer.gullychain.xyz/quests/stats). Gully Quests is Gully Chain's built-in quest system, its answer to Layer3 and TaskOn. The difference: a server does not check your wallet. A contract checks the chain's own state when you call `complete(questId, proof)`. The completion is recorded on chain (`QuestCompleted(questId, account, blockNumber, evidence, reward)`), and the reward is paid from an escrowed pool in the same transaction. ## Seed quests The eight seed quests run until 2026-11-25; the app lists every open quest, including the ones other people created. Rewards are testnet tokens with no value. | # | Quest | Verified by | Reward per completion | Spots | |---|---|---|---|---| | 1 | Claim your .gully name | NameVerifier: your reverse record is a `.gully` name that resolves back to you | 0.0001 ETH | 4 | | 2 | First curve buy | LaunchpadTradeVerifier: you hold a token that the launchpad launched | 0.0001 ETH | 4 | | 3 | Bridge in from Arbitrum Sepolia | BridgeVerifier: an attested ETH deposit of at least 0.001 ETH | 0.0001 ETH | 4 | | 29 (replaces #4), **ended 2026-10-28** (glUSD retired; budget refunded) | Hold 0.5 glUSD for 10 blocks | HoldsTokenVerifier: press **Start clock** (a snapshot) while you hold 0.5 glUSD, keep it, then claim | 0.15 glUSD | 4 | | 5 | Make a swap on Gully Swap | SwapVerifier: the attest server finds your router `Swap` and signs it | 0.0001 ETH | 6 | | 6 | Score 50+ in Frog Hop | ArcadeScoreVerifier: your best score in the latest arcade season | 0.0001 ETH | 6 | | 7 | Refer a friend to Gully Chain | ReferralVerifier: at least one account has set you as its referrer | 0.0001 ETH | 6 | | 8 | Join the GullyChain Telegram | AttestedVerifier (`TELEGRAM_JOIN`): the Gully team signs it after checking you joined [t.me/GullyChain](https://t.me/GullyChain) | 0.0001 ETH | 6 | Quest #4 was created before the v1.1 fix (see [Block numbers](#block-numbers)). Its "10 blocks" are counted in L1 blocks, about two minutes. Quest #6 reads the *latest* arcade season. Season 1 ends on 2026-11-01. Season 2 (until 2026-12-01) opens right after it, and from then on the quest needs a season 2 score. Until it opens, season 1 scores still count. ## Quests v2 Quests v2 adds new verifiers and helpers **next to** the live v1 registry. `QuestRegistry` and `QuestEscrow` were not redeployed and no pool was touched. None of the v2 contracts holds funds or has an owner. | Feature | Contract (`kind`) | What it checks | |---|---|---| | **Multi-step quests** | `MultiStepVerifier` (`multi`) | 1 to 8 steps, each an allow-listed verifier with its own params; all must pass. `stepStatus()` returns per-step progress in one call, so the app shows a checklist | | **Hold for time** | `HoldVerifier` (`hold`) | balance ≥ x for n GullyChain blocks and/or t seconds. `snapshot(token)` is per account and token, so it works inside multi-step quests | | **Quest chains** | `QuestChainVerifier` (`quest-chain`) | completing quest A (all, or k of a list) unlocks this one | | **Daily streaks** | `GullyStreaks` (`streak`) | a daily `checkIn()` (UTC days); quests can require a current, best or total streak | | **Passkey step** | `AccountVerifier` (`account`) | the completer is a Kernel account with the Gully passkey validator (or any smart account) | | **Soulbound badges** | `QuestBadges` | an ERC-5192 soulbound ERC-721 you `claim(questId)` after completing it, with on-chain SVG metadata | | **One-click create** | `QuestBatchGuard` | lets a smart account create and fund a quest in one user operation | Params and proofs: - `multi`: params `abi.encode((address verifier, bytes params)[])`, proof `abi.encode(bytes[])` (one per step, or `0x` when no step needs one). - `hold`: `(address token, uint256 minBalance, uint32 minBlocks, uint32 minSeconds)`. - `quest-chain`: `(uint256[] questIds, uint8 minCount)`, where 0 means all. - `streak`: `(uint8 metric, uint32 min)`, with metric 0 current, 1 best, 2 total days. - `account`: `(uint8 mode)`, 1 for a passkey Kernel account, 2 for any smart account. HoldsTokenVerifier v1 cannot be a step. The attest server signs one attested step of a multi-step quest with `POST /attest { questId, account, step }`. **XP and the leaderboard.** The [quest leaderboard](https://app.gullychain.xyz/quests/leaderboard) ranks accounts by XP from on-chain quest completions, daily check-in streaks and soulbound badges, season by season, all read from the chain. Apps can read the same reputation through the `reputation` claim of [Gully ID](https://docs.gullychain.xyz/gully-id/). ## How a quest works 1. **Create.** Anyone can call `createQuest`. It takes a title, a metadata URI, a start and end time, the maximum number of completions, the reward asset (ETH, USDC.e or WETH; glUSD is no longer allowed), the amount per completion, a **verifier** with its parameters, and an optional reputation gate. 2. **Fund.** The creator, or any sponsor, adds to the pool with `fund` (ETH) or `fundERC20`. **5% of each deposit goes to the Gully treasury.** The other 95% is the quest's pool, held by `QuestEscrow`. 3. **Do it.** On Gully Chain, the user claims a name, buys a launchpad token, swaps, bridges, plays, refers or holds. 4. **Verify.** The app calls `canComplete(questId, account, proof)`, a free read. It shows the exact proof the contract will check and the `evidence` the verifier returns (a name node, a token, a transaction hash). If the check fails, `reason` says why: 1 quest not active, 2 outside the window, 3 already completed, 4 full, 5 reputation gate, 6 verifier said no, 7 pool empty. 5. **Claim.** The user calls `complete(questId, proof)` from their own account (an EOA or a passkey smart account). The registry records the completion and pays the reward. Each account can complete a quest once. ## Verifier types | Verifier (`kind`) | Proves | `params` (abi-encoded) | `proof` | |---|---|---|---| | `NameVerifier` (`name`) | the account has a verified primary `.gully` name | none | `0x` | | `HoldsTokenVerifier` (`holds-token`) | balance ≥ x for ≥ n Gully Chain blocks | `(address token, uint256 minBalance, uint32 minBlocks)` | `0x`. Call `snapshot(questId)` first when `minBlocks` > 0 | | `LaunchpadTradeVerifier` (`launchpad-trade`) | bought (holds a launchpad token) or sold on the curve | `(address launchpad or 0, address token or 0, uint8 side: 0 buy / 1 sell, uint256 minAmount)` | `(launchpad, token, attestation)`. The attestation is empty for buys | | `SwapVerifier` (`swap`) | swapped on Gully Swap (pair and minimum amount) | `(address tokenIn or 0, address tokenOut or 0, uint256 minAmountIn)` | attestation | | `BridgeVerifier` (`bridge`) | deposited ETH from the parent chain | `(uint256 sourceChainId, address token: 0 = ETH, uint256 minAmount)` | attestation. Evidence is the deposit's Gully Chain transaction (`ArbitrumDepositTx`) | | `ArcadeScoreVerifier` (`arcade-score`) | best score ≥ x | `(uint256 gameId, uint256 seasonId: 0 = latest, uint256 minScore)` | `0x` | | `ReferralVerifier` (`referral`) | was referred / referred ≥ n / registered as a referrer | `(uint8 mode: 0 / 1 / 2, uint256 n)` | `0x` | | `AttestedVerifier` (`attested`) | an action the chain cannot see (a Telegram join, a follow, a signup) | `(bytes32 kind, uint256 minValue)` | attestation | When the chain keeps state about an action, the verifier reads that state and nobody has to be trusted. Some actions leave no state: router swaps and launchpad sells exist only as events, a bridge deposit arrives as a special transaction, and a Telegram join happens off chain. For those, the **Gully attest server** signs an EIP-712 attestation from the indexer, the chain's blocks or, for Telegram, the Bot API. The contract still checks the quest id, the account, the action kind (bound to the quest's parameters), the minimum value, the expiry and the attester address. One signature fits one quest, one account and one action. The attester key holds no funds and can be rotated per verifier. Contract addresses are listed [below](#contracts). ## Fees - **5% of every deposit** goes to the treasury, taken when the pool is funded. Creating, completing, claiming and refunds cost nothing beyond gas. - Example: funding 0.0005 ETH gives a 0.000475 ETH pool, enough for four completions at 0.0001 ETH. The create form shows the fee, the net pool and how many completions it covers before you sign. - The owner can change the fee for future deposits, up to 10%. Pools that are already funded are never touched. ## Create a quest In the app, go to [app.gullychain.xyz/quests/new](https://app.gullychain.xyz/quests/new) and follow the steps: choose a verifier, fill in its parameters, set the window, the reward and the number of spots, then sign `createQuest` and `fund`. From a contract or a script: ```solidity QuestRegistry.QuestInput memory q = QuestRegistry.QuestInput({ title: "Hold 100 FROG for 50 blocks", metadataURI: "https://example.com/quest.json", start: uint64(block.timestamp), end: uint64(block.timestamp + 14 days), // at most 365 days maxCompletions: 20, rewardAsset: address(0), // ETH; or USDC.e / WETH rewardAmount: 0.0001 ether, // per completion verifier: HOLDS_TOKEN_VERIFIER, // an allow-listed verifier (table below) params: abi.encode(FROG, 100e18, uint32(50)), requiredReputation: 0, // 1 = .gully name, 2 = account age, 3 = both minAccountAgeBlocks: 0, mode: QuestRegistry.RewardMode.Direct // or Merkle for large pools }); uint256 id = registry.createQuest(q); registry.fund{value: 0.0021 ether}(id); // 5% fee -> 0.001995 ETH pool = 19 completions ``` - Approve `QuestEscrow` before calling `fundERC20`. - Completions revert with `PoolEmpty` while the pool is short, so fund at least one reward. Anyone can top up a pool until the quest ends. - Creators can pause and unpause their quest, cancel it (whatever is left is refunded at once), and withdraw unclaimed rewards after the end. If the pool is already empty (never funded, or fully paid out), a creator's cancel reverts `NothingToRefund`. The quest then just ends at its end time. To delist it sooner, ask the Gully team: the platform owner can cancel an empty quest. ## Reputation gate A quest can require: - flag `1`: a verified `.gully` name; - flag `2`: a minimum account age; - `3`: both. Account age is counted in **Gully Chain blocks** since the account's first transaction. The attest server signs that first-seen block (`GET /age/:account`), and anyone can relay it to `GullyReputation.attestAge`. The stored block can only move earlier, so it can never make an account look younger. Gully Chain produces blocks only when there are transactions (see [Network reference](https://docs.gullychain.xyz/network/#blocks-are-made-only-when-there-are-transactions)), so an age in blocks measures chain activity since the account appeared, not days. ## Block numbers Inside a contract on Gully Chain, `block.number` is an L1 block number: about 12 M, the Ethereum Sepolia height on the testnet. It is not the Gully Chain block (see [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number)). - **Quest windows** use timestamps. - **Reputation and holding quests** count Gully Chain blocks with `ArbSys(0x64).arbBlockNumber()` since **v1.1 (2026-10-26)**. In v1.0, the age gate compared an L1 number with a Gully Chain number, so every attested account passed any age below about 12 M blocks. No live quest used that gate. The fixed `GullyReputation` and `HoldsTokenVerifier` were deployed, the attested ages were migrated, and the registry now points at the new reputation contract. No pool was touched. - **The completion record** (`completedAt` and `QuestCompleted.blockNumber`) stores `block.number`, so it holds an L1 number. The registry holds the pools and cannot be upgraded, so this stays as it is. The indexer and the app show the Gully Chain block and time of the completion transaction. ## Security and trust - **No stuck funds.** For every quest, the escrow holds exactly `pool - paid`. If a creator disappears, anyone can trigger the refund 180 days after the end, and it still goes to the creator. If an ETH reward transfer fails, the reward is credited for a pull claim (`claimOwed`) so the quest is not blocked. - **The platform cannot touch a pool.** The owner can allow verifiers and reward assets, set the fee and treasury, pause new activity and cancel an abusive quest (the refund goes to its creator). There is no sweep and no upgrade path, and the escrow has no owner at all. - **What a global pause stops.** A global pause stops creating, funding, completing and Merkle claims. Creator pause and cancel, withdrawals and `claimOwed` keep working. The 30-day Merkle claim window keeps running during a pause, so the owner keeps any pause well under 30 days while a Merkle quest is in its window. - **Sybil resistance.** Each account can complete a quest once, and a quest can add the reputation gate. Holding quests check the balance at both ends, so a flash-loaned balance cannot pass. - **Large pools.** In Merkle mode, completions are recorded on chain and the creator posts a reward tree after the end. Claims are guaranteed for 30 days before the creator can withdraw the rest. ## Contracts | Contract | Address | |---|---| | QuestRegistry v1.0 | `0xE3E57e15A9973281A8de2B3bedd512BE8C3813Bb` | | QuestEscrow | `0xbAcaB79c8F22cA82eeC6ee2D6200Fb9FBc7EcEfD` | | GullyReputation v1.1 | `0x723243B39F5ff4b5414dcD0d0A8Ad62E4c412dAd` | | NameVerifier | `0xc75C16B242863F26F6b2f8b3C9921C072fF6300B` | | HoldsTokenVerifier v1.1 | `0xc44a3348D5438CD6352a662c75b1456e10137458` | | LaunchpadTradeVerifier | `0x1E0EE16cAe7FFf805b8e1aE28D647595b4E40aa5` | | SwapVerifier | `0x9E251d2acb4ef6597f9feFC7d2e1C9832DE6b1c1` | | BridgeVerifier | `0x6ACAcFc6eD2c70f0114a3203CEFBD54A68CceB2B` | | ArcadeScoreVerifier | `0x6c8e6C29333A8ece85B819F501Af5D160637F0d4` | | ReferralVerifier | `0xa25671A565dDd0cb1DdEe6664209b752Fd0f9593` | | AttestedVerifier | `0x71295ef91ddBd5C174BBA3D9144a7cCDb3662443` | | MultiStepVerifier (v2) | `0xf73B4aB8fD4AB8e153098cFB9eb92f3148F4AB47` | | HoldVerifier (v2) | `0xFf7c0ec7B6cf95937A6EA88f8552cd61f8D5de12` | | QuestChainVerifier (v2) | `0xF54fd7560645Ae838b1ff01357728DC333bb1175` | | GullyStreaks (v2, daily check-in and `streak` verifier) | `0xDb2A958fcf05C020aaE724Adc557Ddf8EF4288fB` | | AccountVerifier (v2, passkey account) | `0xcDd185F0B46e6bae70Ce04d0a815DF49a58879F9` | | QuestBadges (v2, soulbound ERC-5192) | `0xEAfFB05b1aD22659918A3fcF28EB566464EB8B06` | | QuestBatchGuard (v2) | `0x017f76909C7Cec5b6334ceC7F6FfbBA14fD3Ff4c` | | HoldsTokenVerifier v1.0 (retired; quest #4 only, cancelled and superseded by #29) | `0xc355Cc217A838bC8E09e048b7857A3811FB38EAC` | | GullyReputation v1.0 (retired) | `0x2cd00C780AD9E395d79130aAdc6306a058B43120` | Source: `gully-labs/gully-quests` (Foundry, solc 0.8.28, OpenZeppelin 5.6.1). ## For builders A verifier implements one interface: ```solidity interface IQuestVerifier { function verify(uint256 questId, address account, bytes calldata params, bytes calldata proof) external view returns (bool ok, bytes32 evidence); function validateParams(bytes calldata params) external view returns (bool); function kind() external pure returns (string memory); } ``` Once the owner allow-lists a verifier, any Gully contract (a game, a market, a DAO) can have its own quest type. - Useful reads: `quest(id)`, `questParams(id)`, `available(id)`, `completedAt(id, account)`, `canComplete(id, account, proof)`. - Indexer routes: `/quests`, `/quests/:id`, `/quests/:id/completions`, `/accounts/:a/quests`, `/quests/stats`, `/quests/trending`, `/quests/leaderboard`, `/quests/:id/analytics`, `/accounts/:a/xp`, `/streaks/:a`, `/badges/:a` (see [RPC and indexer API](https://docs.gullychain.xyz/rpc-api/#indexer-api)). To get a verifier allow-listed, write to [team@gullylabs.xyz](mailto:team@gullylabs.xyz). # Gully Offerwall Source: https://docs.gullychain.xyz/offerwall/ > Gully Offerwall on GullyChain Testnet: advertisers fund quests through Gully Pay, players earn USDC or points in games and apps, publishers embed the wall and earn a share of every completion. > [!LIVE] > **Live on testnet** at [offers.gullychain.xyz](https://offers.gullychain.xyz/). Campaign checkout through Gully Pay is rolling out: until the Offerwall store is connected, the dashboard shows "Gully Pay checkout is not set up yet" instead of a payment link. The Offerwall is a marketplace on top of [Quests](https://docs.gullychain.xyz/quests/). **Advertisers** (games, protocols, Gully's own apps) fund offers such as "reach level 5", "bridge to GullyChain" or "follow on X". **Players** complete them and earn USDC (USDC.e on Gully Chain) on web and PC, or points on mobile. **Publishers** show the wall on their site or in their game and earn a share of every completion. | | | |---|---| | Site, dashboard, widget | [offers.gullychain.xyz](https://offers.gullychain.xyz/) | | Integration guide | [offers.gullychain.xyz/integrate](https://offers.gullychain.xyz/integrate) | | Sign-in | [Gully ID](https://docs.gullychain.xyz/gully-id/) (client `gully-offerwall`), open to everyone | | Payments | Gully Pay hosted checkout (USD), webhook `checkout.session.completed` | | Public stats | `GET https://offers.gullychain.xyz/v1/stats` (completions and USDC.e paid per hour, last 24 h) | | Health | `GET https://offers.gullychain.xyz/healthz` | ## How a campaign runs 1. **Create the offer** in the dashboard: type (game milestone by postback, on-chain action, social), reward, number of completions, end date. The quote shows the reward, the publisher share and the fees before you pay. 2. **Pay with Gully Pay.** Gully Pay confirms the payment with a signed webhook; the API checks the amount and dedupes the event. 3. **Escrowed on Quests.** The operator calls `OfferwallManager.open`, which pulls the budget in USDC.e and creates the quest on the QuestRegistry with the manager as its creator. 4. **Players complete it.** Completions are attested by the Offerwall's own `AttestedVerifier`; crypto rewards are claimed on the registry, points go to the publisher's callback. 5. **Unspent budget returns.** At the end, or when you cancel, `release` sends everything the campaign no longer needs back to your Gully Chain account. Refunds can never get stuck in the manager. Fees: the Quests protocol fee (5%) and the Offerwall service fee (10%). Publishers earn 25% of the reward of every completion on their placement. ## Add the wall to a site or web game Create a placement in the dashboard (list the origins allowed to frame it), then paste its snippet: ```html
``` The frame is served from offers.gullychain.xyz with `Content-Security-Policy: frame-ancestors` limited to your placement's origins; every other Offerwall page refuses to be framed. Options: `data-mode="modal"` with `GullyOfferwall.open()`, `data-theme` to override the kit colours. iOS and Android placements never show crypto actions: players earn points instead. ## Report game events (postbacks) Game milestones are reported by your **server**, never by the client: ```text POST https://offers.gullychain.xyz/v1/postback X-Gully-Key: pbk_… X-Gully-Timestamp: X-Gully-Nonce: <16-64 chars, never reused> X-Gully-Signature: hex HMAC-SHA256(secret, timestamp + "." + nonce + "." + rawBody) { "clickId": "clk_…", "event": "level_reached", "value": 5 } ``` Unity games use the Offerwall module of the Gully Game SDK (`GullyOfferwallClient`), with a Nakama postback hook. Points rewards arrive at your placement's callback URL, signed with your placement secret `sk_…`; grant once per `completionId`. ## Contracts (GullyChain Testnet, 485590) | Contract | Address | |---|---| | OfferwallManager (campaign budgets, publisher shares, refunds) | `0xD6a8c4151a7ED9865a540D20BDD42073DC9c74Bf` | | AttestedVerifier (the Offerwall's attester, allowed on the QuestRegistry) | `0x68bcaA36c3c2fA4cF6c7D51A2Ac21abfFDF93338` | | QuestRegistry (Gully Quests) | `0xE3E57e15A9973281A8de2B3bedd512BE8C3813Bb` | | Operator (hot key: opens, tops up, settles, releases; moves money only along those paths) | `0x4366C5dBEcA628A97A3965470507A1fa38D4783D` | The service and the operator wallet are on the [status board](https://status.gullylabs.xyz/). # Arcade Source: https://docs.gullychain.xyz/arcade/ > Gully Arcade on GullyChain Testnet: free-to-play games with on-chain leaderboards, attested scores, sponsor-funded prize pots and seasons. Frog Hop is live. > [!LIVE] > **Live on testnet.** The GullyArcade contract is deployed and **Frog Hop season 1** is open. Play it in the GullyChain app at [app.gullychain.xyz/arcade](https://app.gullychain.xyz/arcade). Gully Arcade is a set of free-to-play games whose leaderboards live on GullyChain. Scores are submitted on chain, seasons have prize pots that anyone can sponsor, and winners claim their prizes themselves. | Contract | Address | |---|---| | GullyArcade v1.0 | `0xe573789b235314661DEdDA08a18Ca261c069c872` | ## How it works - **No paid entry, ever.** Playing and submitting a score costs only gas, which is sponsored when the player uses a [smart account](https://docs.gullychain.xyz/account-abstraction/). `submitScore` is not payable and there is no stake, ticket or entry fee anywhere. The arcade is a free contest, not a game of chance with a buy-in. - **Scores are attested.** A score needs an EIP-712 signature from the season's attestation signer, a small server that replays the run from its seed and input log with the same engine the game runs in the browser. Only the player's best score counts, and each run can be submitted once. - **Prizes come from sponsors.** Anyone can add ETH (`fundSeason`) or an allow-listed ERC-20 (`fundSeasonERC20`) to a season's pot while the season is open. - **Settlement is public.** After the season ends, anyone calls `settleSeason`. The pot is split over the top players by a split fixed when the season was created, and each winner pulls their prize with `claim`. Anything not paid out (unfilled ranks, rounding) goes back to sponsors pro rata. - **The owner can never move funds.** There is no withdraw, sweep, fee or upgrade path. The owner can create seasons, pause score submission and funding, allow prize tokens, and cancel a season **only before it ends** (for example if a signer key leaks), in which case the whole pot is refundable to sponsors. Final results cannot be overturned. ## Frog Hop, season 1 | | | |---|---| | Game ID | 1 | | Season ID | 1 | | Runs | 7 days from 2026-10-25 | | Prize split | top 5: 40% / 25% / 15% / 10% / 10% | | Pot | ETH, plus any allow-listed token a sponsor adds | Prizes are testnet tokens with no value. Seasons of one game never overlap and last at most 90 days. ## For builders The contract is open and any game can be added as a new game ID with its own seasons and attestation signer. Useful views: `leaderboard(seasonId)` (top N, best first), `season(seasonId)`, `pot(seasonId, token)`, `bestScore(seasonId, player)` and `latestSeasonOf(gameId)`. Events: `SeasonCreated`, `SeasonFunded`, `ScoreSubmitted`, `LeaderboardUpdated`, `SeasonSettled`, `PrizeAwarded`, `PrizeClaimed`, `RefundClaimed`, `SeasonCancelled`. Season start and end are **timestamps**, not block numbers, because `block.number` on GullyChain is the parent chain's block number (see [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number)). To propose a game for the arcade, write to [team@gullylabs.xyz](mailto:team@gullylabs.xyz). # Referrals Source: https://docs.gullychain.xyz/referrals/ > GullyChain referrals: an on-chain referral registry, 20% of platform fees paid to referrers in WETH for 180 days via weekly Merkle roots, .gully names as codes. > [!LIVE] > **Live on testnet.** The referral registry and the rewards distributor are deployed. Referral links work in the GullyChain app at `https://app.gullychain.xyz/r/` or `/r/0x…`. Referrals on GullyChain are **on chain**: who referred whom is recorded in a registry, and rewards are paid from the platform fees the referred users actually generate. | Contract | Address | |---|---| | GullyReferrals (registry) | `0x42B46EA814024683B346cCEAc2124A054F4544b7` | | GullyRewardsDistributor (rewards) | `0x1F299b4EDecf58749f6f51Fab663a2509C6D11C6` | ## The deal | | | |---|---| | Reward | **20%** of the platform fees paid by the users you referred | | Which fees | Launchpad trade fees and Gully Swap interface fees | | For how long | **180 days** after each referral | | Paid in | WETH (claim as ETH if you like), every **7-day epoch** | | Points | Shown in the app as a running score. **No token is promised for points.** | Rewards on the testnet are testnet ETH with no value. ## Registry rules - One referrer per user, set once and never changed (`setReferrer(address)`). - No self-referral and no two-way loops (A refers B while B referred A). - A referrer must be **registered**: it has sent at least one transaction to the registry (`register()`, or its own `setReferrer`). The app does this when you open "Activate my link". Referred users are registered automatically. - `setReferrerFor(user, referrer, deadline, signature)` lets a relayer or the paymaster pay the gas: the user signs an EIP-712 message (smart accounts sign through ERC-1271). - The registry has no owner, no pause and no upgrade path. A referral code is a `.gully` name or an address. The app resolves the name through the [.gully resolver](https://docs.gullychain.xyz/names/) and calls `setReferrer`. ## How rewards are paid 1. Every epoch, an off-chain job reads the chain's fee events, works out each referrer's share and builds a Merkle tree of **cumulative** rewards per address. 2. The root is posted to the distributor with a delay (currently one day) before it becomes active, so a bad root can be cancelled before anyone claims from it. 3. Referrers call `claim` (or `claimTo` to receive ETH) with their proof. Because amounts are cumulative, one claim always collects everything owed so far. The distributor is funded by the treasury in WETH. The owner can pause claims, change the poster and sweep **surplus only**, never what is owed under the active root. ## Sybil and minimum activity Rewards are only one level deep, so chains of referrals earn nothing extra. Minimum activity and sybil checks run off chain in the epoch job; addresses that fail them are left out of the tree. # Real-world assets Source: https://docs.gullychain.xyz/rwa/ > ERC-3643 (T-REX) and ONCHAINID compliance rails on GullyChain Testnet: identity, claims, transfer rules and a token factory for licensed asset issuers. > [!LIVE] > **Testnet rails live.** The ERC-3643 suite, ONCHAINID and Gully's compliance modules are deployed on GullyChain Testnet, with one demo asset, **TEST-TBILL**. > [!WARNING] > **Gully Labs does not issue securities.** GullyChain provides compliance rails that **licensed issuers** use to issue and run their own tokens. TEST-TBILL is a test asset with no value, no underlying asset and no redemption rights. Nothing on this page is an offer or solicitation of securities, and nothing here is legal advice. ## What the rails are GullyChain runs the reference implementation of **ERC-3643** (T-REX 4.1.3, the permissioned-token standard used for tokenized securities) together with **ONCHAINID** identities, both GPL-3.0. On top, Gully adds three compliance modules written from scratch: | Piece | What it does | |---|---| | **TREXFactory and TREXGateway** | An approved issuer deploys a complete token suite (token, identity registry, compliance, claim and trusted-issuer registries) in one transaction, with CREATE2. | | **ONCHAINID** | Each investor has an on-chain identity holding signed claims (for example "KYC passed" from a claim issuer). The self-service gateway lets a wallet create its own identity. | | **Compliance modules** | Country deny and allow lists, maximum balance per investor, maximum number of holders. Immutable and ownerless; each issuer configures them for its own token. | | **Claim topics** | 1 = KYC, 2 = AML, 3 = qualified investor. | Gully holds **no agent or owner power** over an issuer's token. An issuer can move its token to its own implementation authority through the `IAFactory`, after which only the issuer decides on upgrades. ## Contracts | Contract | Address | |---|---| | TREXFactory | `0x0FF2771EC18fC9dbDb7d3B231a94D13b68b7e4f1` | | TREXGateway | `0xA4682fA7Ef1E787a38229ab378CD7cA16f1839D4` | | TREX implementation authority | `0xA1F8855EdcE9069953877AE7ECA0398179eb87af` | | IAFactory | `0xB558a2F403eE13582440Fb794334B5EFfb63eE34` | | ONCHAINID IdFactory | `0x81fF68AD45723351A577725BC4145524313AC422` | | ONCHAINID Gateway | `0xd79BCA8D5a3f1046bC0Cb48884B842d17C91b512` | | Country module | `0x2Fd0347270F9df26cB242b3825B02229c68fEa5D` | | Max balance module | `0xA810EEE1E8E393fb79F305AA69d1006C419883dC` | | Max holders module | `0xfB9b8dc234f2362e5337f31c420856953eF9B6Cc` | | Gully testnet KYC claim issuer | `0x34291C44d75FeeEd27d875e32159E2d5B268F6e1` | The testnet KYC claim issuer is **manual**: there is no KYC provider behind it. Gully signs a KYC claim for tester wallets on request so the demo flow can be tried. It must not be read as a verification of anyone. ## TEST-TBILL, the demo asset "Gully Test Treasury Bill (testnet, no value)", 6 decimals. It shows the full flow: an investor creates an ONCHAINID, gets a KYC claim, is registered with a country, and can then receive and transfer the token within the rules. | Contract | Address | |---|---| | TEST-TBILL token | `0x7644b56E58e06471C2767FD4291fFB995deE06f6` | | Identity registry | `0xC92560D047A7ee4A455aD197D2481DD773756016` | | Compliance | `0x6234dfc53BcBBE037894a280E1BF88162b485be0` | | Mock NAV oracle (AggregatorV3-style, 8 decimals) | `0xB9f178D2DC79350245c11CA3Cd01b1eAF2315b55` | | Subscription desk (free test units) | `0x227AC9bEF3E57F8B351094ab8110B41F919491F9` | Rules on the demo token: required claim topic KYC (1), a country deny list, a maximum balance per investor of 100,000 units, at most 10,000 holders, and at most 10,000 units per subscription. The NAV is a mock that starts at 1.00 and accrues a fixed 4.5% per year. None of it has value. ## For issuers If you are a licensed issuer or transfer agent and want to run a token on GullyChain, the **issuer guide** covers what you deploy, how identity claims and agents work, the modules you can attach, bridging and the KYC-provider options. Write to [team@gullylabs.xyz](mailto:team@gullylabs.xyz) and we will send the guide and get your wallet approved on the gateway for a testnet run. Two technical notes: - Compliance that depends on time (lock-ups, holding periods) must use **timestamps**: `block.number` on GullyChain is the parent chain's block number (see [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number)). - The ERC-3643 and ONCHAINID contracts are GPL-3.0; their verified sources are on the explorer. ## What comes next - A vetted list of KYC claim issuers that issuers can choose to trust (none integrated yet). - Issuer-approved bridge routes for permissioned tokens. - Mainnet, only with issuers that hold the licences they need, and after counsel has reviewed the rails. # Gully Core launchpad and DEX Source: https://docs.gullychain.xyz/gully-core/ > Gully Core is Gully Chain's launchpad and DEX core, live on testnet. Launch a token in one transaction with liquidity locked forever, anti-snipe opening fees and an optional creator tax. Every fee number on this page is read from the contracts on chain, plus all 44 contract addresses. **Gully Core** is Gully Chain's own launchpad and DEX core, built by Gully Labs. It is **live on Gully Chain Testnet** (chain 485590) and it is where every new token launches and trades. > [!LIVE] > **New launches use Gully Core.** The earlier Gully launchpads (v1.0, v2.0, v2.1 and v3 with its fair launch) are > **legacy**: their tokens keep trading and their lockers keep paying fees, but nothing new launches there. They stay > listed on [Contract addresses](https://docs.gullychain.xyz/contracts/#legacy-launchpads) with status `deprecated`. {{gc-live}} ## How it works 1. **You launch in one transaction.** Pick a name, a symbol and a picture, choose how much of the supply goes into the pool, and send one transaction with the {{gc launchFee}} launch fee. The token is created, its pool opens and it can be traded from the very first block. You can add your own first buy to the same transaction, so nobody gets in before you. 2. **The liquidity is locked forever.** The tokens put into the pool are locked by the Gully Core lockers. Nobody, not you, not Gully Labs, can ever pull them out. There is no bonding curve to fill and no migration later: the pool you launch on is the real pool. 3. **Snipers pay an opening fee.** For the first minute every trade pays a higher fee (on our launchpad 50%) that falls second by second to the normal 0.3% fee. A bot that buys in the first second pays the most. That fee is not lost: it goes to the people behind the launch, so **most of it comes back to you, the creator**. 4. **You can add a creator tax, if you want.** An optional fee on buys and sells, at most {{gc taxMax}}, that **ends on its own** (at most {{gc taxMaxDuration}} after launch). It is fixed before the first trade and can never be raised. 5. **You earn from every trade.** The trading fee is split between you and the protocol (on our launchpad you keep 75%). Your share collects in the lockers and the launch guard, and you claim it whenever you like. 6. **Everyone trades through the Gully Core DEX.** Swaps run through one shared Vault and router, the same core every launchpad and DEX on Gully Chain uses. ## Fees in plain words | What | How much | Who gets it | |---|---|---| | Launch fee, once per launch | **{{gc launchFee}}** | Gully Core (the protocol). Can never be more than {{gc maxLaunchFee}}, and a rise must be announced {{gc launchFeeNotice}} ahead. | | Opening fee (anti-snipe) | on our launchpad 50%, falling to 0.3% over 60 seconds (the contracts allow up to {{gc guardMaxInitial}}) | the launch: you, the protocol and an optional partner app, by the launch's split | | Normal trading fee after the opening | **0.3%** on our launchpad (never more than {{gc guardMaxFinal}}) | same split as above | | Creator tax (optional) | up to **{{gc taxMax}}** on buys and sells, ends by itself within {{gc taxMaxDuration}} | mostly you; the protocol takes {{gc taxMinProtocol}} to {{gc taxMaxProtocol}} of it | | Protocol fee of the DEX on launch pools | **0** | nobody: launch pools pay no core protocol fee | **The split of the trading fee.** The protocol's share is at least {{gc kitProtocolFloor}} and at most {{gc clMaxProtocol}}; a partner app that built the launch can take up to {{gc clMaxIntegrator}}; the creator gets the rest. Our launchpad uses **75% creator, 25% protocol, 0% partner**. Launchpads that others build on Gully Core with PadFactory may take a partner share of up to {{gc clMaxIntegrator}} from the creator's side; the protocol share stays between {{gc clMinProtocol}} and {{gc clMaxProtocol}} for everyone. ## Our launchpad defaults What a launch on our launchpad ([app.gullychain.xyz](https://app.gullychain.xyz/), Gully Street) uses unless you change it. Supply and starting market cap are under **Advanced** in the launch form; the limits come from the contracts. {{gc-defaults}} **The opening fee.** 50% at the first second, falling in a straight line to the normal 0.3% fee after 60 seconds, the shortest window the launch guard allows. Most of it comes back to you through the launch's split. {{gc-default-chart}} This is a price, not a wall: a buyer willing to pay can still buy, and splitting a buy over many wallets is not stopped. What it removes is the free money for a bot at the open.
Advanced: other anti-snipe schedules (presets) Gully Core also ships named presets (`LaunchPresets.sol`), and any launch can set its own numbers within the limits in [Fees in detail](#fees-in-detail). The opening fee always falls in a straight line over its window, then stays. {{gc-presets}} | Preset | Opens at | Settles at | Over | |---|---|---|---| | Our launchpad (custom, default) | 50% | 0.30% | 60 seconds | | Fair launch | 10% | 0.30% | 5 minutes | | Anti-sniper (aggressive) | 50% | 1% | 30 minutes, and a max buy per transaction is required | | Stealth | 50% | 0.30% | 2 minutes, best with a set start time | | No tax | 0.30% | 0.30% | no opening fee | The presets are for concentrated-liquidity pools; Bin pools cap the opening fee at {{gc binGuardMaxInitial}} and the final fee at {{gc binGuardMaxFinal}}.
## Fees in detail
Advanced: every number, where it is read from, and the protocol fee policy ### Launch (LaunchpadKitV2) | Value | On chain | Read with | |---|---|---| | Launch fee | {{gc launchFee}} | `launchFeeWei()` | | Announced fee change | {{gc pendingLaunchFee}} (0 = none pending) | `pendingLaunchFee()` | | Launch fee ceiling | {{gc maxLaunchFee}} | `maxLaunchFeeWei()` | | Notice before a fee rise | {{gc launchFeeNotice}} | `launchFeeNoticeSeconds()` | | Protocol share floor of the LP fee split | {{gc kitProtocolFloor}} | `PROTOCOL_LP_FLOOR_BPS()` | | Partner app (integrator) share, max | {{gc kitMaxIntegrator}} | `maxIntegratorBps()` | | Partner app launch fee, max | {{gc maxIntegratorLaunchFee}} | `maxIntegratorLaunchFeeWei()` | | Creator tax, max per side | {{gc kitMaxTax}} | `maxTaxBps()` | | Partner share of the creator tax, max | {{gc kitMaxTaxIntegrator}} | `maxTaxIntegratorBps()` | | Liquidity legs per launch, max | {{gc maxLegs}} (up to {{gc maxBinsPerLeg}} bins per Bin leg) | `maxLegs()`, `maxBinsPerLeg()` | | Longest delayed start | {{gc kitMaxStartDelay}} | `MAX_START_DELAY_SECONDS()` | | Owner and protocol fee recipient | {{gc kitFeeRecipient}} (governance Safe) | `owner()`, `protocolFeeRecipient()` | ### Locked liquidity (GullyCoreLPLocker, GullyCoreBinLPLocker) | Value | CL locker | Bin locker | |---|---|---| | Protocol share, min | {{gc clMinProtocol}} | {{gc binMinProtocol}} | | Protocol share, max | {{gc clMaxProtocol}} | {{gc binMaxProtocol}} | | Partner share, max | {{gc clMaxIntegrator}} | {{gc binMaxIntegrator}} | | Launches locked so far | {{gc clLockCount}} | {{gc binLockCount}} | The creator gets what is left after the protocol and partner shares. The split is written once per launch and can never change; only the creator can hand their share to another address (two steps). Fees are collected with the permissionless `collectFees(tokenId)` and paid by pull: `claimable(account, currency)`, then `claim(currency, to)`. ### Launch guard: opening fee and creator tax (LaunchGuardHook, BinLaunchGuardHook) | Value | On chain | |---|---| | Opening fee, max (CL / Bin) | {{gc guardMaxInitial}} / {{gc binGuardMaxInitial}} | | Final fee, max (CL / Bin) | {{gc guardMaxFinal}} / {{gc binGuardMaxFinal}} | | Decay window | {{gc guardMinDecay}} to {{gc guardMaxDecay}} | | Share of the trading fee left to the pool as LP fee (buys only) | {{gc guardLpShare}} (cap {{gc guardMaxLpShare}}) | | Protocol share of the trading fee, min | {{gc guardFeeMinProtocol}} | | Creator tax, max per side | {{gc taxMax}} | | Creator tax, longest duration | {{gc taxMaxDuration}} | | Protocol share of the creator tax | {{gc taxMinProtocol}} to {{gc taxMaxProtocol}} | | Partner share of the creator tax, max | {{gc taxMaxIntegrator}} | | Latest opening after the launch is claimed | {{gc guardMaxStartDelay}} | The guard takes the trading fee itself, in the pool's quote currency (ETH, WETH or USDC.e), on every swap. On a buy, {{gc guardLpShare}} of it is left to the pool as its LP fee, which the locked liquidity earns and the locker splits; the rest, and the whole fee on a sell, goes to the guard's fee pot. `settleFee` (anyone may call it) splits the pot by the launch's fee split into `claimable(account, currency)`, and each party calls `claim`. The creator tax has its own pot and split (`settleTax`). Rates, split and expiry are frozen from the start time or the first trade. ### Protocol fee policy of the DEX Both pool managers name **GullyCoreProtocolFeeControllerV4** as their protocol fee controller (CL: {{gc clController}}, Bin: {{gc binController}}). Core asks it once, when a pool is created, and stores the answer for that pool: 1. **Locked launch pools pay 0.** V4 asks its launch oracle, the kit ({{gc v4Oracle0}}, {{gc v4OracleCount}} oracle), whether the pool is a locked launch. If yes, the protocol fee is 0. 2. **Pools on a listed fee-sharing hook pay 0.** These hooks already pay the protocol their own share: the CL dynamic-fee hook (listed: {{gc v4ZeroDynHook}}), the Bin dynamic-fee hook ({{gc v4ZeroBinDynHook}}) and the DEX hook ({{gc v4ZeroDexHook}}). The Safe can add a hook at once; removing one needs {{gc v4HookNotice}} notice. 3. **Every other pool pays what the policy says**, `policy()` = **GullyCoreProtocolFeeControllerV2** ({{gc v4Policy}}): - static-fee pools: **{{gc v2SplitRatio}} of the total swap fee** (`protocolFeeSplitRatio`), taken from the swap input on top of the LP fee, so LPs keep their whole fee; - dynamic-fee pools: a flat **{{gc v2DynamicPips}}** per direction (`dynamicFee()`, set: {{gc v2DynamicSet}}), what a 0.30% pool pays under the split; - the cap is {{gc v2MaxProtocolFee}}; a kill switch can turn every fee off (`feesDisabled`: {{gc v2FeesDisabled}}), and no per-tier override is set. | Pool LP fee | Protocol fee (`feeForLpFee`) | |---|---| | 0.01% | {{gc v2Fee100}} | | 0.05% | {{gc v2Fee500}} | | 0.25% | {{gc v2Fee2500}} | | 0.30% | {{gc v2Fee3000}} | | 1% | {{gc v2Fee10000}} | Collected protocol fees can only go to the treasury, the governance Safe ({{gc v4Treasury}}); V2's guardian ({{gc v2Guardian}}) can only switch fees off, never collect. A protocol fee for a pool that already exists changes only through the owner's `syncPoolToPolicy` or `setPoolProtocolFee` (never non-zero on a locked launch or listed hook). The same numbers as JSON: [/gully-core-fees.json](https://docs.gullychain.xyz/gully-core-fees.json).
## Launch from code - `LaunchpadKitV2.createLaunch(LaunchParamsV2)` is payable with the launch fee. `metadataURI` is `ipfs://` of a JSON `{name, symbol, description, image}`. - `GullyCoreLaunchAndBuy.launchAndBuy(params, buy)` launches and makes the creator's first buy atomically (start delay 0). Get the token address first with `predictLaunchToken(creator, salt)` and pass it back as `expectedToken`; `previewOpeningFee(schedule, amountIn)` shows what the first buy pays. - Each launch is up to {{gc maxLegs}} single-sided legs (a CL range above or below the price, or a Bin shape), every leg locked. `legsOf(token)` and `getLeg(poolId)` on the kit give each leg's kind (CL or Bin) and lock id; `isLocked(lockId)` on the locker proves the lock. - Open your own launchpad or DEX on Gully Core in one transaction with `GullyCorePadFactory`. ## Contract addresses {{gc-contracts}} Shared contracts Gully Core uses: Permit2 `0x000000000022D473030F116dDEE9F6B43aC78BA3`, WETH `0x26aCCCb2e98ca9e067E58668Aa3B101beF432754` and USDC.e `0x65Ba03c6FA90Ed549f465D4c8f2e784D6eEB7E76` (6 decimals). ## The chain in one table | Setting | Value | |---|---| | Chain ID | **485590** (hex `0x768d6`) | | Type | Arbitrum Orbit L3 (Nitro, ArbOS 51), rollup mode, settles to Arbitrum Sepolia (421614). Mainnet will settle to Arbitrum One. | | Gas token | ETH, 18 decimals | | Block production | Blocks on demand, first-come-first-served sequencer, no public mempool, so no classic sandwich bots | | EVM | Cancun opcodes; Stylus (Rust/WASM) contracts | | Genesis | L3 block 0 at Arbitrum Sepolia block 322,568,124 | ## The two-clock rule > [!WARNING] > **`block.number` returns the parent chain's block number.** On Gully Chain, as on every Arbitrum chain, `block.number` inside a contract is an L1 block number (Ethereum Sepolia's height on the testnet, Ethereum's on mainnet; see [Network reference](https://docs.gullychain.xyz/network/#blocknumber-is-not-the-l3-block-number)), while the JSON-RPC's `eth_blockNumber` and the explorer show Gully Chain's own blocks. Gully Core uses **`block.timestamp`** for every window (opening fee, tax expiry, start time). Your own contracts should too, or read the L3 block number with `ArbSys(0x64).arbBlockNumber()`. Indexers must treat the contract-side block number as the parent chain's clock (a `parent-l1` block clock). ```solidity interface ArbSys { function arbBlockNumber() external view returns (uint256); } uint256 l3Block = ArbSys(address(0x64)).arbBlockNumber(); ``` ## Endpoints | Service | URL | |---|---| | RPC | `https://rpc.gullychain.xyz` (public, rate limited; a keyed endpoint for an indexer is available on request) | | Explorer | [testnet-explorer.gullychain.xyz](https://testnet-explorer.gullychain.xyz/) (contract verification supported) | | Bridge | [bridge.gullychain.xyz](https://bridge.gullychain.xyz/) | | Faucet | [faucet.gullychain.xyz](https://faucet.gullychain.xyz/): 0.0005 ETH per address per day (Gully ID sign-in) | | Bundler and paymaster | see [Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/#endpoints) | | Token list | `https://gullychain.xyz/tokenlist.json` | | App | [app.gullychain.xyz](https://app.gullychain.xyz/) (the GullyChain app: swap, launch, names, arcade) | ## Legacy launchpads Before Gully Core the testnet ran small Gully launchpads of its own. They are **deprecated**: do not launch new tokens there. Existing tokens keep trading, curves keep graduating into Uniswap v3, and the lockers keep collecting fees for their creators. All of them are listed on [Contract addresses](https://docs.gullychain.xyz/contracts/#legacy-launchpads). | Contract | Address | Status | |---|---|---| | GullyLaunchpadV3 (with GullyFairLaunch) | `0x2d723cd02061e3F2E0e0B2dc20C0549c66C462de` | legacy: new launches use Gully Core | | GullyLaunchpad v2.1 | `0xCe2c3Ac523EfF3Bec8D3894f7e5C5F519638326b` | legacy: new launches use Gully Core | | GullyLaunchpad v2.0 | `0x3378b659f6ddA7F13D87599B383b3995f82D0974` | legacy | The Uniswap v3 deployment and Gully Swap stay live next to Gully Core; see [Contract addresses](https://docs.gullychain.xyz/contracts/#uniswap-v3-and-gully-swap). ## What comes next 1. Every launch is scanned by Gully Security, mapped by HolderMaps from its first block and given a 0 to 100 launch score. 2. An independent audit of Gully Core before mainnet. 3. A production price source is chosen before any mainnet dollar values are shown. 4. Mainnet: deployed by the governance Safe, announced on [@Gully_Labs](https://x.com/Gully_Labs). Gully Core is derived from the DeepCore contracts (GPL-2.0-or-later), with Gully Labs modifications. # Status Source: https://docs.gullychain.xyz/status/ > What is live on GullyChain Testnet today, what is rolling out next and what comes after. The dated release history is on the Changelog page. For the chain's live state (block height, last block, gas price, batch posting and RPC health) open the **[testnet stats page](https://gullychain.xyz/testnet/)**. It reads the chain directly from your browser. ## Live | Service | Notes | |---|---| | RPC | Five public endpoints with fallbacks: [rpc.gullychain.xyz](https://rpc.gullychain.xyz), the Gully RPC keyless project, rpc2, testnet-rpc and same-origin `/rpc`. See [RPC and indexer API](https://docs.gullychain.xyz/rpc-api/). | | Gully Bridge | [bridge.gullychain.xyz](https://bridge.gullychain.xyz/): the Hyperlane fast lane (native ETH, about a minute both ways) and the canonical bridge. See [Bridging](https://docs.gullychain.xyz/bridging/). | | Canonical withdrawals | The validator is staked on Arbitrum Sepolia and assertions are confirmed, so withdrawals can be claimed after the confirmation period. | | Explorer | [testnet-explorer.gullychain.xyz](https://testnet-explorer.gullychain.xyz/): the Control room, with contract labels and USD prices. | | Contract verification | [verify.gullychain.xyz](https://verify.gullychain.xyz/): self-hosted Sourcify for chain 485590. | | Batch posting | The sequencer posts batches to Arbitrum Sepolia. Live count on the [stats page](https://gullychain.xyz/testnet/). | | Faucet | [faucet.gullychain.xyz](https://faucet.gullychain.xyz/): 0.0005 ETH per address per day, sign in with Gully ID. | | Gully ID | [gullyid.xyz](https://gullyid.xyz/): Sign in with Gully (OIDC) with wallet, `.gully` name and reputation claims; one-tap approvals (session keys, $25 a day by default, enforced on chain by GullySessionPolicy `0xFDEB7b7715200dBc94A058BA1254b863c08D070E`), Send and Receive with a QR code, `.gully` name claim on the ID tab, an installable app, Telegram and Farcaster sign-in. See [Gully ID sign-in](https://docs.gullychain.xyz/gully-id/). | | Standard contracts | CREATE2 factories, CreateX, Multicall3, Permit2, ERC-1820, ERC-6551, EntryPoint v0.6 to v0.8, Seaport 1.6 and more, each with its live status on [Deploy on Gully Chain](https://docs.gullychain.xyz/deploy/#standard-contracts) and re-checked every minute on the status page. | | Smart accounts and sponsored gas | Kernel v3.3 accounts with passkeys and session keys, the Alto bundler (EntryPoint v0.7) and the Gully paymaster (ERC-7677). See [Accounts and passkeys](https://docs.gullychain.xyz/account-abstraction/). | | Gully Safe | [safe.gullychain.xyz](https://safe.gullychain.xyz/): Safe 1.4.1 multisigs with passkey signers. See [Gully Safe](https://docs.gullychain.xyz/safe/). | | Stablecoins | USDC.e (Circle Bridged USDC Standard) is the stablecoin. glUSD is retired (2026-10-28): redeem-only 1:1 for USDC.e, redeem by 2026-11-11. See [Stablecoins](https://docs.gullychain.xyz/stablecoins/). | | Uniswap v3 and Gully Swap | Factory, router, position manager, quoter, plus the Gully fee controller and swap router. | | Gully Core launchpad and DEX | Live 2026-10-29: one-transaction launches with liquidity locked forever, anti-snipe opening fees, creator tax, the Gully Core DEX. See [Gully Core](https://docs.gullychain.xyz/gully-core/). The earlier launchpads (v2.x, v3) are legacy. | | App | [app.gullychain.xyz](https://app.gullychain.xyz/): five tabs (Home, Discover, Create, Inbox, Me), Shorts, fan memberships and members-only posts, the meme maker with Remix and Launch as coin, share cards and embeds, global search, the social feed, profiles, DMs, the GullyVerified badge, copy trading, swap, launch, names, quests, arcade, referrals. See [Getting started](https://docs.gullychain.xyz/getting-started/). | | Season 0 | [app.gullychain.xyz/season-0](https://app.gullychain.xyz/season-0): six on-chain quests (34 to 39) until 2026-11-26. Early activity is recorded on chain, no airdrop is promised. | | Telegram Mini App | [app.gullychain.xyz/tg](https://app.gullychain.xyz/tg): Gully inside Telegram, with Telegram sign-in. | | Share cards and embeds | Cards, story images, the embeddable player and oEmbed. See [Share and embed](https://docs.gullychain.xyz/embeds/). | | .gully names | ENS contracts with a free testnet registrar. See [.gully names](https://docs.gullychain.xyz/names/). | | Quests | Gully Quests v1 and v2: multi-step, hold, quest chains, streaks, soulbound badges, leaderboard. See [Quests](https://docs.gullychain.xyz/quests/). | | Arcade | GullyArcade with Frog Hop season 1. See [Arcade](https://docs.gullychain.xyz/arcade/). | | Referrals | Registry and rewards distributor. See [Referrals](https://docs.gullychain.xyz/referrals/). | | RWA rails | ERC-3643 and ONCHAINID with the TEST-TBILL demo asset. See [Real-world assets](https://docs.gullychain.xyz/rwa/). | | Price feed (testnet only) | RedStone pull feed for ETH, BTC and USDC with AggregatorV3-style adapters. See [Price oracle](https://docs.gullychain.xyz/oracle/). | | Indexer API | [indexer.gullychain.xyz](https://indexer.gullychain.xyz/): tokens, candles, trades, holders, feed, names, quests. | | Token list | [gullychain.xyz/tokenlist.json](https://gullychain.xyz/tokenlist.json) and [gully-labs/token-lists](https://github.com/gully-labs/token-lists). See [Token list](https://docs.gullychain.xyz/token-list/). | | Uptime | [status.gullylabs.xyz](https://status.gullylabs.xyz/) checks every public host each minute. | ## Rolling out | Service | Notes | |---|---| | Gully Pay on GullyChain | Tips and paid DMs work in the app; checkout in USDC.e on chain 485590 and x402 settlement are rolling out. | | Gully ID: Google, X and Apple sign-in | Passkey, wallet, email, Telegram and Farcaster work; Google, X and Sign in with Apple are coming. | ## Next | Service | Notes | |---|---| | Safe singleton factory | Safe's canonical addresses; see [Not deployed yet](https://docs.gullychain.xyz/contracts/#not-deployed-yet). | | Production price feed | The RedStone testnet feed is for non-production use; a production source is chosen before mainnet. | | Mainnet | Will settle to Arbitrum One. Timing on [X](https://x.com/Gully_Labs). | ## Changelog The dated release history moved to its own page: **[Changelog](https://docs.gullychain.xyz/changelog/)**. # Changelog Source: https://docs.gullychain.xyz/changelog/ > Every Gully Chain release by date, newest first: the app, Gully ID, contracts, network services and the docs. 2026-10-29 brings the five-tab app, Shorts, fan memberships, memes, Season 0, one-tap approvals and Gully Core on testnet. Every release of the Gully Chain testnet, the Gully Chain app and these docs, newest first. For what is live right now see [Status](https://docs.gullychain.xyz/status/). Releases are also posted on the [Gully Chain Telegram channel](https://t.me/GullyChain). ## 2026-10-29: the new app, Season 0 and Gully Core **The Gully Chain app** at [app.gullychain.xyz](https://app.gullychain.xyz/) - **Five tabs:** Home, Discover, Create, Inbox and Me, with one global search box and a What's new sheet. Old links (`/feed`, `/creators`, `/explore`) still work and forward to their new place. - **Shorts** at [/shorts](https://app.gullychain.xyz/shorts): short vertical videos from creators. - **Fan memberships and locked content:** creators sell monthly memberships in Studio ([/studio/memberships](https://app.gullychain.xyz/studio/memberships)) and lock posts and videos to members; fans manage theirs under Me. - **Memes:** the meme maker ([/create/meme](https://app.gullychain.xyz/create/meme)), **Remix** of other people's memes, and **Launch as coin** to turn a meme into a token on Gully Chain. - **Share cards and embeds:** a rich card for every share link, story images, an embeddable player for tracks, videos, Shorts and live streams, and oEmbed at `https://app.gullychain.xyz/oembed?url=...`. See [Share and embed](https://docs.gullychain.xyz/embeds/). - **Season 0** at [/season-0](https://app.gullychain.xyz/season-0): six on-chain quests (34 to 39: claim a Sentry Key, first swap, bridge, launch a token, follow the Telegram channel, refer a friend) until 2026-11-26. Early activity is recorded on chain, no airdrop is promised. - **Telegram Mini App** at [/tg](https://app.gullychain.xyz/tg): Gully inside Telegram, with Telegram sign-in. **Gully ID** at [gullyid.xyz](https://gullyid.xyz/) - **One-tap approvals:** after one passkey approval, small tips, unlocks and renewals take one tap under a daily limit ($25 a day by default, $0 to $250 per app). The limit is enforced on chain by GullySessionPolicy `0xFDEB7b7715200dBc94A058BA1254b863c08D070E` (source verified). Bigger payments, new recipients and security changes still need the passkey. - **Send and Receive** with a QR code, **.gully name claim** on the ID tab, an **installable app** (PWA), and **Telegram and Farcaster sign-in**. **Contracts** - **Launch on Gully Core:** the launchpad and DEX core is live on testnet: 44 contracts (vault, pool managers, router, launchpad, hooks, orders, vaults), verified on Sourcify. In the app: one-transaction launches with liquidity locked forever ([/launch](https://app.gullychain.xyz/launch)), swaps on the Gully Core DEX, token pages and [analytics](https://app.gullychain.xyz/analytics). The earlier launchpads are legacy. See [Gully Core](https://docs.gullychain.xyz/gully-core/). - **GullyPayFoundersPass** `0xd71788bD3D348305a31c65384ec1124990e7cc01` and **QuestTracker** `0x474969574A81dBA94D96540619509b817307Cb2B` are deployed; see [Contract addresses](https://docs.gullychain.xyz/contracts/). - The WETH/USDC.e pool has liquidity and swaps work. **Docs** - New pages: [Getting started](https://docs.gullychain.xyz/getting-started/) (the app in ten minutes) and this changelog (it moved here from the Status page). - [Share and embed](https://docs.gullychain.xyz/embeds/) is marked live and documents the share event API; [Gully Core](https://docs.gullychain.xyz/gully-core/) lists every deployed address. - [/llms-full.txt](https://docs.gullychain.xyz/llms-full.txt): every docs page in one Markdown file for AI tools, next to [/llms.txt](https://docs.gullychain.xyz/llms.txt). > [!SOON] > Not live yet, so not linked: Gully Music, Radio, Watch series and Gully Pass; live video and chat; bridging from Ethereum, Base, BNB Chain, Solana and Arbitrum; native iOS and Android apps; creator tiers ($25 to $500 a year); ads; Sign in with Apple. ## 2026-10-28: developer self-serve - **[Deploy on Gully Chain](https://docs.gullychain.xyz/deploy/)**: one page with the network table, Foundry, Hardhat, viem and ethers config, Sourcify verification, every standard and Gully contract with its live status, quirks, rate limits and where to get help. - **Machine-readable chain data:** [/chain.json](https://docs.gullychain.xyz/chain.json) (ethereum-lists fields and the EIP-3085 `wallet_addEthereumChain` object) and [/addresses.json](https://docs.gullychain.xyz/addresses.json), on docs. and dev. - **Status page:** a Chain readiness group checks the code at every standard contract address. - The bridge's primary address is now [bridge.gullychain.xyz](https://bridge.gullychain.xyz/); testnet-bridge stays as an alias. ## 2026-10-28: Offerwall - **Gully Offerwall** live at [offers.gullychain.xyz](https://offers.gullychain.xyz/): quest campaigns funded through Gully Pay (checkout rolling out), USDC or points rewards, an embeddable widget and server postbacks. New page: [Offerwall](https://docs.gullychain.xyz/offerwall/). Gully Pay's payment contracts are now listed on [Contracts](https://docs.gullychain.xyz/contracts/#gully-pay). ## 2026-10-28: Sentry Keys - **Gully Sentry** live at [sentry.gullychain.xyz](https://sentry.gullychain.xyz/): free testnet Sentry Keys (one per Gully ID and per wallet, no gas) and the one-file watcher that checks every assertion on Arbitrum Sepolia. Testnet keys have no monetary value. New page: [Run a Sentry](https://docs.gullychain.xyz/sentry/). ## 2026-10-27: identity, Safe, Quests v2 - **Gully ID** moved to its own domain, [gullyid.xyz](https://gullyid.xyz/) (issuer `https://gullyid.xyz/`), with the developer console and the `wallet`, `gully_name` and `reputation` claims. The faucet, bridge and explorer sign in with it. New page: [Gully ID sign-in](https://docs.gullychain.xyz/gully-id/). - **Gully Safe** live at [safe.gullychain.xyz](https://safe.gullychain.xyz/) on Safe 1.4.1 and the Safe passkey modules at Gully's own addresses; sponsored Safe user operations tested end to end. New page: [Gully Safe](https://docs.gullychain.xyz/safe/). - **Quests v2:** multi-step quests, hold-for-time, quest chains, daily streaks, a passkey-account step, soulbound badges and the leaderboard. - **CreateX** deployed at its canonical address. - **Validator staked** on Arbitrum Sepolia: canonical withdrawals now confirm. - **Public RPCs:** rpc.gullychain.xyz, the Gully RPC keyless project, rpc2.gullychain.xyz and same-origin `/rpc` join testnet-rpc, plus `/price/eth`. New page: [RPC and indexer API](https://docs.gullychain.xyz/rpc-api/). - **Contract verification** at [verify.gullychain.xyz](https://verify.gullychain.xyz/) (self-hosted Sourcify). - **Sentry Keys** contracts deployed; the free testnet mint is not open yet. - **App:** the social feed is fed live from the indexer; the explorer's Control room shows contract labels and USD prices. - **Docs:** new Gully ID sign-in, Gully Safe, Price oracle and RPC and indexer API pages; Bridging, Quests and Accounts updated. ## 2026-10-26: Quests, the fast lane, social - **Gully Quests** live with eight seed quests and verifier contracts for names, curve trades, swaps, bridge deposits, arcade scores, referrals, holdings and attested actions. - **Native ETH fast lane:** a Hyperlane warp route between Arbitrum Sepolia and GullyChain (real ETH both ways) with Gully's own 2-of-3 validators and relayer. The earlier gETH route is redeem only. - **Social and copy trading:** posts, follows, paid DMs, the GullyVerified badge and the copy-trading engine at copy.gullychain.xyz. ## 2026-10-25: Multicall3 - **Multicall3** deployed at its canonical address `0xcA11bde05977b3631167028862bE2a173976CA11` from the published pre-signed transaction. viem `multicall` and wagmi `useReadContracts` now work. ## 2026-10-25: the app layer lands on testnet - **Smart accounts live:** Kernel v3.3 accounts, WebAuthn (passkey) validator and signer, ECDSA signer, call, rate-limit, timestamp and sudo policies, a Gully-owned factory staker. Public bundler at testnet-bundler.gullychain.xyz and ERC-7677 paymaster at testnet-paymaster.gullychain.xyz. - **Stablecoins:** USDC.e deployed under the Circle Bridged USDC Standard with dedicated USDC gateways on both chains; glUSD and its 1:1 PSM (fees 0, capped at 0.5%, redemptions never pausable). - **Uniswap v3** deployed with Uniswap's deploy tool; **Gully Swap** fee controller and interface-fee router. - **Launchpad** v2.1 with the LP locker that splits graduated-pool fees 50/50 between creator and platform (v2.0 and its locker stay live for earlier tokens). - **.gully names** live with a free first-come testnet registrar. - **Arcade** contract live, Frog Hop season 1 open for 7 days. - **Referrals:** registry and Merkle rewards distributor (20% of platform fees for 180 days, weekly epochs). - **RWA rails:** ERC-3643 (T-REX 4.1.3) and ONCHAINID 2.2.1 with Gully's country, max-balance and max-holders modules, and the TEST-TBILL demo asset. - **Price feed** (testnet only): RedStone pull feed for ETH, BTC and USDC. - **Token list** now lists USDC.e and glUSD. - **Docs:** new Stablecoins, Arcade, Referrals and Real-world assets pages; the Accounts and passkeys and launchpad integration pages rewritten; two-clock (`block.number`) warnings added. ## 2026-10-25: testnet live - **Rollup created** on Arbitrum Sepolia: GullyChain Testnet, chain ID 485590, Arbitrum Orbit (Nitro) in rollup mode with ETH as the gas token. - **Deterministic deployers** on the chain: the Arachnid CREATE2 factory, the ERC-2470 singleton factory, the Zoltu deployer and the ERC-1820 registry. - **Standard contracts** deployed at their mainnet addresses: Permit2, EntryPoint v0.7 and v0.8, Safe4337Module 0.3.0, SafeModuleSetup 0.3.0 and the P256 verifier, plus a WETH9 clone. - **Canonical token bridge** created, with routers and standard, custom and WETH gateways on both chains. - **Explorer** live at [testnet-explorer.gullychain.xyz](https://testnet-explorer.gullychain.xyz/). - **Bridge UI** live at [testnet-bridge.gullychain.xyz](https://testnet-bridge.gullychain.xyz/). - **Faucet** live at [faucet.gullychain.xyz](https://faucet.gullychain.xyz/). - **Testnet page** with live stats, charts, a block feed, endpoints and contract addresses at [gullychain.xyz/testnet](https://gullychain.xyz/testnet/). - **Developer docs** published at docs.gullychain.xyz. # Community & bots Source: https://docs.gullychain.xyz/community/ > Every official Gully Chain channel and bot in one place: the News, Deploys and Trending Telegram channels, the Gully Chain trading bot, the Quest and Buy bots, Discord and X. These are the only official Gully Chain channels and bots. Anything else using the name is not us: we never DM first and never ask for a seed phrase or private key. ## Channels | | Link | What it is | |---|---|---| | | [Gully Chain News](https://t.me/GullyChain) | Official announcements: releases, contracts, network status and mainnet timing. | | | [Gully Chain Deploys](https://t.me/GullyChainDeploys) | Every new token and contract deployed on Gully Chain, as it lands. | | | [Gully Trending](https://t.me/GullyTrending) | The tokens and launches moving most on Gully Chain right now. | ## Bots | | Link | What it is | |---|---|---| | | [Gully Chain Bot (trading)](https://t.me/GullyChainBot) | Non-custodial trading from your Gully passkey account: /connect, /buy, /sell, /copy. Testnet; caps 0.05 ETH per trade. | | | [Gully Quest Bot](https://t.me/GullyQuestBot) | Track your on-chain quests and claim rewards from Telegram. | | | [Gully Buy Bot](https://t.me/GullyBuyBot) | Posts every buy of your token in your group: add it, then send /setup 0xToken. | ## Social | | Link | What it is | |---|---|---| | | [Discord](https://discord.com/invite/tY2ErsNNBp) | Chat with the team and other builders, get help and share what you ship. | | | [X (@Gully_Labs)](https://x.com/Gully_Labs) | Gully Labs on X: launches, threads and live updates. | ## Using the bots - **Gully Chain Bot** trades from your own Gully passkey account through a session key you approve, so the bot never holds your funds. Start with `/connect`, then `/buy`, `/sell` or `/copy`. Testnet only for now, capped at 0.05 ETH per trade. - **Gully Buy Bot** posts every buy of your token in your Telegram group: add the bot to the group, then send `/setup 0xYourToken`. - **Gully Quest Bot** shows your on-chain [quests](https://docs.gullychain.xyz/quests/) and lets you claim rewards from Telegram. Need a hand? See [Support](https://docs.gullychain.xyz/support/). # Gully ecosystem Source: https://docs.gullychain.xyz/ecosystem/ > Every Gully Labs product in one place (Gully Labs, Gully Pay, Gully RPC, Gully ID, Gully Studio, Gully AI, Gully Security and HolderMaps), with what each one does and how it connects to Gully Chain. Gully Chain is one of several products by Gully Labs. The Gully Chain sites keep their menus to Gully Chain itself (the app, explorer, bridge, faucet, Safe, Sentry, verify, docs and the developer portal), so the rest of the Gully family is listed here. Each card opens the product's own site in a new tab. - [Gully Labs](https://gullylabs.xyz/): The company behind Gully Chain and every product on this page. - [Gully Pay](https://gullypay.xyz/): Checkout and x402 payments in USDC for apps and merchants. - [Gully RPC](https://gullyrpc.xyz/): A multi-chain RPC gateway with API keys and a usage dashboard. - [Gully ID](https://gullyid.xyz/): One sign-in for every Gully app: passkeys, wallets and email over OpenID Connect. - [Gully Studio](https://gullystudio.xyz/): The Gully Labs game studio, making Unity games. - [Gully AI](https://gullyai.xyz/): The Gully Labs LLM service: an open-weight model behind an OpenAI-compatible API. - [Gully Security](https://gullysecurity.xyz/): Smart contract scans with a Gully Score, plus monitoring and alerts. - [HolderMaps](https://holdermaps.xyz/): Bubble maps of a token's holders, clustered wallets and launch checks. ## How they fit together - **Sign in once.** Gully ID is the account behind the Gully Chain app, the faucet and the other Gully apps: a passkey on your device that is also your Gully Chain wallet. See [Gully ID sign-in](https://docs.gullychain.xyz/gully-id/). - **Pay once.** Gully Pay is the payment gateway for every Gully product. When something on Gully Chain costs money, the button you press is a Gully Pay checkout. - **Reach the chain your way.** The public RPC in [Network](https://docs.gullychain.xyz/network/) is free and rate-limited. Gully RPC gives you your own keyed, metered endpoint for the same chain. See [RPC & API](https://docs.gullychain.xyz/rpc-api/). - **Check before you touch.** HolderMaps and Gully Security work on Gully Chain tokens and contracts, so you can see who holds a token and what a contract does before you trade or integrate. Building something on Gully Chain? It belongs in the [developer portal ecosystem](https://dev.gullychain.xyz/ecosystem/) of apps on the chain. # Support Source: https://docs.gullychain.xyz/support/ > Get help building on GullyChain: email team@gullylabs.xyz, join the GullyChain Discord and Telegram channels, or reach Gully Labs on X at @Gully_Labs. ## Contact | Channel | Use it for | |---|---| | Email: [team@gullylabs.xyz](mailto:team@gullylabs.xyz) | Questions, bugs, higher RPC limits, partnerships and building on GullyChain. | | X: [@Gully_Labs](https://x.com/Gully_Labs) | Announcements: new contracts, service status, mainnet timing. | ## Reporting a problem Include as much of this as you can, so we can reproduce it: - What you were doing, what you expected and what happened instead. - Transaction hashes and contract addresses, with links to the [explorer](https://testnet-explorer.gullychain.xyz/). - The tool and version (Foundry, Hardhat, viem, cargo-stylus, wallet) and the exact error message. - For bridge issues: the transaction hash on Arbitrum Sepolia and the address you deposited to. Never send a private key or seed phrase, not even a testnet one. Gully Labs will never ask for it. ## Before you write - Is the chain up? Check the [testnet stats page](https://gullychain.xyz/testnet/). A long gap since the last block is normal on a quiet chain: blocks are made only when there are transactions. - Is the feature live? Check [Status and changelog](https://docs.gullychain.xyz/status/). - Need ETH back on Arbitrum Sepolia fast? Use the [fast lane](https://docs.gullychain.xyz/bridging/#fast-lane-hyperlane-native-eth). Canonical withdrawals finish after the confirmation period; see [Bridging](https://docs.gullychain.xyz/bridging/#withdrawals-gullychain-to-arbitrum-sepolia). ## Launch your own chain Want an Arbitrum Orbit chain like this for your own project? Gully Labs builds and runs them: see [gullylabs.xyz/chains](https://gullylabs.xyz/chains) or email [team@gullylabs.xyz](mailto:team@gullylabs.xyz). # Privacy Source: https://docs.gullychain.xyz/privacy/ > How the Gully Chain sites measure visits: self-hosted Umami analytics at analytics.gullychain.xyz, no cookies, no IP addresses stored, Do Not Track respected, no consent banner needed. This notice covers the Gully Chain sites run by Gully Labs: [gullychain.xyz](https://gullychain.xyz/), the app at [app.gullychain.xyz](https://app.gullychain.xyz/), these docs, [dev.gullychain.xyz](https://dev.gullychain.xyz/), the [explorer](https://testnet-explorer.gullychain.xyz/), the [bridge](https://bridge.gullychain.xyz/), the [faucet](https://faucet.gullychain.xyz/), [Sentry](https://sentry.gullychain.xyz/) and the [blog](https://blog.gullychain.xyz/). ## Analytics We count visits with **Umami**, an open-source (MIT) analytics tool that we host ourselves at `analytics.gullychain.xyz`, on Gully Labs servers. No third-party analytics service receives your visit. | Question | Answer | |---|---| | Cookies or local storage for tracking? | No. Umami sets no cookies and stores nothing in your browser. | | IP address stored? | No. Each visit is counted with a one-way hash that uses a salt rotated every day, so a visitor cannot be followed from one day to the next or across sites. | | What is recorded? | The page address, the referring site, browser, operating system, device type, screen size, language and the country (worked out from the request, then discarded). | | Custom events | A few anonymous counters on the steps that matter for the product: sign-up, first swap, quest completed, bridge, creator application, faucet claim, Sentry key claim. They carry no wallet address, name or email. | | Do Not Track | Respected. If your browser sends Do Not Track, the tracking script does not run at all. | | Consent banner? | Not needed: there are no cookies and no personal data in the analytics. | | Who can see it? | Gully Labs staff only. The data is not sold or shared. | Blocking `analytics.gullychain.xyz` in your browser or with a content blocker turns analytics off and does not break any site. ## On-chain data Gully Chain is a public blockchain. Transactions, addresses, quest completions, referrals and `.gully` names are public by design and visible in the explorer to anyone. Nothing we do can make them private or delete them. ## Accounts and email Signing in with Gully ID, joining the blog newsletter or contacting us gives us the details you choose to share (for example an email address). We use them only to run that service and to answer you. You can unsubscribe from the newsletter from any email, and ask us to delete your details at [team@gullylabs.xyz](mailto:team@gullylabs.xyz). ## Contact Questions about this notice: [team@gullylabs.xyz](mailto:team@gullylabs.xyz).