While building the MetaDAO dashboard at Blocmates, @563defi and I spent some time digging into MetaDAO’s launchpad program to understand the existing Dune queries, build on them, and create new ones.

These are my notes, which I will be referring back to as I verify & build out more queries on MetaDAO’s activity. This can also be used as context to feed to an LLM for generating simple queries.

Hopefully this helps you understand the program structure and verify your queries are pulling the right data.

Overview

MetaDAO uses the launchpad program to run token presales. Users commit USDC, and after the raise closes, they claim their token allocation (plus refunds if oversubscribed). If the raise is successful, the program creates two liquidity pools, and transfers the remaining USDC to the project’s treasury.

Instructions Covered

The launchpad_v7 program contains nine instructions, but this document will only cover the following instructions:

InstructionDescription
initializeLaunchStages the launch onchain, minting token, and creating the necessary accounts for state and transfers
fundUser commits USDC to a raise
CompleteLaunchAuthority closes raise, triggers AMM pool creation and treasury funding
claimUser receives token allocation
refundUser claims refund

When a launch is initiated, the program creates the necessary accounts for state management and transfers. You should pay special attention to two of these accounts: launchSigner and launch.

The launchSigner account serves as the authority for fund commitments, claims, and refunds throughout the sale.

MetaDAO launch architecture

Meanwhile, the launch account stores configuration and state, tracking details like totalCommittedAmount, and secondsForLaunch. More importantly, the launch account appears at position 1 in every instruction, making it the key filter for querying a specific raise.

Program IDs

VersionProgram ID
v0.7.0moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM
v0.6.0MooNyh4CBUYEKyXVnjGYQ8mEiJDpGvJMdvrZx1iGeHV
v0.5.0mooNhciQJi1LqHDmse2JPic2NqG2PXCanbE3ZYzP3qA

v5, v6, and v7 share the same instruction structure and all queries in this doc work across versions by including each program ID in your filter. However, the event data emitted on-chain differs slightly between versions and isn’t covered here.

How Queries Work

Each instruction in the launchpad program can be identified using Dune’s solana.instruction_calls table by filtering on:

  1. Program ID (executing_account) - the launchpad program address(es)
  2. 8-byte discriminator - the first 8 bytes of the instruction data, unique to each instruction type
  3. Account arguments - accounts at specific positions identify the launch, funder, and other relevant addresses

Instruction Breakdown

initializeLaunch

The initializeLaunch instruction stages the launch onchain by minting the token and creating the necessary accounts for state management and transfers.

Discriminator:

BytesValue
1-85ac9dc8e70fd640d
WHERE bytearray_substring(data, 1, 8) = 0x5ac9dc8e70fd640d

Account Positions:

PositionAccountSQLDescription
1launchaccount_arguments[1]PDA storing launch configuration and state
2Base Mintaccount_arguments[2]Mint address of the token being sold
4launch Signeraccount_arguments[4]Authority wallet for fund transfers

Instruction Data:

ValueBytesTypeDescription
minimumRaiseAmount9-16u64 (little-endian)Minimum USDC that must be raised for launch to succeed
monthlySpendingLimitAmount17-24u64 (little-endian)Maximum USDC the treasury can spend per month
performancePackageTokenAmount224-231u64 (little-endian)Token allocation reserved for performance incentives
monthsUntilInsidersCanUnlock232u8Lockup period before insiders can access tokens

Decoded:


-- minimumRaiseAmount (bytes 9-16, u64)
bytearray_to_uint256(bytearray_reverse(bytearray_substring(data, 9, 8))) / 1e6 AS minimum_raise_amount

-- monthlySpendingLimitAmount (bytes 17-24, u64)
bytearray_to_uint256(bytearray_reverse(bytearray_substring(data, 17, 8))) / 1e6 AS monthly_spending_limit

-- performancePackageTokenAmount (bytes 224-231, u64)
bytearray_to_uint256(bytearray_reverse(bytearray_substring(data, 224, 8))) / 1e6 AS performance_package_token_amount

-- monthsUntilInsidersCanUnlock (byte 232, u8 - single byte, no reverse needed)
bytearray_to_uint256(bytearray_substring(data, 232, 1)) AS months_until_insiders_can_unlock

Example: https://solscan.io/tx/2fbjgAiRnGShdmtkEc6UTA3EzXsuSk7omtu499F9vPE3M8rEo9ux6HHN7CriXTN554wpnU2aHpxedJTLcq6VQJWQ https://solscan.io/tx/3WsHz8iCgeq4VLapPtJGyyccSiPPpc4BYRc4g5GKNQAnEVzRGu1hjuwR4ujBbBXLQLtx3aEW4vzrnuhXxy1S2pPs

Fund

When a user commits USDC to a raise, they call the fund instruction.

Discriminator:

BytesValue
1-8dabc6fdd9871ae07
WHERE bytearray_substring(data, 1, 8) = 0xdabc6fdd9871ae07

Account Positions:

PositionAccountSQLDescription
1launchaccount_arguments[1]PDA storing launch configuration and state
3launchSigneraccount_arguments[3]Authority wallet for fund transfers
5funderaccount_arguments[5]Wallet address of the user committing funds

Instruction Data:

ValueBytesTypeDescription
amount9-16u64 (little-endian)USDC amount committed by the user

Decoded:

bytearray_to_uint256(bytearray_reverse(bytearray_substring(data, 9, 8))) / 1e6 AS usdc_amount

Example: Transaction Ty9tEwqASApmCLWodJkkoS5bEREp9VggTniVqGU4X769tvSHth6165qPzSD3xcg2HJSzercLS2vYAAuLbMhByoo

Complete Launch

Once a raise succeeds, the completeLaunch instruction signals the conclusion of a raise, creates liquidity pools on Futarchy AMM and Meteora DAMM v2, and seeds the project’s treasury (Squads Multisig Vault).

Discriminator:

BytesValue
1-876cffa822c94fbed
WHERE bytearray_substring(data, 1, 8) = 0x76cffa822c94fbed

Account Positions:

PositionAccountSQLDescription
1launchaccount_arguments[1]PDA storing launch configuration and state
5launchSigneraccount_arguments[5]Authority wallet for fund transfers
14Dao (Futarchy AMM pool)account_arguments[14]Futarchy AMM liquidity pool (Token-USDC)
16Squads Multisig Vaultaccount_arguments[16]Project treasury controlled by the DAO
36Meteora Accounts Pool (Meteora DAMM v2 pool)account_arguments[36]Meteora DAMM v2 liquidity pool (Token)

Claim

When a raise completes, the claim instruction is triggered to send tokens to participants’ wallets.

Discriminator:

BytesValue
1-83ec6d6c1d59f6cd2
WHERE bytearray_substring(data, 1, 8) = 0x3ec6d6c1d59f6cd2

Account Positions:

PositionAccountSQLDescription
1launchaccount_arguments[1]PDA storing launch configuration and state
3launchSigneraccount_arguments[3]Authority wallet for fund transfers
6funderaccount_arguments[6]Wallet address of the user claiming funds

Instruction Data:

The claim value is located in the second inner instruction’s data payload. You can filter these inner instructions using their 8-byte discriminator.

Claim instruction inner data

Discriminator for claim inner instruction:

BytesValue
1-8e445a52e51cb9a1d

Claimed token amount:

ValueBytesTypeDescription
tokensClaimed105-112u64 (little-endian)Claimed token amount

Decoded:

To query claim instructions, create two CTEs:

  1. Capture claim instructions by filtering on discriminator 3ec6d6c1d59f6cd2
  2. Capture inner instructions containing the token amount by filtering on discriminator e445a52e51cb9a1d

Join on tx_id and outer_instruction_index to match events to their parent instructions.

Here’s an example forked from @adam_tehc:

Claim query example

https://dune.com/queries/6529959?sidebar=none

Example: Transaction 2aFDEAGW8gRTFBks8pf56ENibg4HQbSYev4enw4rqcaHUiDMLV4SL3REPFK4zYiLRQngCLKsYXvRSzdQvChSqTYG

Refund

When a raise is oversubscribed, the refund instruction returns excess USDC to participants.

Discriminator:

BytesValue
1-80260b7fb3fd02e2e
WHERE bytearray_substring(data, 1, 8) = 0x0260b7fb3fd02e2e

Account Positions:

PositionAccountSQLDescription
1launchaccount_arguments[1]PDA storing launch configuration and state
4launchSigneraccount_arguments[4]Authority wallet for fund transfers
5funderaccount_arguments[5]Wallet address of the user

Instruction Data:

The refunded value is located in the second inner instruction’s data payload. You can filter these inner instructions using the data’s 8-byte discriminator.

Refund instruction inner data

Discriminator for inner instruction:

BytesValue
1-8e445a52e51cb9a1d

Refunded USDC value:

ValueBytesTypeDescription
usdcRefunded105-112u64 (little-endian)USDC amount

Decoded:

To query refund instructions, create two CTEs:

  1. Capture refund instructions by filtering on discriminator 0260b7fb3fd02e2e
  2. Capture inner instructions containing the token amount by filtering on discriminator e445a52e51cb9a1d

Join on tx_id and outer_instruction_index to match events to their parent instructions.

Example: Transaction zwtWBrKobmdpY5ZPW5vdLyd2KFByyipYdij8jtB8g8V7CgTXzq5DQBExbqujQQhd8vCrBJmvMDyja5NaR9naxuH

Transaction zdrYEdQQrP2C8XDGkY8M9LgNLLUX54yFJGWVoMPaxWMYJBN5tRrDagDzaF6ZdP7raYmLjm7N5i8Nug9VamVwbnR


I compiled important accounts for each project so you don’t have to worry about sluething:

ProjectTreasury accountLaunch accountToken mint
PaystreamBpXtB2ASf2Tft97ewTd8PayXCqFQ6Wqod33qrwwfK9Vz13YpYe4k5GPaD2vZvvY7v7if31S1Wu8yWShkQs8MzLNhPAYZP1W3UmdEsNLJwmH61TNqACYJTvhXy8SCN4Tmeta
ZKLSOLBNvDfXYG2FAyBDYD71Xr9GhKE18MbmhtjsLKsCuXho6z4h248CdXdeWtxWnHxEPqa5ruYZaEwXRZPyDFYnndbzpRZKFHiLAfAFMTcDAuCtjNW54VzpERvoe7PBF9mYgmeta
LoyalAQyyTwCKemeeMu8ZPZFxrXMbVwAYTSbBhi1w4PBrhvYEE7kXdSdZrjVFDkLb6V7S8VihKookPviRJ7tXVik9qbduLYLikzBQtpa9ZgVrJsqYGQpR3cC1WMJrBHaXGrQmeta
AviciDGgYoUcu1aDZt4GEL5NQiducwHRGbkMWsUzsXh2j622G2rYvdtK8ovuSziJuy5gTTPtviY5CfTnW6Pps4pk7ehEqBANKJmvhT8tiJRsBSS1n2HryMBPvT5Ze4HU95DUAmeta
Umbra6VsC8PuKkXm5xo54c2vbrAaSfQipkpGHqNuKTxXFySx69kx7UDFzFt7e2V4pFtawnupKKvRR3EhV7P1Pxmc5XCQjPRVT6TB7uss3FrUd2D9xs2zqDBsa3GbMJMwCQsgmeta
Omnipair34rned2SLUcYjUrM9meQkuyJY4QDBcKhkcUPXCgGuXD9DHW6DToYjhwknzVCDvZ6r7hSv7ZpGw9adEN8NvZuUpVhomfgRBnxHsNJh6YeGbGAmWenNkenzsXyBXm3WDhmeta
Ranger55H1Q1YrHJQ93uhG4jqrBBHx3a8H7TCM8kvf2UM2g5q38Nmd13rpULJjY7h6oxCfuTWy8WkZxcuDrDWiSdnViVuoRNGRtJMbCveqCp7AC6U95KmrdKecFckaJZiWbPGmeta
Solomon98SPcyUZ2rqM2dgjCqqSXS4gJrNTLSNUAAVCF38xYj9u634r63NH2qbTrSVyLieC3Ab3YKaEfoGnCLM8idZMEycESoLo9oxzLDpcq1dpqAgMwgce5WqkRDtNXK7EPnbmeta