From 0625ad6c9458c7428c1de27759fa0c1f931c9300 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Sun, 14 Jun 2026 17:31:13 -0600 Subject: [PATCH] docs(distribution): sync 100m launch parameters --- deploy/MAINNET-PARAMETERS.md | 10 +-- deploy/config/base-mainnet.json | 2 +- packages/migration-claim/README.md | 24 ++++-- .../docs/KITE_TESTNET_GUIDE.md | 13 +++- .../script/DeployTangleMigration.s.sol | 41 +++++----- .../scripts/deploy-tangle-migration.sh | 75 ++++++++----------- .../migration-claim/src/TangleMigration.sol | 2 +- .../test/TangleMigration.t.sol | 6 +- 8 files changed, 87 insertions(+), 86 deletions(-) diff --git a/deploy/MAINNET-PARAMETERS.md b/deploy/MAINNET-PARAMETERS.md index ec55780f..4ebd227c 100644 --- a/deploy/MAINNET-PARAMETERS.md +++ b/deploy/MAINNET-PARAMETERS.md @@ -58,7 +58,7 @@ never calls the setters that would write the secure values. | `stakeAssets[EIGEN].depositCap` | 1M | **250k** | Right-size before any future enablement (entry stays `0x0`/disabled) | | `stakeAssets[USDe].depositCap` | 15M | **5M** | Risk right-size (disabled) | | `stakeAssets[stETH/wstETH].depositCap` | 30k each | **15k each** | Same Lido underlying — treat as one family budget (15k each = 30k aggregate) | -| **+ `governance` block** | (absent) | votingDelay 1d / votingPeriod 7d / proposalThreshold 200k TNT / quorum 6% / timelockDelay 4d | Pin launch governance; conservative-start | +| **+ `governance` block** | (absent) | votingDelay 1d / votingPeriod 7d / proposalThreshold 100k TNT / quorum 4% / timelockDelay 4d | Pin launch governance; thin-float-aware conservative start | | **+ `slashing` block** | (absent) | maxSlashBps 50% / disputeWindow 7d / disputeBond 0.02 ETH / resolutionDeadline 21d / maxPending 8 | Drives `setSlashConfig`; removes 100%-slash + free-dispute defaults | | **+ `payments` block** | (absent) | 2000/1950/4000/2000/**50** (dev/protocol/operator/staker/keeper) | Drives `setPaymentSplit`; keeper market for permissionless billing | @@ -124,10 +124,10 @@ signalling high dilution. **Governance launch values (thin-float-aware).** `votingDelay 1d / votingPeriod 7d / proposalThreshold 100k TNT / quorum 4% / timelockDelay 4d`. The non-obvious driver: quorum is `% of getPastTotalSupply` = the full -109.26M minted at genesis, but most supply is vesting-locked and undelegated at launch (Substrate+EVM unlock -only 10% at TGE; Treasury 0%, Foundation 30%), so realistic delegatable float is single-digit millions. A high -quorum would *brick* governance. 4% (~4.37M votes) is reachable with engagement; 100k proposalThreshold is a -spam floor that isn't paralyzing on thin float. *Alternatives:* quorum 3% if early participation is weak, 6% +100M minted at genesis, but most supply is vesting-locked and undelegated at launch (Substrate unlocks +10% at claim, Treasury 0%, Foundation 30%), so realistic delegatable float is single-digit millions. A high +quorum would *brick* governance. 4% (= 4,000,000 votes at the 100M cap) is reachable with engagement; 100k +proposalThreshold is a spam floor that isn't paralyzing on thin float. *Alternatives:* quorum 3% if early participation is weak, 6% once float deepens (ratchet up via governance as vesting unlocks over 3yr). `proposalThreshold` 200k if you expect strong delegation. The real defense against a low-quorum capture proposal is the **CANCELLER guardian Safe below**, not a high quorum — wire it. diff --git a/deploy/config/base-mainnet.json b/deploy/config/base-mainnet.json index 51322e40..05bf7af8 100644 --- a/deploy/config/base-mainnet.json +++ b/deploy/config/base-mainnet.json @@ -188,7 +188,7 @@ }, "_note_governance_slashing_payments": "These three blocks are consumed by deploy/deploy-all.sh (the prod orchestrator) AFTER core deploy. governance -> script/DeployGovernance.s.sol (deploy Timelock+Governor, then put the Timelock address in roles.timelock). slashing -> Tangle.setSlashConfig. payments -> Tangle.setPaymentSplit. Without these steps mainnet ships the insecure hardcoded defaults (maxSlashBps=100%, disputeBond=0, keeperBps=0). See deploy/MAINNET-PARAMETERS.md for rationale.", "governance": { - "_note": "Quorum is % of getPastTotalSupply = the full 109.26M minted at genesis, but most supply is vesting-locked/undelegated at launch (substrate+EVM unlock only 10% at TGE; treasury 0%, foundation 30%). Realistic delegatable float at launch is single-digit millions, so a high quorum BRICKS governance. quorumPercent=4 (~4.37M votes) is reachable with engagement; proposalThreshold 100k TNT is a spam floor that isn't paralyzing on thin float. Conservative-start: ratchet quorum up via governance as vesting unlocks over 3yr. STRONGLY pair with an independent CANCELLER_ROLE guardian Safe (see openDecisions) — it is the real defense against a low-quorum capture proposal, not a high quorum. Alternatives: quorum 3% if early participation is weak, or 6% only once float deepens.", + "_note": "Quorum is % of getPastTotalSupply = the full 100M minted at genesis, but most supply is vesting-locked/undelegated at launch (Substrate unlocks 10% at claim; Treasury 0%; Foundation 30%). Realistic delegatable float at launch is single-digit millions, so a high quorum bricks governance. quorumPercent=4 (= 4,000,000 votes at the 100M cap) is reachable with engagement; proposalThreshold 100k TNT is a spam floor that is not paralyzing on thin float. Conservative start: ratchet quorum up via governance as vesting unlocks over 3yr. Strongly pair with an independent CANCELLER_ROLE guardian Safe (see openDecisions); it is the real defense against a low-quorum capture proposal, not a high quorum. Alternatives: quorum 3% if early participation is weak, or 6% only once float deepens.", "votingDelay": 86400, "votingPeriod": 604800, "proposalThreshold": "100000000000000000000000", diff --git a/packages/migration-claim/README.md b/packages/migration-claim/README.md index 21208d20..66af0ca4 100644 --- a/packages/migration-claim/README.md +++ b/packages/migration-claim/README.md @@ -1,6 +1,10 @@ # TNT Substrate → EVM Migration (SP1) -This subpackage (`packages/migration-claim`) contains the SP1/ZK-based migration claim system for TNT, plus scripts and real snapshot outputs for testnet/mainnet dry runs. +This subpackage (`packages/migration-claim`) contains the SP1/ZK-based migration claim system for TNT, plus scripts and snapshot outputs used by deployment rehearsals. + +Mainnet genesis is normalized to exactly 100,000,000 TNT in `deploy/distributions/normalized-100m.json`. +That file is the distribution source of truth: active Substrate claims, active EVM claims, the foundation +bucket, and the treasury balancer must sum to `TangleToken.MAX_SUPPLY`. ## What’s Included @@ -10,19 +14,20 @@ This subpackage (`packages/migration-claim`) contains the SP1/ZK-based migration - `src/lockups/TNTVestingFactory.sol` + `src/lockups/TNTLinearVesting.sol`: per-beneficiary linear vesting contracts. - `src/TNT.sol`: simple mintable ERC20 used for local testing only (production can use the canonical TNT token from `tnt-core`). -**Real snapshot outputs (kept in-repo for reproducible testing)** +**Snapshot outputs (kept in-repo for reproducible testing)** - `packages/migration-claim/merkle-tree.json`: Merkle root + per-SS58 proofs. - `packages/migration-claim/evm-claims.json`: EVM recipient list + amounts. -- `packages/migration-claim/treasury-carveout.json`: Sum of non-claimable Substrate module accounts (sent to the EVM treasury at deploy). -- `packages/migration-claim/foundation-carveout.json`: Optional carveout for the foundation allocation (sent fully liquid at deploy). +- `packages/migration-claim/treasury-carveout.json`: Treasury bucket input before normalization. +- `packages/migration-claim/foundation-carveout.json`: Foundation bucket input before deployment vesting policy is applied. -If you need to carve out additional non-claimable pubkeys (beyond `modl*` module accounts), add them to `treasury-carveout.json` and re-run `scripts/carveoutTreasury.ts` (or pass `--treasury-pubkey 0x...`). +If you regenerate the snapshot, update `deploy/distributions/normalized-100m.json` and run +`python3 deploy/distributions/reconcile.py`. Treasury is the balancing bucket; the 100M cap does not move. ## Vesting Schedule (default) Claims split into: -- `unlockedBps = 200` (2%) transferred immediately to the recipient at TGE. -- `vestedAmount` (98%) transferred to a deterministic `TNTLinearVesting` contract for the recipient. +- `unlockedBps = 1000` (10%) transferred immediately to the recipient at claim time. +- `vestedAmount` (90%) transferred to a deterministic `TNTLinearVesting` contract for the recipient. **Default vesting parameters:** - 12-month cliff (365 days) - no tokens vest during this period @@ -33,6 +38,11 @@ You can update vesting config via `TangleMigration.setVestingConfig(...)` only w Vesting contracts are created with `delegatee = recipient` so (if the token supports `IVotes`) the recipient can use voting power while tokens are locked. +`FullDeploy` handles the treasury and foundation buckets separately from user claims: + +- Treasury: 0% unlocked, 6-month cliff, 30-month linear vest. +- Foundation: 30% unlocked, 6-month cliff, 30-month linear vest. + ## Merkle Format Each Merkle value is `(bytes32 pubkey, uint256 amount)` where `pubkey` is the 32-byte SR25519 public key (derived from SS58). diff --git a/packages/migration-claim/docs/KITE_TESTNET_GUIDE.md b/packages/migration-claim/docs/KITE_TESTNET_GUIDE.md index 472f8905..3ac47433 100644 --- a/packages/migration-claim/docs/KITE_TESTNET_GUIDE.md +++ b/packages/migration-claim/docs/KITE_TESTNET_GUIDE.md @@ -68,7 +68,10 @@ Save the `PROGRAM_VKEY` from the output. ## Step 3: Deploy Migration Contracts -The migration includes token allocations for the foundation and liquidity operations. For testnet, use your deployer address as the recipient for both. +The wrapper reads the normalized 100M distribution from `deploy/distributions/normalized-100m.json` when +run from the repo. It uses the same four buckets as the production deploy path: Substrate claims, active EVM +claims, foundation, and treasury. For testnet, use your deployer address as the treasury and foundation +recipient. ```bash cd packages/migration-claim @@ -77,13 +80,15 @@ PRIVATE_KEY=0x... \ PROGRAM_VKEY=0x \ SP1_VERIFIER=0x \ FOUNDATION_RECIPIENT=0x \ -LIQUIDITY_OPS_RECIPIENT=0x \ +TREASURY_RECIPIENT=0x \ ./scripts/deploy-tangle-migration.sh --kite ``` **Environment variables:** - `FOUNDATION_RECIPIENT`: EVM address to receive foundation tokens (~15M TNT) -- `LIQUIDITY_OPS_RECIPIENT`: EVM address to receive liquidity/ops tokens (5M TNT) +- `TREASURY_RECIPIENT`: EVM address to receive treasury tokens (~35.64M TNT) + +The current normalized distribution has no liquidity-ops bucket and no active EVM allocation. Save the deployed addresses: - `TNT_TOKEN` @@ -272,7 +277,7 @@ export PRIVATE_KEY=0x... export PROGRAM_VKEY=0x... export SP1_VERIFIER=0x... export FOUNDATION_RECIPIENT=0x... # Receives ~15M TNT (use deployer address for testnet) -export LIQUIDITY_OPS_RECIPIENT=0x... # Receives 5M TNT (use deployer address for testnet) +export TREASURY_RECIPIENT=0x... # Receives ~35.64M TNT (use deployer address for testnet) # Relayer export RELAYER_PRIVATE_KEY=0x... diff --git a/packages/migration-claim/script/DeployTangleMigration.s.sol b/packages/migration-claim/script/DeployTangleMigration.s.sol index ae23bda0..f4ef039a 100644 --- a/packages/migration-claim/script/DeployTangleMigration.s.sol +++ b/packages/migration-claim/script/DeployTangleMigration.s.sol @@ -16,8 +16,8 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol * * Environment Variables (Required): * MERKLE_ROOT - Merkle root from migration snapshot - * TOTAL_SUBSTRATE - Exact total for Substrate claims (from distribution.json) - * TOTAL_EVM - Exact total for EVM airdrop (from distribution.json) + * TOTAL_SUBSTRATE - Exact total for Substrate claims (from normalized-100m.json) + * TOTAL_EVM - Exact total for active EVM claims (currently 0 in normalized-100m.json) * * Environment Variables (Optional): * PRIVATE_KEY - Deployer private key (default: Anvil account 0) @@ -29,18 +29,18 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol * TREASURY_RECIPIENT - Address to receive treasury allocation (vested) * TREASURY_AMOUNT - Treasury allocation in wei (0% unlocked, 100% vested) * FOUNDATION_RECIPIENT - Address to receive foundation allocation - * FOUNDATION_AMOUNT - Foundation allocation in wei (2% of total supply unlocked, rest vested) - * LIQUIDITY_OPS_RECIPIENT - Address to receive liquidity ops allocation - * LIQUIDITY_OPS_AMOUNT - Liquidity ops allocation in wei (100% liquid) + * FOUNDATION_AMOUNT - Foundation allocation in wei (30% unlocked, rest vested) + * LIQUIDITY_OPS_RECIPIENT - Legacy test-only liquidity ops recipient + * LIQUIDITY_OPS_AMOUNT - Legacy test-only liquidity ops amount in wei * * Usage: - * # Use the deploy-migration.sh wrapper script which reads from distribution.json: + * # Use the deploy-migration.sh wrapper script which reads normalized-100m.json: * ./scripts/local-env/deploy-migration.sh * * # Or manually with exact values: * MERKLE_ROOT=0x824b... \ - * TOTAL_SUBSTRATE=108138164691043996671207028 \ - * TOTAL_EVM=1125776519168932493729792 \ + * TOTAL_SUBSTRATE=49322182835914246230618074 \ + * TOTAL_EVM=0 \ * USE_MOCK_VERIFIER=true \ * forge script script/DeployTangleMigration.s.sol:DeployTangleMigration \ * --rpc-url http://localhost:8545 --broadcast @@ -183,13 +183,13 @@ contract DeployTangleMigration is Script { console.log(" Remaining in deployer:", evmAllocation / 1e18, "TNT"); console.log(" Run ExecuteEVMAirdrop to distribute to", "EVM holders"); - // 8. Optional: Treasury allocation (0% unlocked, 100% vested with 12-month cliff + 24-month linear) + // 8. Optional: Treasury allocation (0% unlocked, 100% vested with 6-month cliff + 30-month linear) if (treasuryAmount > 0) { require(treasuryRecipient != address(0), "TREASURY_RECIPIENT required when TREASURY_AMOUNT > 0"); // Treasury: 0% unlocked, 100% goes to vesting contract - // 12-month cliff + 24-month linear = 3 years total - TNTVestingFactory treasuryVestingFactory = new TNTVestingFactory(365 days, 730 days); + // 6-month cliff + 30-month linear = 3 years total + TNTVestingFactory treasuryVestingFactory = new TNTVestingFactory(180 days, 912 days); // forge-lint: disable-next-line(unsafe-typecast) address treasuryVesting = treasuryVestingFactory.getOrCreateVesting( configuredTnt, @@ -203,23 +203,22 @@ contract DeployTangleMigration is Script { console.log(" Total:", treasuryAmount / 1e18, "TNT"); console.log(" Vesting contract:", treasuryVesting); console.log(" Beneficiary:", treasuryRecipient); - console.log(" Cliff: 12 months, Linear: 24 months (3 years total)"); + console.log(" Cliff: 6 months, Linear: 30 months (3 years total)"); } - // 9. Optional: Foundation allocation (2% of total supply unlocked, rest vested with 12-month cliff + 24-month linear) + // 9. Optional: Foundation allocation (30% unlocked, rest vested with 6-month cliff + 30-month linear) if (foundationAmount > 0) { require(foundationRecipient != address(0), "FOUNDATION_RECIPIENT required when FOUNDATION_AMOUNT > 0"); - // Foundation: 2% of TOTAL SUPPLY unlocked immediately, rest vested - uint256 foundationUnlocked = (totalSupply * 200) / 10_000; // 2% of total supply - require(foundationUnlocked <= foundationAmount, "Foundation allocation too small for 2% total supply unlock"); + // Foundation: 30% of its allocation unlocked immediately, rest vested. + uint256 foundationUnlocked = (foundationAmount * 3000) / 10_000; uint256 foundationVested = foundationAmount - foundationUnlocked; // Transfer unlocked portion directly require(tntToken.transfer(foundationRecipient, foundationUnlocked), "Foundation unlocked transfer failed"); - // Create vesting for the rest (12-month cliff + 24-month linear = 3 years) - TNTVestingFactory foundationVestingFactory = new TNTVestingFactory(365 days, 730 days); + // Create vesting for the rest (6-month cliff + 30-month linear = 3 years) + TNTVestingFactory foundationVestingFactory = new TNTVestingFactory(180 days, 912 days); // forge-lint: disable-next-line(unsafe-typecast) address foundationVesting = foundationVestingFactory.getOrCreateVesting( configuredTnt, @@ -229,12 +228,12 @@ contract DeployTangleMigration is Script { ); require(tntToken.transfer(foundationVesting, foundationVested), "Foundation vesting transfer failed"); - console.log("\n6. Foundation Allocation (2% of total supply unlocked):"); + console.log("\n6. Foundation Allocation (30% unlocked):"); console.log(" Total:", foundationAmount / 1e18, "TNT"); - console.log(" Unlocked (2% of total supply):", foundationUnlocked / 1e18, "TNT to", foundationRecipient); + console.log(" Unlocked:", foundationUnlocked / 1e18, "TNT to", foundationRecipient); console.log(" Vested:", foundationVested / 1e18, "TNT"); console.log(" Vesting contract:", foundationVesting); - console.log(" Cliff: 12 months, Linear: 24 months (3 years total)"); + console.log(" Cliff: 6 months, Linear: 30 months (3 years total)"); } // 10. Optional: Liquidity Ops allocation (100% liquid for liquidity/operational expenses) diff --git a/packages/migration-claim/scripts/deploy-tangle-migration.sh b/packages/migration-claim/scripts/deploy-tangle-migration.sh index 0e8ac400..b4ea14ee 100755 --- a/packages/migration-claim/scripts/deploy-tangle-migration.sh +++ b/packages/migration-claim/scripts/deploy-tangle-migration.sh @@ -7,14 +7,12 @@ # 3. TangleMigration contract (with merkle root and funding) # 4. Treasury vesting (if TREASURY_RECIPIENT set) # 5. Foundation vesting (if FOUNDATION_RECIPIENT set) -# 6. Liquidity ops transfer (if LIQUIDITY_OPS_RECIPIENT set) # -# Reads allocations from JSON files: -# - merkle-tree.json: Substrate claims (merkle root + total) -# - evm-claims.json: EVM claims (may be 0 if excluded) -# - treasury-carveout.json: Treasury allocation -# - foundation-carveout.json: Foundation allocation -# - liquidity-ops-carveout.json: Liquidity ops allocation +# Reads allocations from deploy/distributions/normalized-100m.json when present: +# - substrate: Substrate claims +# - evm: active EVM claims, currently 0 +# - treasury: treasury balancer +# - foundation: foundation allocation # # Prerequisites: # - Foundry installed @@ -25,7 +23,7 @@ # PRIVATE_KEY (required) # TREASURY_RECIPIENT - Address to receive treasury allocation (vested) # FOUNDATION_RECIPIENT - Address to receive foundation allocation -# LIQUIDITY_OPS_RECIPIENT - Address to receive liquidity ops allocation +# LIQUIDITY_OPS_RECIPIENT - Legacy test-only liquidity ops recipient # PROGRAM_VKEY - SP1 program verification key (required for --base-sepolia, --kite-testnet) # SP1_VERIFIER - SP1 verifier gateway address (required for --kite-testnet) # @@ -112,6 +110,7 @@ fi # Check prerequisites command -v forge >/dev/null 2>&1 || { echo "Error: Foundry not installed"; exit 1; } +command -v jq >/dev/null 2>&1 || { echo "Error: jq not installed"; exit 1; } # PRIVATE_KEY is required if [ -z "$PRIVATE_KEY" ]; then @@ -163,54 +162,44 @@ if ! cast block-number --rpc-url "$RPC_URL" >/dev/null 2>&1; then exit 1 fi -# Read merkle root and total substrate allocation from the generated tree +# Read merkle root from the generated tree if [ -f "$ROOT_DIR/merkle-tree.json" ]; then MERKLE_ROOT=$(grep -o '"root": "0x[a-fA-F0-9]\{64\}"' "$ROOT_DIR/merkle-tree.json" | grep -o '0x[a-fA-F0-9]\{64\}') - TOTAL_SUBSTRATE=$(grep -o '"totalValue": "[0-9]*"' "$ROOT_DIR/merkle-tree.json" | grep -o '[0-9]*') echo "Merkle Root: $MERKLE_ROOT" - echo "Total Substrate: $TOTAL_SUBSTRATE" else echo "Error: merkle-tree.json not found at $ROOT_DIR" echo "Please run the migration snapshot generator first." exit 1 fi -# Read total EVM allocation from evm-claims.json (may be 0 if claims excluded) -if [ -f "$ROOT_DIR/evm-claims.json" ]; then - TOTAL_EVM=$(grep -o '"totalAmount": "[0-9]*"' "$ROOT_DIR/evm-claims.json" | grep -o '[0-9]*') - if [ -z "$TOTAL_EVM" ]; then - TOTAL_EVM="0" - fi - echo "Total EVM: $TOTAL_EVM" -else - echo "Warning: evm-claims.json not found, setting TOTAL_EVM=0" - TOTAL_EVM="0" -fi - -# Read treasury carveout from treasury-carveout.json -if [ -f "$ROOT_DIR/treasury-carveout.json" ]; then - TREASURY_AMOUNT=$(grep -o '"amount": "[0-9]*"' "$ROOT_DIR/treasury-carveout.json" | grep -o '[0-9]*') - echo "Treasury Amount: $TREASURY_AMOUNT" -else - echo "Warning: treasury-carveout.json not found" - TREASURY_AMOUNT="0" -fi - -# Read foundation carveout from foundation-carveout.json -if [ -f "$ROOT_DIR/foundation-carveout.json" ]; then - FOUNDATION_AMOUNT=$(grep -o '"amount": "[0-9]*"' "$ROOT_DIR/foundation-carveout.json" | grep -o '[0-9]*') - echo "Foundation Amount: $FOUNDATION_AMOUNT" +# Prefer the normalized 100M distribution used by FullDeploy. +DIST_FILE="$ROOT_DIR/../../deploy/distributions/normalized-100m.json" +if [ -f "$DIST_FILE" ]; then + TOTAL_SUBSTRATE=$(jq -r '.buckets.substrate.wei' "$DIST_FILE") + TOTAL_EVM=$(jq -r '.buckets.evm.wei' "$DIST_FILE") + TREASURY_AMOUNT=$(jq -r '.buckets.treasury.wei' "$DIST_FILE") + FOUNDATION_AMOUNT=$(jq -r '.buckets.foundation.wei' "$DIST_FILE") + LIQUIDITY_OPS_AMOUNT="0" + echo "Distribution: $DIST_FILE" else - echo "Warning: foundation-carveout.json not found" - FOUNDATION_AMOUNT="0" + echo "Warning: normalized-100m.json not found; falling back to package-local snapshot files" + TOTAL_SUBSTRATE=$(grep -o '"totalValue": "[0-9]*"' "$ROOT_DIR/merkle-tree.json" | grep -o '[0-9]*') + TOTAL_EVM=$(grep -o '"totalAmount": "[0-9]*"' "$ROOT_DIR/evm-claims.json" 2>/dev/null | grep -o '[0-9]*' || true) + TREASURY_AMOUNT=$(grep -o '"amount": "[0-9]*"' "$ROOT_DIR/treasury-carveout.json" 2>/dev/null | grep -o '[0-9]*' || true) + FOUNDATION_AMOUNT=$(grep -o '"amount": "[0-9]*"' "$ROOT_DIR/foundation-carveout.json" 2>/dev/null | grep -o '[0-9]*' || true) + LIQUIDITY_OPS_AMOUNT=$(grep -o '"amount": "[0-9]*"' "$ROOT_DIR/liquidity-ops-carveout.json" 2>/dev/null | grep -o '[0-9]*' || true) + TOTAL_EVM="${TOTAL_EVM:-0}" + TREASURY_AMOUNT="${TREASURY_AMOUNT:-0}" + FOUNDATION_AMOUNT="${FOUNDATION_AMOUNT:-0}" + LIQUIDITY_OPS_AMOUNT="${LIQUIDITY_OPS_AMOUNT:-0}" fi -# Read liquidity ops carveout from liquidity-ops-carveout.json -if [ -f "$ROOT_DIR/liquidity-ops-carveout.json" ]; then - LIQUIDITY_OPS_AMOUNT=$(grep -o '"amount": "[0-9]*"' "$ROOT_DIR/liquidity-ops-carveout.json" | grep -o '[0-9]*') +echo "Total Substrate: $TOTAL_SUBSTRATE" +echo "Total EVM: $TOTAL_EVM" +echo "Treasury Amount: $TREASURY_AMOUNT" +echo "Foundation Amount: $FOUNDATION_AMOUNT" +if [ "$LIQUIDITY_OPS_AMOUNT" != "0" ]; then echo "Liquidity Ops Amount: $LIQUIDITY_OPS_AMOUNT" -else - LIQUIDITY_OPS_AMOUNT="0" fi cd "$ROOT_DIR" diff --git a/packages/migration-claim/src/TangleMigration.sol b/packages/migration-claim/src/TangleMigration.sol index 72802a86..1681fd46 100644 --- a/packages/migration-claim/src/TangleMigration.sol +++ b/packages/migration-claim/src/TangleMigration.sol @@ -144,7 +144,7 @@ contract TangleMigration is Ownable, ReentrancyGuard { adminClaimDeadline = block.timestamp + 60 days; - // Defaults: 2% unlocked, 98% vested over 18 months (6-month cliff + 12-month linear) + // Defaults: 10% unlocked, 90% vested over 36 months (12-month cliff + 24-month linear). unlockedBps = DEFAULT_UNLOCKED_BPS; vestingFactory = new TNTVestingFactory(DEFAULT_CLIFF_DURATION, DEFAULT_VESTING_DURATION); diff --git a/packages/migration-claim/test/TangleMigration.t.sol b/packages/migration-claim/test/TangleMigration.t.sol index 8355d202..fff1b984 100644 --- a/packages/migration-claim/test/TangleMigration.t.sol +++ b/packages/migration-claim/test/TangleMigration.t.sol @@ -73,8 +73,8 @@ contract TangleMigrationTest is Test { assertEq(migration.owner(), owner); assertEq(migration.treasury(), treasury); assertFalse(migration.paused()); - // New defaults: 2% unlocked - assertEq(migration.unlockedBps(), 200); + // Default claim schedule: 10% unlocked. + assertEq(migration.unlockedBps(), 1000); // Vesting config: 12-month cliff + 24-month linear (3 years total) assertEq(migration.cliffDuration(), 365 days); assertEq(migration.vestingDuration(), 730 days); @@ -512,8 +512,6 @@ contract TangleMigrationTest is Test { function test_LinearVesting_CannotReleaseBeforeCliff() public { bytes memory zkProof = ""; - uint256 vestedAmount = TEST_AMOUNT - (TEST_AMOUNT * migration.unlockedBps()) / 10_000; - vm.prank(claimer); migration.claimWithZKProof(TEST_PUBKEY, TEST_AMOUNT, merkleProof, zkProof, claimer);