Skip to content
AnmuProtocolPublic

About

Solidity for **Anmu** (安幕), the CauseLaunch protocol on BNB Smart Chain. The compiler is 0.8.28. The optimizer runs 200 times.

Topics

Resources

Stars

208 stars

Watchers

0 watching

Forks

Repository files navigation

Anmu contracts

Solidity for Anmu (安幕), the CauseLaunch protocol on BNB Smart Chain. The compiler is 0.8.28. The optimizer runs 200 times. OpenZeppelin is remapped from lib/openzeppelin-contracts. Foundry is the test and deployment tool. The protocol specification is in ../docs. The public reading is https://docs.anmu.pro.

A launch is a fixed-supply token and a public campaign record. The record stores commitments for the creator, the beneficiary, and the fee receiver. Wallets and legal names are not fields on that record. Donations, trades, allocations, and proof checks are public. The protocol is a funding system. It does not promise a return.

Proof verification does not make the surrounding transactions anonymous.

Contracts

Contract Duty
CampaignFactory Checks the creator-auth proof, the configuration digest, the current authorization root, and an unused nullifier. Registers the campaign and, in the same transaction, deploys the token and the vault and opens the curve. Does not store msg.sender
CampaignRegistry Public records, the lifecycle, and the spent-nullifier map
CauseToken One ERC-20. The full supply is minted once, to the vault, at 18 decimals. No owner, pause, blacklist, or further mint
CampaignVault Credits donations, pays a proof-bound beneficiary claim, holds the bonding curve, and holds creator trade fees
PrivateFeeVault Holds the standard-token creation fee and the platform trade share. Pays a proof-bound fee-receiver claim. There is no admin withdrawal
PancakeLiquidityModule At migration, receives the remaining tokens and the real BNB, burns 95% of the LP token, and leaves 5% for a creator claim
BnbTradeRouter Trades the curve while the launch is Launched. After migration, collects the BNB fee and swaps the rest on PancakeSwap
TokenDeployer, VaultDeployer CREATE2 deployers. The factory is their only caller. Their creation code lives outside the factory so the factory stays under the 24,576-byte limit
CreatorVerifier, ClaimVerifier Check the seven public inputs, then call the generated UltraHonk verifiers

contracts/privacy/honk/CreatorAuthHonkVerifier.sol and contracts/privacy/honk/ClaimHonkVerifier.sol are generated by Barretenberg. The only edit after generation is the contract name. Do not regenerate them as part of an unrelated change. contracts/privacy/README.md records the generator.

Interfaces live in contracts/interfaces. The shared structs and the public-input layouts live in contracts/types/CauseLaunchTypes.sol. ConfigHash, ClaimBinding, BondingCurve, and LaunchRules are the libraries a reviewer should read before the contracts that call them.

Two launches

LaunchRules freezes the split. A caller cannot choose another allocation.

Campaign Standard token
launchKind 1 2
Creation fee None 0.005 BNB, credited by depositCreationFee
Donation split 10000 / 0 / 0 beneficiary, liquidity, protocol Donations revert
Trade fee 50 bps creator, 50 bps added at migration 70 bps plus a creator tax of 0, 100, 200, or 300, and 30 bps platform
Creator tax 0 0%, 1%, 2%, or 3%

Name, symbol, supply, metadata URI, commitments, basis points, launch kind, and creator tax are bound into one configuration digest. They do not change after register.

A campaign may store an invite hash instead of a beneficiary commitment. Donations can start that day. The creator's claim can withdraw them until the beneficiary locks and then publishes. After acceptance the creator's proof no longer withdraws that bucket. No administrator role can withdraw it.

Curve

BondingCurve uses a virtual quote of 4 ether and a migration quote of 16 ether. The invariant is (tokenReserve) * (realQuote + 4 ether) = totalSupply * 4 ether. Fees are taken outside that product. The opening market cap is 4 BNB for every supply. The market cap at migration is 100 BNB. Twenty percent of the supply remains for the PancakeSwap pool.

The buy that reaches 16 BNB of real quote is capped. Unused BNB is refunded. Migration happens in that same transaction: the remaining tokens, the real reserve, and a campaign's parked 0.5% are added to PancakeSwap V2. Ninety-five percent of the LP token is sent to 0x000000000000000000000000000000000000dEaD. Five percent stays in the vault for a creator claim with role 3.

Launched means the curve is open. Active means the curve has migrated. Closing a campaign stops new donations. A curve that has not migrated still allows sells while curveQuote is greater than zero.

The router is 0x10ED43C718714eb63d5aA57B78B54704E256024E. PancakeSwap's own 0.25% pool fee is separate from the BNB fee above. After the pair is registered, a transfer to or from that pair reverts unless BnbTradeRouter opened the trade. Wallet-to-wallet transfers stay whole.

Claims

zk/private_claim opens one commitment and binds the campaign, the recipient, the amount, and the role. ClaimBinding checks those public inputs before the verifier runs, so a substituted recipient never consumes a nullifier.

Role Value Opens Paid by
Beneficiary 1 Separator 6 CampaignVault
Fee receiver 2 Separator 7 PrivateFeeVault
Creator 3 Separator 1, the creator-auth commitment CampaignVault

The recipient is public in the payment transaction. The record still has no recipient field.

Creator authorization is zk/creator_auth: a creator commitment, a depth-16 Merkle membership under the current authorization root, and a nullifier bound to the configuration digest. The factory accepts the proof only when that root, that digest, and an unused nullifier all match. The authorization root on mainnet is 0x205dc578df7131fb3779050cc02073adb79457cd13660700db37a99720de4666.

CREATE2

The vault salt is bytes32(campaignId). The token salt is keccak256(abi.encode(campaignId, uint256(1))). The CREATE2 origin is the deployer contract, not the factory. The factory predicts the vault, deploys the token to that address, then deploys the vault with the same salt. A failure reverts both. The full supply is minted to the vault once.

Roles

DEFAULT_ADMIN_ROLE, VERIFIER_ROLE, and PAUSER_ROLE are held by the deployer 0x6A39c2229ba13732068ED93Bc5FA02528c2e6B42. Those three roles should move to a timelocked multisig. FACTORY_ROLE is the factory. The relayer 0xc086a238AFb5bf1DE9D56d9b83213D3Abd94ab3C has no protocol role. The factory does not allowlist the createCampaign sender.

A pause stops the action it names. It is not a withdrawal and it is not a seizure of a vault balance.

Mainnet

Broadcast on 20 October 2026, chain id 56, blocks 128647492–128647493. The deployment order and the transaction hashes are in ../docs/deployment.md. script/Deploy.s.sol deploys this set. script/deploy.ts derives the authorization root from PLATFORM_AUTH_SECRET and broadcasts the script. Keys stay in the environment.

Contract Address Sourcify
CreatorAuthHonkVerifier 0x8b6e8F7B7cc46FEe428AA3BE5437fB4C5D2e0967 match
CreatorVerifier 0x4d8fa488a519bF293b00763C1f53b4181579135A exact match
ClaimHonkVerifier 0xd107ab3DF4a7cE6a0D2403FCe0db39885C5947d0 match
ClaimVerifier 0x513de405D23d90bB79d45365738611048B276A49 exact match
CampaignRegistry 0x26Fa379809809bCef5C12b5eBa30b59eb1f0b75A exact match
PrivateFeeVault 0xA1034F4776683e9546CE1c9E770673bD898cdcC2 exact match
PancakeLiquidityModule 0xc53550E133e3EE3Aed985ee738B5A31C7de9e853 exact match
BnbTradeRouter 0xD272996546Ba6e976C90E9643cDCC698b5BB5065 exact match
CampaignFactory 0xae6b42Da848144ceA61CE19eA838fcFf5D6Cfb32 exact match
VaultDeployer 0x3aC61Bea0c2c50A1ec20291E7439eAF0c505c37c exact match
TokenDeployer 0xFD96c6c504bd82a996Bb871465F2814439B4C6A0 exact match

Each launch deploys one CauseToken and one CampaignVault. Those instance addresses are on the campaign record. They were not submitted to Sourcify. BscScan's verified badge was not submitted for this deployment.

Tests

forge test
Command What it checks
forge test --match-path test/PrivacyVerifier.t.sol The generated UltraHonk verifiers
forge test --match-path test/CampaignFactory.t.sol The digest, the current authorization root, and an unused nullifier
forge test --match-path test/ConfigDigest.t.sol The locked configuration digest
forge test --match-path test/CampaignVault.t.sol A donation is credited entirely to the beneficiary
forge test --match-path test/PrivateClaim.t.sol A claim pays the recipient and the amount bound in the proof
forge test --match-path test/TradingFees.t.sol Campaign and standard trade fees, and the 0.005 BNB creation fee
forge test --match-path test/Liquidity.t.sol Migration, the 95% burn, and later trade-fee BNB added to the pair
forge test --match-path test/BondingCurve.t.sol The virtual reserve, the cap, and the refund

A passing proof test means the relation holds for that witness. It does not authorize a campaign. The public fixtures are format checks. They are not live credentials.

About

Solidity for **Anmu** (安幕), the CauseLaunch protocol on BNB Smart Chain. The compiler is 0.8.28. The optimizer runs 200 times.

Topics

Resources

Stars

208 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages