Mainnet Test — On-Chain Proof

To prove that everything works as designed, we performed a full mainnet test on Abstract Chain with the exact same contract code as the production raise contract. The only changes were:

  • LAUNCH_TIME changed to 1775031640 (short delay for testing)

  • EMERGENCY_DEADLINE changed to 1775031940 (LAUNCH_TIME + 5 minutes, instead of 30 days)

  • Token name changed to "PGMTest" / "PGMT" (instead of "PGM")

The raise contract is immutable — no admin functions, no upgrades, no proxy. What you see on-chain is what you get.


Deployed Contracts

Contract
Address
Abscan

Governor

0xff163b37308A7A10033d1210f4113C3BF8e151dD

Truth

0x64868ed43AB056f256a91D8DD01fAE557991bBBD

AddressBook

0x6a01008C3d8D8Ab36977BaAEbFFa5caA45fDaBd6

RoleMapping

0xa61247DAD565E40572e8557E81423cA8380F641a

Authority

0x35772cb8D7a5cF7f2A4df3772E59A70B95E5EB44

ShopTreasuryAllocRouter

0x29e82056464b6b0A077A2f8dc34d9b412ee86fe4

GameTreasuryAllocRouter

0x41BA615d842A5A0f3f5968792bB5E498cF1Df2ac

InfinityStakingTreasuryAllocRouter

0x3681D33845461e3C04af19BF6b74630e3f85D9bC

BadgeTreasuryAllocRouter

0xeA55c2C915dA8433B45651996880AEBCD8D0b8BE

TradingFeeRouter

0x877556d975B335d93D61a9F4A0607Cb9d6A7D6c4

ExcessUSDTRouter

0x8102B6694d1f9443137c9De2129aa1345Ad778aA

SacrificeProxy (Shop)

0x06A0FBa1807189Ba6cbB335074C5F24ffA0a4010

SacrificeProxy (Game)

0x23D8C57AC649E88803745Ce95Bd76D841e3E86Fc

SacrificeProxy (Staking)

0x0dEc4D8ce458DD611DdD416571d72D19385ce5D0

SacrificeProxy (Badge)

0xe13FED4754F9aFaA68Fb4f20c23b0B54fd3539C2

ReferralRegistry

0xec7fddB7381b3a9e48deCaAA1A5D77634E33BF9B

Raise

0xe17aCba439BbFCd186c62834D5106Bc059C71F5d

PGMTest Token

0x86CbFf4F8934126AB448aD30AeCA797c06eeF1d1


Test Wallets

Wallet
Role
Address
Abscan

W0

Deployer

0x689B768D3F0ed429bFB60cf5C4D768DBBCb34763

W1

Passive Investor

0x29549CfF7542BEE4F2AA3FeE483c2547DA91E09d

W2

Multi-Deposit Investor

0x54fFF072e36c578b5D8b80ec5102C1FF9A072652

W3

Sacrifice Investor

0x8868EFAB4df386cD6dcDa56DE8ab489b52950f2c

W4

Buyback Trigger (no investment)

0x6d69d48e2F04F11d55c15048593299471Eba889b

W4b

Trader (buy/sell on DEX)

0x7ee5d265aB6F974952E6086A7cF2EB76224EA814

W5

Late Investor (triggers refund mode)

0x96B08DA3B56424d11cea97F86c1b7EB4ED9351c9

W6

Emergency Withdraw Investor

0x23366200787612f93d8af03ccFA91d1C1FE11748


Deployment

All contracts were deployed on Abstract Chain mainnet using Foundry (forge script --broadcast). Each step below was executed as a separate transaction from the specified wallet.


Transaction Reference

All transactions are on Abstract Chain mainnet. Click any TX hash to verify on Abscan.

Step
Action
Wallet
TX Hash

1n

Fund pool setup (0.02 USDT)

W0

2

W1 deposit 10 USDT

W1

3

W2 deposit 5 USDT

W2

4

W2 deposit 5 USDT (2nd)

W2

5

W3 deposit 10 USDT

W3

6a

W3 sacrifice Shop (1 USDT)

W3

6b

W3 sacrifice Game (1 USDT)

W3

6c

W3 sacrifice Staking (1 USDT)

W3

6d

W3 sacrifice Badge (1 USDT)

W3

7

W5 deposit 10 USDT

W5

7b

W6 deposit 5 USDT

W6

8b

W6 emergencyWithdraw → 5 USDT

W6

10

W1 claim 10000 PGM

W1

11a

W2 claim 5000 PGM

W2

11b

W2 claim 5000 PGM

W2

12b

W3 claim 6000 PGM

W3

13

W5 claim 10000 PGM

W5

14

W1 redeem → 10 USDT (KEY PROOF)

W1

15a

W2 redeem 9000 → 9 USDT

W2

15c

W3 redeem 6000 → 6 USDT

W3

17

W4 triggerBuyback 0.5 USDT

W4

19c

W4b redeem ~150 PGM

W4b

21

W1 collectExcessUSDT → 0.346 USDT

W1

22

W5 redeem → 10 USDT (REFUND MODE)

W5

DEX trades (W2 sell, W4b buys/sells) are visible in the wallet histories linked in the Test Wallets table above, and on DexScreenerarrow-up-right.


Test Execution — Step by Step

Test Phase 1: Pre-Launch Deposits

Step 1 — W0 deploys all contracts

Step 2 — W1 deposits 10 USDT

Step 3 — W2 deposits 5 USDT (first)

Step 4 — W2 deposits 5 USDT (second)

Step 5 — W3 deposits 10 USDT

Step 6a — W3 sacrifices 1 USDT to Shop

Step 6b — W3 sacrifices 1 USDT to Game

Step 6c — W3 sacrifices 1 USDT to Staking

Step 6d — W3 sacrifices 1 USDT to Badge

Step 7 — W5 deposits 10 USDT

Step 7b — W6 deposits 5 USDT

State after all deposits: Total 45 USDT deposited, buybackReserve = 41 USDT (after 4 USDT sacrifice)


Test Phase 2: Launch

Step 8 — W2 calls launch() (not deployer!)


Test Phase 2b: Emergency Withdraw

Step 8b — W6 calls emergencyWithdraw()


Test Phase 3: Finalize

Step 9 — W1 calls finalize() (not deployer!)


Test Phase 4: Claim

Step 10 — W1 claims ALL (10,000 PGM)

Step 11a — W2 partial claim (5,000 PGM)

Step 11b — W2 claims remaining (5,000 PGM)

Step 12a — W3 tries to over-claim (REVERT)

  • Tries claim(10,000 PGM) but only 6,000 available after sacrifice

  • Result: reverts with "bad amount"

Step 12b — W3 claims correct amount (6,000 PGM)

Step 13 — W5 claims ALL (10,000 PGM)


Test Phase 5: Redeem

Step 14 — W1 redeems ALL — THE KEY PROOF

  • Result: W1 receives 10 USDT (exact deposit amount)

  • Passive investor deposits 10 USDT, gets 10 USDT back. Zero loss.

Step 15a — W2 redeems 9,000 PGM (90%)

Step 15b — W3 tries to over-redeem (REVERT)

  • Tries redeem(10,000 PGM) but only holds 6,000

  • Result: reverts with "insufficient PGM"

Step 15c — W3 redeems ALL after sacrifice (6,000 PGM)


Test Phase 6: Price Drop and Buyback

Step 16 — W2 sells remaining 1,000 PGM on DEX

Step 17 — W4 triggers buyback (never invested!)

  • Calls triggerBuyback(500000) — spends 0.5 USDT from reserve, buys 836 PGM, burns them

  • Proves: buyback is permissionless — anyone can defend the floor


Test Phase 7: Trading

Step 18a/b — W4b buys PGM on DEX (2 + 8 USDT)

Step 19a/b — W4b sells PGM on DEX

Step 19c — W4b redeems remaining ~150 PGM

Step 20 — W3 calls collectTradingFees()

  • Result: 0.031 USDT in LP fees sent to TradingFeeRouter

  • Proves: only trading fees (LP earnings) are collected — not investor funds


Test Phase 8: Excess USDT Collection

Step 21 — W1 calls collectExcessUSDT()

  • Result: 0.346 USDT excess sent to ExcessUSDTRouter

  • Excess arose because W2 sold PGM on DEX (Step 16) instead of redeem, then buyback burned PGM — reducing circulating supply below what the reserve was backing

  • Proves: excess collection cannot drain the floor — the invariant holds


Test Phase 9: Last Investor Redeems (Refund Mode)

Step 22 — W5 redeems ALL — REFUND MODE

  • buybackReserve was 8.2 USDT but W5 needs 10 USDT

  • Within this single TX, redeem() automatically activates refund mode:

    • Dissolves floor protection LP NFT

    • Recovers USDT from LP into refundReserve

    • Burns PGM recovered from LP

    • Completes redemption from buybackReserve + refundReserve

  • Result: W5 receives 10 USDT (full deposit)

  • Proves: even the last investor gets full principal back — refund mode works automatically


Additional Revert Tests (proven on-chain)

During the test, we also verified that the contract correctly prevents invalid operations:

Action
Expected Revert
Actual Result

W1 tries claim() before finalize

"not finalized"

✅ Reverted correctly

W1 tries redeem() before finalize

"insufficient PGM"

✅ Reverted correctly

W2 tries launch() again after launch

"already launched"

✅ Reverted correctly

W3 tries deposit() after launch

"launched"

✅ Reverted correctly

W6 tries emergencyWithdraw() before deadline

"too early"

✅ Reverted correctly

W3 tries claim(10000 PGM) with only 6000 available

"bad amount"

✅ Reverted correctly

W3 tries redeem(10000 PGM) with only 6000 held

"insufficient PGM"

✅ Reverted correctly


End State

After all test steps completed, verified on-chain:

Wallet
PGM held
USDT received
Status

W0 (Deployer)

0

0

Never invested, only deployed

W1 (Passive)

0

10 USDT

Full principal returned via redeem

W2 (Multi-Deposit)

0

9 USDT + 0.64 USDT from DEX sale

Partial redeem + DEX sell

W3 (Sacrifice)

0

6 USDT

Correct: 10 deposited - 4 sacrificed = 6 returned

W4 (Buyback)

0

0

Never invested, triggered buyback with 0.5 USDT from reserve

W4b (Trader)

0

~9.97 USDT (from DEX trading + redeem)

Bought 10 USDT of PGM, sold + redeemed

W5 (Late)

0

10 USDT

Full principal returned — triggered refund mode automatically

W6 (Emergency)

0

5 USDT

Full principal returned via emergency withdraw

Final contract state:

  • buybackReserve: 0 USDT (fully used)

  • refundReserve: 0.013 USDT (dust remaining after refund mode)

  • refundMode: true (activated by W5's redeem)

  • totalPGMMinted: 40,000 PGM

  • totalPGMBurned: 35,987 PGM

  • ExcessUSDTRouter received: 0.346 USDT (real excess from DEX sell + buyback burn)

  • TradingFeeRouter received: 0.031 USDT (LP trading fees only)

PGM supply remaining: only the upside price discovery PGM locked in the upside LP NFT. All investor PGM has been burned through redeems and buybacks. No wallet holds any PGM.


How to Verify

Every transaction is on-chain and verifiable. Click any wallet address in the table above to see all transactions chronologically on Abscan. The Raise contract address shows all interactions from all wallets.

Key verification links:


Summary of On-Chain Proofs

What
Proven By
Result

Passive investor loses $0

W1: deposit 10 → redeem 10

Multiple deposits work

W2: deposit 5 + 5 = 10

Partial claim works

W2: claim 5000, then claim 5000 more

Over-claim reverts

W3: tries to claim 10000 with only 6000 available

Over-redeem reverts

W3: tries to redeem 10000 with only 6000 held

Partial redeem works

W2: redeem 9000 of 10000

All 4 sacrifice paths work

W3: sacrifice to Shop, Game, Staking, Badge (1 USDT each)

Sacrifice math is correct

W3: deposit 10, sacrifice 4, redeem 6

Emergency withdraw works

W6: deposit 5, emergency withdraw 5

Emergency withdraw before deadline reverts

W6: "too early"

Launch is permissionless

W2 (not deployer) calls launch()

Finalize is permissionless

W1 (not deployer) calls finalize()

Double launch reverts

W2: "already launched"

Deposit after launch reverts

W3: "launched"

Claim before finalize reverts

W1: "not finalized"

Buyback is permissionless

W4 (non-investor) triggers buyback

Buyback buys + burns PGM

Reserve decreased, totalPGMBurned increased

Trading works on DEX

W4b buys and sells PGM on Aborean

Trading fees collected correctly

collectTradingFees() → 0.031 USDT to TradingFeeRouter

Excess only takes real excess

collectExcessUSDT() → 0.346 USDT to ExcessUSDTRouter

Redeem works after trading

W4b redeems after buy/sell activity

Refund mode activates automatically

W5 redeem triggers LP dissolution in single TX

Late investors are protected

W5: deposit 10 → redeem 10 (via refund mode)

Minter permanently renounced

After finalize, no new PGM possible

Every single transaction listed above is verifiable on Abscanarrow-up-right. The contract source code matches the production raise contract byte-for-byte (only LAUNCH_TIME, EMERGENCY_DEADLINE, and token name differ — all visible as constructor arguments on Abscan).

Last updated

Was this helpful?