One Click, 900 Systems: Advanced Full Stack Engineering to ensure a smooth mint on MegaETH
MEGACORP15 min read·Just now--
Technical field report from the MegaCorp Blockchain Development Group.
The Operator License mint looked simple from the outside. A participant opened /mint, connected an EVM wallet, clicked the mint button, signed one transaction, and received an ERC-721 credential.
The system behind that click was much larger. It had to coordinate an upgradeable NFT contract, phase-based pricing, allowlists, referral codes, on-chain treasury forwarding, Lambda-issued EIP-712 authorizations, AWS edge controls, DynamoDB attribution, live dashboards, wallet-provider quirks, and MegaETH’s very fast confirmation loop.
This document explains the design in enough detail for another MegaETH team to adapt it.
Research Basis
Before designing around MegaETH, the team treated it as standard EVM with a few important MegaEVM differences:
- Standard Solidity contracts, OpenZeppelin upgradeable contracts, Foundry, and ethers all work on MegaETH.
- MegaEVM has a larger contract size limit than Ethereum L1. That mattered because
OperatorLicensecombines minting, progression, tools, sessions, and game hooks in one upgradeable contract. - MegaEVM uses multidimensional gas. Developers should use MegaETH RPC gas estimation and remember the 60,000 intrinsic gas floor.
- MegaETH’s short confirmation times shift the risk from chain throughput to wallet UX, nonce caching, backend signing latency, and edge request spikes.
The Design Brief
Minting an operator’s license is much more in depth than sending a cartoon picture of an animal via OpenSea. The mint contract we know had to issue a credential that would later authorize mining, progression, session wallets, CUBE-related actions, and approved automation paths such as droneOS and AFK tools. The system also had to survive live phase transitions, influencer referral codes, public mint traffic, and the kind of last-minute operational changes that always happen when a launch is real.
The blockchain group solved that by splitting the system into four control planes:
- The contract owns supply, price enforcement, replay resistance, treasury routing, and the final mint decision.
- The capability issuer owns eligibility, EIP-712 signing, referral policy, and launch-time dynamic decisions.
- The edge layer absorbs request floods before Lambda becomes the first line of defense.
- The frontend keeps the user path direct: injected EVM wallet, signed authorization from the issuer, user-submitted mint transaction.
The contract never trusts the UI. The UI never invents eligibility. The Lambda never receives custody of user funds. Revenue forwarding happens on-chain.
MegaETH Deployment Shape
Production uses MegaETH Frontier mainnet:
Network megaeth-mainnetChain ID 4326RPC proxy https://rpc.megacorp.globalWebSocket proxy wss://ws.megacorp.globalExplorerhttps://megaeth.blockscout.comOperator License proxy 0x7503c12b94807993778e9a3ef8b7c0e1f8fe70bbMegaCubeV5 proxy0x7ab966239f3b8cff285594c761424f11b672fd78Contract ArchitectureOperatorLicense is an upgradeable ERC-721:
contract OperatorLicense is
Initializable,
ERC721EnumerableUpgradeable,
OwnableUpgradeable,
ReentrancyGuardUpgradeable,
UUPSUpgradeableDeployment uses an implementation contract behind an ERC-1967 proxy:
OperatorLicense impl = new OperatorLicense();
bytes memory initData = abi.encodeCall(OperatorLicense.initialize, (treasury));
ERC1967Proxy proxy = new ERC1967Proxy(address(impl), initData);That gave the team for example room to ship a scoped referral-manager upgrade without redeploying the NFT collection or changing the public mint address.
MegaCorp-Hosted RPC and WebSocket Edge
You will notice thatrpc.megacorp.global and ws.megacorp.global are not vanity aliases. They are MegaCorp-operated edge endpoints in front of MegaETH's upstream RPC and WebSocket services.
That layer earned its keep four ways.
It gave the frontend a stable origin. Wallets, browsers, and static builds point at MegaCorp endpoints without embedding an upstream vendor URL or needing to ship a new client every time infrastructure shifts.
It kept privileged upstream credentials out of browser DevTools. The client talks to MegaCorp’s public edge. The edge talks to the upstream MegaETH provider with server-side configuration the user never sees.
It separated browser traffic from backend traffic. The public app uses the MegaCorp RPC and WebSocket edge. Server-side systems, including the relay and capability issuer, can use their own protected upstream connections and failure budgets without sharing a noisy neighbor with the mint page.
It made launch operations easier to reason about. When users reported a wallet, mint, or event-stream issue, the team could distinguish three layers cleanly: the browser and wallet, the MegaCorp RPC or WebSocket edge, and the upstream MegaETH network. Three layers, three owners, three fixes. That clarity is worth a lot when mint opened with thousands of concurrent connections.
Why One Contract Was Acceptable on MegaETH
On Ethereum L1, a contract that combines NFT state, phase logic, progression, session keys, tools, and game hooks can be uncomfortable. MegaETH’s larger contract size limit made the single-contract approach practical. The complexity tradeoff is real. OperatorLicense is the credential ledger for the game:
- ERC-721 ownership and enumeration
- Mint phases
- EIP-712 capability verification
- EIP-712 mint authorization verification
- Referral code state
- Session key delegation
- Battery and progression attributes
- Tool inventories
- Game-only hooks for block destruction and CUBE accounting
- Metadata base URI controls
- UUPS upgrade authorization
The mint path uses only a subset of that surface, but the minted asset had to arrive with enough state to become a live operator credential later.
Mint Phase System
The contract supports ten phase slots:
struct MintPhase {
string name;
uint64 startTs;
uint64 endTs;
uint256 priceWei;
uint32 cap;
uint32 mintedInPhase;
uint8 maxPerWallet;
bool requiresAllowlist;
bool enabled;
}Default launch phases were initialized once so that the live on-chain phase config is the source of truth. The owner has a simple setMintPhase() to adjust price, cap, time window, wallet limit, allowlist requirement, or enabled status. That is how the public Omega phase could be altered or configured for launch terms without replacing the contract.
Active Phase Selection
getActiveMintPhaseId() walks phases from 0 to 9 and returns the first enabled phase whose window is open and whose cap is not full.
That simple rule is important. It lets operators schedule multiple waves in advance and lets the contract perform the same phase decision for every user. The Lambda may sign a mint authorization, but the contract re-checks the active phase at transaction execution time.
If a phase fills while a user’s wallet is open, a stale signature cannot mint into the wrong phase. mintLicense() calls _consumePublicMintAuthorization(), which requires:
- valid signer
- valid wallet
- valid time window
- valid
targetContract - valid
startLevel - unused authorization digest
auth.phaseId == current active phase
A filled or closed phase produces a clean revert such as Mint phase changed before any incorrect mint can land.
EIP-712 Capability Model
MegaCorp used two related signed payloads.
Capability
The Capability struct authorizes action modes:
struct Capability {
address wallet;
uint8 allowedModes;
uint64 nonce;
uint64 issuedAt;
uint64 expiresAt;
uint16 budget;
}Mode bits:
0x01 CAP_MODE_MINEmining / block destruction0x02 CAP_MODE_SPEND minting, session updates, purchases0x04 CAP_MODE_INSCRIBE $CUBE inscription
Capabilities are budgeted. The contract stores capabilityState[wallet] = { nonce, remaining, expiresAt }. A new nonce resets the local budget. A repeated nonce decrements the remaining budget. This works for actions like mining where one signature may cover several small calls.
MintAuthorization
Mints use a stricter one-shot payload:
struct MintAuthorization {
address wallet;
uint64 nonce;
uint64 issuedAt;
uint64 expiresAt;
uint8 designationId;
uint8 mintKind;
uint8 phaseId;
uint8 startLevel;
bytes32 referralCodeKey;
address targetContract;
}The contract stores usedCapabilities[digest] = true after a mint authorization is consumed. That makes every mint authorization single-use, even if the user or a malicious actor tries to replay the same signature.
The domain is shared across MegaCorp contracts and is convenient because the backend can use one signing model across multiple contracts. It requires strict typed-data discipline. When the Genesis Drone release added startLevel, the version moved to 2, and tests verify that v1 signatures are rejected.
Public Mint Flow
The public mint path is:
- User connects an injected EVM wallet on
/mint. - Frontend reads
getAllMintPhases()fromOperatorLicense. - Frontend calls
GET /status?wallet=...for allowlist or public eligibility. - Frontend calls
POST /capabilitywithallowedModes: 0x02andmintKind: "public". - Capability Lambda verifies runtime config, phase eligibility, and policy.
- Lambda signs both
CapabilityandMintAuthorization. - Frontend submits
mintLicense(auth, sig)from the user's wallet withvalue = phase.priceWei. - Contract rechecks active phase, payment, per-wallet cap, signature, and replay status.
- Contract mints the ERC-721, increments phase counters, forwards revenue, refunds excess ETH, and emits events.
The Lambda never touches user ETH. It only signs a short-lived authorization.
Referral Mint Flow
Referral mints use mintLicenseWithReferral(codeKey, auth, sig).
The referral code is a bytes32 key derived from a normalized code string. The signed authorization binds that key:
require(auth.referralCodeKey == codeKey, "Referral code mismatch");Referral mints enforce:
- code exists
- code is enabled
- time window is open
mintedCount < maxMints- wallet has not used any referral code before
- payment covers
ReferralCode.priceWei - signed
mintKindis referral-specific - signed phase is
REFERRAL_POOL_PHASE_ID(9)
Referral mints emit ReferralMinted rather than MintedInPhase. That detail matters for analytics. Public phase counters and referral counts are separate. Post-mint reconciliation should compare:
getTotalMinted() - sum(mintedInPhase[]) == count(ReferralMinted events)JIT Referral Sync
The referral system stores operational data in DynamoDB and on-chain limits in OperatorLicense. If a DynamoDB referral row exists but the code is missing on-chain, the Lambda can register it just-in-time:
ensureReferralCodeOnChainFromDynamo(code)
-> read Dynamo referral-codes[code]
-> check status and supply fit
-> call setReferralCode(codeKey, priceWei, maxMints, startTs, endTs, enabled)
-> wait for receipt
-> issue referral mint authorizationThat JIT path let the MegaCorp Community Outreach & Operations Department create, patch, pause, and activate referral codes through admin systems while still making the contract enforce the final mint.
A hardening pass added two important Lambda-side guardrails:
CAPABILITY_MIN_REFERRAL_PRICE_WEIcan reject codes below a configured minimum before signing a referral mint authorization.CAPABILITY_REFERRAL_REQUIRED_PHASE_IDcan restrict referral mints to a required active phase, such as Omega.
Those are just policy gates while the contract still enforces the code price and one-use rules.
Genesis L10 Slots
Some pre-Omega mints were eligible for Genesis L10 licenses. The allocation is deterministic:
MINT_DEFAULT_START_LEVEL = 1GENESIS_START_LEVEL = 10- seed:
megacube-genesis-v1 - total:
100 / 1500pre-Omega mints
The Lambda checks isGenesisSlot(phaseId, mintedInPhase) while building the MintAuthorization. The chosen startLevel is signed into the payload. The contract then validates:
require(
auth.startLevel >= 1 && auth.startLevel <= MAX_AUTHORIZED_START_LEVEL,
"Invalid start level"
);That design lets the backend assign launch-specific starts while the contract still caps the blast radius.
Treasury and Authority Model
The launch split authority across multiple hardware custody and scoped hot keys.
owner() Hardware wallet: phases, treasuries, capability signer, upgradesrevenueTreasury Hardware wallet: receives OperatorLicense ETH inflowsreferralCodeManager AWS Secrets Manager scoped hot EOA: referral code CRUD onlycapabilitySigner AWS Secrets Manager scoped hot EOA: signs capabilities and mint authorizations
Game and treasury operations will move to a multi-sig before the deployment to destroy the Cube.
Revenue forwarding happens inside the contract:
if (price > 0) {
_forwardRevenue(price);
}Excess ETH is refunded to the minter. This means a UI display bug cannot route mint funds to a wrong address. The contract’s revenueTreasury() decides where the sale proceeds go.
The referralCodeManager role was added because the Lambda needed to upsert, pause, and delete referral codes without holding full onlyOwner power. The owner can revoke that role by setting it to address(0).
Capability Issuer
Capability Issuer
The capability issuer is a Lambda function deployed via infrastructure as code.
The central route is:
POST /capabilityIt accepts:
{
"wallet": "0x...",
"allowedModes": 2,
"referralCode": "OPTIONAL",
"mintKind": "public"
}It returns a capability signature and, when mintKind is present, a mint authorization:
{
"capability": {
"wallet": "0x...",
"allowedModes": 2,
"nonce": "123",
"issuedAt": "1710000000",
"expiresAt": "1710000300",
"budget": 1
},
"signature": "0x...",
"mintAuthorization": {
"wallet": "0x...",
"nonce": "123",
"issuedAt": "1710000000",
"expiresAt": "1710000300",
"designationId": 3,
"mintKind": 0,
"phaseId": 9,
"startLevel": 1,
"referralCodeKey": "0x0000...",
"targetContract": "0x7503..."
},
"mintSignature": "0x..."
}Runtime Sanity Checks
Before issuing signatures, validateRuntimeConfig() confirms:
CAPABILITY_CHAIN_IDis valid- stage functions use chain
6343 - prod functions use chain
4326 - RPC network chain ID matches the environment
- contract bytecode exists at
CAPABILITY_DRONE_NFT_ADDRESS - on-chain
capabilitySigner()matches the Lambda signer address
That last check is critical. If an operator rotates the contract signer but the Lambda still holds the old key, mint authorizations fail immediately instead of producing silently bad signatures.
Eligibility Policy
The Lambda handles making policies adjustable without a contract upgrade:
- Alpha, Gamma, and Delta allowlist decisions
- public Omega access
- referral code locks for smoke tests
- referral price floor
- referral-required phase
- launch wave gates
- existing-license spend capability for upgrades and tools
- mining and inscription authorization for session wallets
mintSecurityPolicy.ts keeps the core decisions small and testable:
resolveMintAuthorizationRequest()planSpendAllowlistDecision()checkLockedReferralMintAccess()checkReferralMintPriceFloor()checkReferralMintPhaseAccess()
The contract enforces the final mint. The Lambda decides whether to sign.
DynamoDB Data Model
The capability stack creates pay-per-request DynamoDB tables for referral, Discord, and XP surfaces. Mint-relevant tables include:
{env}-referral-codes ode metadata, price, max mints, status, referrer wallet{env}-referral-claims one claim per wallet for generated / assigned codes{env}-referral-attribution who referred a successful mint{env}-referral-stats counters and commission totals per referrer{env}-referral-payroll commission accrual rows{env}-xp-profiles profile / rank / XP state{env}-xp-ledger idempotent XP awards
The on-chain ReferralMinted event is the ground truth. DynamoDB is the bookkeeping and payout layer.
Edge Layer and WAF
The launch put WAF in front of Lambda instead of using the in-memory rate limiter as the first gate. That limiter is useful inside one warm container, but concurrent Lambda scale means each container has its own bucket.
The production path is:
Browser
-> Cloudflare DNS
-> CloudFront distribution
-> AWS WAFv2 WebACL
-> API Gateway v2 HTTP API
-> Capability Lambda aliasThe CDK stack can put WAF rules into count mode or active block mode.
CloudFront adds an origin-guard secret header before forwarding to API Gateway. If CAPABILITY_ORIGIN_GUARD_SECRET is configured and the request does not have the expected header, Lambda returns 403. That preserves a break-glass API path while preventing casual origin bypass.
Provisioned Concurrency
MegacubeCapabilityStack optionally creates a Lambda alias named live:
new lambda.Alias(this, "CapabilityLiveAlias", {
aliasName: "live",
version: fn.currentVersion,
provisionedConcurrentExecutions: props.capabilityProvisionedConcurrency,
})API Gateway targets that alias when provisioned concurrency is positive. During mint preparation, this kept warm Lambda workers ready for phase-open bursts. After the intense allowlist phases ended, concurrency was able to be scaled back.
Frontend Architecture
The public mint page is intentionally direct-wallet focused. It avoids the full app’s session wallet and custodial flow for the license mint. The hot path is:
- find a real injected EVM provider
- switch or add MegaETH
- read on-chain phase state
- call capability endpoints
- submit the user’s transaction
Wallet Provider Selection
Browser wallet injection is messy. Multiple providers may attach to window.ethereum, and embedded-wallet SDKs may also present EIP-1193-looking objects.
getInjectedWallet() now:
- reads
window.ethereum - expands provider arrays
- removes Privy-labeled providers
- prioritizes MetaMask, Rabby, Coinbase Wallet, Brave, Frame, and Trust
- returns the highest-priority external provider
That keeps the public mint path anchored to the user’s browser wallet.
Chain Switching
ensureMegaEthChain() calls:
wallet_switchEthereumChain- then
wallet_addEthereumChainif the wallet does not know MegaETH yet
Mint Submission
handleMint() performs the final UI-side orchestration:
- Validate or clear referral code.
- Re-read active phase and wallet phase count.
- Request mint authorization from the capability issuer.
- Build
valuefrom referral price or current phase price. - Submit
mintLicenseWithReferral()ormintLicense(). - Wait for receipt + claim mint XP asynchronously.
- Refresh phase, wallet, owned-license, and designation state.
MegaETH Nonce Lag Handling
MegaETH confirms quickly enough that browser wallets can lag behind the chain’s pending nonce. Users who click “Mint Another” quickly may hit wallet-side nonce cache errors.
The frontend catches:
nonce too lownonce has already been usednonce_expired
Then it waits briefly, reads getTransactionCount(wallet, "pending"), and retries once with an explicit nonce.
That is a MegaETH-specific UX lesson. The chain can be faster than the wallet’s local assumptions.
Live Reads and Events
BlockchainService reads:
getAllMintPhases()walletMintedInPhase(phaseId, wallet)getTotalMinted()- referral validation endpoints
- launch wave endpoints
It also listens for:
MintedInPhaseMintPhaseUpdated
Those events invalidate the cached phase snapshot. The next UI read reflects the newest on-chain state. The page also polls periodically while visible, so a missed WebSocket event does not freeze the mint surface.
Operations and Monitoring
Mint day had three live evidence streams.
On-chain Reads
Operators used cast call against the deployed proxy:
cast call "$OP_LICENSE" "getAllMintPhases()" --rpc-url "$RPC"
cast call "$OP_LICENSE" "owner()(address)" --rpc-url "$RPC"
cast call "$OP_LICENSE" "revenueTreasury()(address)" --rpc-url "$RPC"
cast call "$OP_LICENSE" "capabilitySigner()(address)" --rpc-url "$RPC"WAF Metrics
WAF rules emit per-rule CloudWatch metrics. During preparation, count mode gave the team a way to see what would have been blocked before turning rules on.
During the live mint, WAF made the capability API less interesting to attack. The API was still reachable by real users, but malformed bodies, excessive capability requests, cheap-read floods, and admin-path floods had a gate before Lambda.
Failure Modes That Were Designed Out
Wrong Treasury
The UI never chooses where ETH goes. The contract forwards price to revenueTreasury. Preflight checked revenueTreasury()against the canonical hardware wallet record in docs/TREASURIES.md.
Free Public Mint by UI Bug
The contract derives public mint price from the active phase. A UI display error cannot lower priceWei.
Free Referral Mint by Bad Code
Referral price lives in on-chain ReferralCode.priceWei, but the Lambda can refuse to sign referral mint authorizations below CAPABILITY_MIN_REFERRAL_PRICE_WEI. The scoped referralCodeManager role can also be revoked by the owner if referral writes need to freeze.
Replay
Mint authorization digests are one-shot. Capabilities have decrementing budgets. Old v1 mint authorizations fail under the v2 domain.
Wrong Contract
targetContract is part of the signed MintAuthorization. The contract requires auth.targetContract == address(this).
Phase Race
The Lambda signs a phase. The contract checks the current active phase again when the transaction executes.
Bot Flood
WAF, API Gateway throttles, in-Lambda rate costs, origin guard, and provisioned concurrency all share the load. No single layer is treated as magic.
Referral Attribution Loss
Attribution is rebuilt from the on-chain ReferralMinted event. Client retries, beacon delivery, idempotent DynamoDB writes, and admin replay cover the common failure cases.
Wallet Provider Collision
The mint page filters embedded Privy providers out of the public injected-wallet path and prefers browser EVM wallets.
MegaETH Nonce Race
The frontend retries nonce-lag failures once with a fresh pending nonce from the provider.
What Other MegaETH Developers Can Reuse
1. Keep the Contract in Charge of Money
Display price anywhere you want, but enforce price on-chain from contract state. For public mints, derive price from the active phase. For referral mints, bind the signed authorization to a code key whose on-chain record stores price and cap.
2. Sign Intent, Then Recheck State
Short-lived EIP-712 authorizations are useful for allowlists and dynamic policy. Use them as admission tickets, then recheck active phase, wallet, price, target contract, replay status, and code key in Solidity.
3. Separate Owner Power From Operational Power
The hardware owner should control upgrades, treasuries, signer rotation, and phase authority. A hot key can manage narrow operational tasks such as referral code CRUD. Make that role revocable.
4. Treat Referrals as a Two-System Protocol
The chain proves a referral mint happened. Your database proves who should see credit, rank, commission, and dashboard state. Build retries and replay tools from day one.
5. Put WAF Before Lambda
Lambda in-memory rate limiting is useful inside one container. A concurrent Lambda fleet needs a shared gate. Put CloudFront + WAF or equivalent edge controls in front of high-demand signing endpoints.
6. Test Signature Drift
Typed-data version changes are dangerous. Add tests that prove old signatures fail after the struct changes.
7. Design for Fast-Chain Wallet Weirdness
On MegaETH, the chain may confirm faster than an injected wallet updates its local nonce. Handle nonce lag in the UI instead of treating every send failure as a user error.
8. Make Every Operational Toggle Observable
Every launch switch should have a read path:
- active phase
- minted count
- signer
- treasury
- referral manager
- WAF mode
- provisioned concurrency
- Lambda health
- referral totals
If the team cannot read it under pressure, the team cannot operate it under pressure.
Minimal Blueprint
For a MegaETH team building a similar mint:
- Deploy an upgradeable ERC-721 proxy with an owner-held hardware wallet.
- Store phases on-chain with price, cap, time window, wallet limit, and allowlist flag.
- Add
MintAuthorizationwith wallet, nonce, time bounds, phase ID, target contract, and any launch-specific attributes. - Make mint authorizations one-shot by storing the digest.
- Put the signing key in a server-side secret store.
- Make the server validate chain ID, contract bytecode, and on-chain signer before signing
- Put the signer behind API Gateway, CloudFront, WAF, and origin guard.
- Use short TTLs and random uint64 nonces.
- Keep all user funds in wallet-submitted transactions.
- Forward sale proceeds from the contract to the treasury.
- Add event-based reconciliation for every off-chain metric.
- Test every phase, cap, replay, wrong-kind signature, wrong-contract signature, and rollover edge.
The Internal Takeaway
The hardest work was making mintLicense() operable under live pressure.
MegaETH gave the team a fast EVM target. The launch system around it had to handle everything that speed exposes: stale wallet nonces, sudden request bursts, phase races, signer drift, referral drift, and live admin decisions.
The lesson is simple enough to carry forward.
Put the irreversible rules on-chain. Put the changing policy behind signed, short-lived authorizations. Put the signing service behind real edge controls. Then make every moving part observable before the first participant arrives.