diff --git a/src/lib/LibProdTokenConfig.sol b/src/lib/LibProdTokenConfig.sol index 6e100ff5..d380faf0 100644 --- a/src/lib/LibProdTokenConfig.sol +++ b/src/lib/LibProdTokenConfig.sol @@ -42,10 +42,10 @@ struct TokenConfig { /// means carrying that space forward; the parity pin would flag it as a /// divergence otherwise. library LibProdTokenConfig { - /// @notice The 41 production token deploy configs, Base table order. + /// @notice The 50 production token deploy configs, Base table order. /// @return configs The name/symbol table. function productionTokenConfigs() internal pure returns (TokenConfig[] memory configs) { - configs = new TokenConfig[](41); + configs = new TokenConfig[](50); configs[0] = TokenConfig("MSTR", "MicroStrategy Incorporated ST0x", "tMSTR"); configs[1] = TokenConfig("TSLA", "Tesla Inc ST0x", "tTSLA"); configs[2] = TokenConfig("COIN", "Coinbase Global Inc ST0x", "tCOIN"); @@ -88,5 +88,16 @@ library LibProdTokenConfig { configs[38] = TokenConfig("BABA", "Alibaba Group Holding Limited ADR ST0x", "tBABA"); configs[39] = TokenConfig("TQQQ", "ProShares UltraPro QQQ ST0x", "tTQQQ"); configs[40] = TokenConfig("FTF", "Franklin Limited Duration Income Trust ST0x", "tFTF"); + configs[41] = TokenConfig("CBRS", "Cerebras Systems Inc. ST0x", "tCBRS"); + configs[42] = TokenConfig("AIR.PA", "Airbus SE ST0x", "tAIR.PA"); + configs[43] = TokenConfig("BMW.DE", "Bayerische Motoren Werke Aktiengesellschaft ST0x", "tBMW.DE"); + // solc rejects a bare non-ASCII string literal; `unicode"..."` is the + // same bytes, and Base carries the ë — dropping it would break parity. + configs[44] = TokenConfig("MC.PA", unicode"LVMH Moët Hennessy Louis Vuitton SE ST0x", "tMC.PA"); + configs[45] = TokenConfig("SIE.DE", "Siemens Aktiengesellschaft ST0x", "tSIE.DE"); + configs[46] = TokenConfig("MBG.DE", "Mercedes-Benz Group AG ST0x", "tMBG.DE"); + configs[47] = TokenConfig("RHM.DE", "Rheinmetall AG ST0x", "tRHM.DE"); + configs[48] = TokenConfig("MCD", "McDonald's Corporation ST0x", "tMCD"); + configs[49] = TokenConfig("NKE", "NIKE, Inc. ST0x", "tNKE"); } } diff --git a/src/lib/LibTokenInvariants.sol b/src/lib/LibTokenInvariants.sol index 21debd43..3a62a784 100644 --- a/src/lib/LibTokenInvariants.sol +++ b/src/lib/LibTokenInvariants.sol @@ -389,14 +389,86 @@ library LibTokenInvariants { /// https://basescan.org/address/0x9bDe199Ac6E7E050334306D9267c93e3D6d38333 address internal constant FTF_WRAPPED_TOKEN_VAULT = address(0x9bDe199Ac6E7E050334306D9267c93e3D6d38333); - /// @notice Returns the 41 production token instance triples on Base, in + // ---- tCBRS / wtCBRS — Cerebras Systems Inc. ST0x ---- + /// https://basescan.org/address/0xAe8aD2340aa19749A0b935C7F2245823fC4F14FB + address internal constant CBRS_RECEIPT = address(0xAe8aD2340aa19749A0b935C7F2245823fC4F14FB); + /// https://basescan.org/address/0xBeB0c2011bd5520A0998b69132E9245E39Ac5D1D + address internal constant CBRS_RECEIPT_VAULT = address(0xBeB0c2011bd5520A0998b69132E9245E39Ac5D1D); + /// https://basescan.org/address/0xB457cfBF31995d3aAAa704dA9999cC0b011820ca + address internal constant CBRS_WRAPPED_TOKEN_VAULT = address(0xB457cfBF31995d3aAAa704dA9999cC0b011820ca); + + // ---- tAIR.PA / wtAIR.PA — Airbus SE ST0x ---- + /// https://basescan.org/address/0xa618f8eB7c33a23C84d1500c5191746f86F98b2A + address internal constant AIR_PA_RECEIPT = address(0xa618f8eB7c33a23C84d1500c5191746f86F98b2A); + /// https://basescan.org/address/0xDdB07ADd0e23BB7eC97f53C0959d9c6Cc09624f4 + address internal constant AIR_PA_RECEIPT_VAULT = address(0xDdB07ADd0e23BB7eC97f53C0959d9c6Cc09624f4); + /// https://basescan.org/address/0x1C600EF167c675C878BF3222f3935C4fA2A43C31 + address internal constant AIR_PA_WRAPPED_TOKEN_VAULT = address(0x1C600EF167c675C878BF3222f3935C4fA2A43C31); + + // ---- tBMW.DE / wtBMW.DE — Bayerische Motoren Werke Aktiengesellschaft ST0x ---- + /// https://basescan.org/address/0x30864F2921886Dc491326D86015eB66c9601BF2b + address internal constant BMW_DE_RECEIPT = address(0x30864F2921886Dc491326D86015eB66c9601BF2b); + /// https://basescan.org/address/0x9610C265EB8F38B22Fec78498C74924D9fe55891 + address internal constant BMW_DE_RECEIPT_VAULT = address(0x9610C265EB8F38B22Fec78498C74924D9fe55891); + /// https://basescan.org/address/0xD0269618455cF7dA71665856f16C2D03A1b26290 + address internal constant BMW_DE_WRAPPED_TOKEN_VAULT = address(0xD0269618455cF7dA71665856f16C2D03A1b26290); + + // ---- tMC.PA / wtMC.PA — LVMH Moët Hennessy Louis Vuitton SE ST0x ---- + /// https://basescan.org/address/0xBEDD4C7219E35E6C45BE792F31F076737481FF2c + address internal constant MC_PA_RECEIPT = address(0xBEDD4C7219E35E6C45BE792F31F076737481FF2c); + /// https://basescan.org/address/0xF5245a17E5eb64D53dEa213d40aBa01821D465Cd + address internal constant MC_PA_RECEIPT_VAULT = address(0xF5245a17E5eb64D53dEa213d40aBa01821D465Cd); + /// https://basescan.org/address/0xd92cc92557BFC33028195983ED31465F99b4A01c + address internal constant MC_PA_WRAPPED_TOKEN_VAULT = address(0xd92cc92557BFC33028195983ED31465F99b4A01c); + + // ---- tSIE.DE / wtSIE.DE — Siemens Aktiengesellschaft ST0x ---- + /// https://basescan.org/address/0xe89995E4Bf9691486445917e3C69ed3d935183f1 + address internal constant SIE_DE_RECEIPT = address(0xe89995E4Bf9691486445917e3C69ed3d935183f1); + /// https://basescan.org/address/0xa662066a60964a528aD05209139a79BDa3a7577f + address internal constant SIE_DE_RECEIPT_VAULT = address(0xa662066a60964a528aD05209139a79BDa3a7577f); + /// https://basescan.org/address/0xed0B0fdD92F7eece606A0FB0457352616d6e6B34 + address internal constant SIE_DE_WRAPPED_TOKEN_VAULT = address(0xed0B0fdD92F7eece606A0FB0457352616d6e6B34); + + // ---- tMBG.DE / wtMBG.DE — Mercedes-Benz Group AG ST0x ---- + /// https://basescan.org/address/0x984d884fc03D17e7b9cCfE6A32f27e9b6d9B92bd + address internal constant MBG_DE_RECEIPT = address(0x984d884fc03D17e7b9cCfE6A32f27e9b6d9B92bd); + /// https://basescan.org/address/0x07d7ca9384812b86e7E429473dF354fb59DA73A0 + address internal constant MBG_DE_RECEIPT_VAULT = address(0x07d7ca9384812b86e7E429473dF354fb59DA73A0); + /// https://basescan.org/address/0xfae641bfE7009B5326396048b951E3aa31902a2B + address internal constant MBG_DE_WRAPPED_TOKEN_VAULT = address(0xfae641bfE7009B5326396048b951E3aa31902a2B); + + // ---- tRHM.DE / wtRHM.DE — Rheinmetall AG ST0x ---- + /// https://basescan.org/address/0xfbd76467e4FBbd64dD43057bF137a75ec676C3c2 + address internal constant RHM_DE_RECEIPT = address(0xfbd76467e4FBbd64dD43057bF137a75ec676C3c2); + /// https://basescan.org/address/0x725E0Df28D1EB09338f63776B76bCfc00f3b6f44 + address internal constant RHM_DE_RECEIPT_VAULT = address(0x725E0Df28D1EB09338f63776B76bCfc00f3b6f44); + /// https://basescan.org/address/0xD3c42aB4D5A60A50401b3A67D10B03Ce7D96DA19 + address internal constant RHM_DE_WRAPPED_TOKEN_VAULT = address(0xD3c42aB4D5A60A50401b3A67D10B03Ce7D96DA19); + + // ---- tMCD / wtMCD — McDonald's Corporation ST0x ---- + /// https://basescan.org/address/0x1Cfa3Af9DcEc40dCa8f8588c7b7FCE5a1BA6eC3f + address internal constant MCD_RECEIPT = address(0x1Cfa3Af9DcEc40dCa8f8588c7b7FCE5a1BA6eC3f); + /// https://basescan.org/address/0x6363657E19A82ABE0E210e9b8c88Ea61d96eceaB + address internal constant MCD_RECEIPT_VAULT = address(0x6363657E19A82ABE0E210e9b8c88Ea61d96eceaB); + /// https://basescan.org/address/0x7ecAE30Ed8ee4F72653ada7b0941bDE7a0a8eE8d + address internal constant MCD_WRAPPED_TOKEN_VAULT = address(0x7ecAE30Ed8ee4F72653ada7b0941bDE7a0a8eE8d); + + // ---- tNKE / wtNKE — NIKE, Inc. ST0x ---- + /// https://basescan.org/address/0x8A0037757d67084f5431c02eE2A352593eFe2957 + address internal constant NKE_RECEIPT = address(0x8A0037757d67084f5431c02eE2A352593eFe2957); + /// https://basescan.org/address/0x88C3F4E2E0a977Fed97ed246c70BFD7A01070246 + address internal constant NKE_RECEIPT_VAULT = address(0x88C3F4E2E0a977Fed97ed246c70BFD7A01070246); + /// https://basescan.org/address/0x0883f32d23Ed5535057a4B5E3eB1970FE08606AF + address internal constant NKE_WRAPPED_TOKEN_VAULT = address(0x0883f32d23Ed5535057a4B5E3eB1970FE08606AF); + + /// @notice Returns the 50 production token instance triples on Base, in /// the order they were deployed. This is the structured source of truth /// the flat `productionReceiptVaults()` accessor derives from; consumers /// that need the receipt / wrapped-vault legs or the underlying join key /// (cross-chain parity, per-token config checks) iterate this instead. - /// @return tokens The 41 production token instances on Base. + /// @return tokens The 50 production token instances on Base. function productionTokensBase() internal pure returns (TokenInstance[] memory tokens) { - tokens = new TokenInstance[](41); + tokens = new TokenInstance[](50); tokens[0] = TokenInstance("MSTR", MSTR_RECEIPT, MSTR_RECEIPT_VAULT, MSTR_WRAPPED_TOKEN_VAULT); tokens[1] = TokenInstance("TSLA", TSLA_RECEIPT, TSLA_RECEIPT_VAULT, TSLA_WRAPPED_TOKEN_VAULT); tokens[2] = TokenInstance("COIN", COIN_RECEIPT, COIN_RECEIPT_VAULT, COIN_WRAPPED_TOKEN_VAULT); @@ -448,12 +520,21 @@ library LibTokenInvariants { tokens[38] = TokenInstance("BABA", BABA_RECEIPT, BABA_RECEIPT_VAULT, BABA_WRAPPED_TOKEN_VAULT); tokens[39] = TokenInstance("TQQQ", TQQQ_RECEIPT, TQQQ_RECEIPT_VAULT, TQQQ_WRAPPED_TOKEN_VAULT); tokens[40] = TokenInstance("FTF", FTF_RECEIPT, FTF_RECEIPT_VAULT, FTF_WRAPPED_TOKEN_VAULT); + tokens[41] = TokenInstance("CBRS", CBRS_RECEIPT, CBRS_RECEIPT_VAULT, CBRS_WRAPPED_TOKEN_VAULT); + tokens[42] = TokenInstance("AIR.PA", AIR_PA_RECEIPT, AIR_PA_RECEIPT_VAULT, AIR_PA_WRAPPED_TOKEN_VAULT); + tokens[43] = TokenInstance("BMW.DE", BMW_DE_RECEIPT, BMW_DE_RECEIPT_VAULT, BMW_DE_WRAPPED_TOKEN_VAULT); + tokens[44] = TokenInstance("MC.PA", MC_PA_RECEIPT, MC_PA_RECEIPT_VAULT, MC_PA_WRAPPED_TOKEN_VAULT); + tokens[45] = TokenInstance("SIE.DE", SIE_DE_RECEIPT, SIE_DE_RECEIPT_VAULT, SIE_DE_WRAPPED_TOKEN_VAULT); + tokens[46] = TokenInstance("MBG.DE", MBG_DE_RECEIPT, MBG_DE_RECEIPT_VAULT, MBG_DE_WRAPPED_TOKEN_VAULT); + tokens[47] = TokenInstance("RHM.DE", RHM_DE_RECEIPT, RHM_DE_RECEIPT_VAULT, RHM_DE_WRAPPED_TOKEN_VAULT); + tokens[48] = TokenInstance("MCD", MCD_RECEIPT, MCD_RECEIPT_VAULT, MCD_WRAPPED_TOKEN_VAULT); + tokens[49] = TokenInstance("NKE", NKE_RECEIPT, NKE_RECEIPT_VAULT, NKE_WRAPPED_TOKEN_VAULT); } /// @notice Returns the production token instance triples on Ethereum /// mainnet — Base's underlyings in Base row order, so the tables pair by /// index as well as by key. - /// @return tokens The 41 production token instances on Ethereum. + /// @return tokens The 42 production token instances on Ethereum. function productionTokensEthereum() internal pure returns (TokenInstance[] memory tokens) { // Deployed on Ethereum mainnet 2026-07-22 by // `20260706-deploy-tokens-ethereum` (manual-broadcast run @@ -463,7 +544,7 @@ library LibTokenInvariants { // run's logged (underlying, receipt, receiptVault, wrapped) tuples. // Order and underlyings match Base row-for-row (the cross-chain // parity pin asserts this). - tokens = new TokenInstance[](41); + tokens = new TokenInstance[](42); tokens[0] = TokenInstance( "MSTR", address(0xE3772C8695c2cf3dcAA2Dd29759f4Bb91a342763), @@ -726,12 +807,23 @@ library LibTokenInvariants { address(0x334ccaD2e7D774F5e6A13437977dD0878926deF8), address(0x710A14a41a8Ea2e25376124C48bf9cAdc1E69be5) ); + // CBRS, deployed 2026-08-14 by `20260807-deploy-missing-tokens` (run + // 31845108154) — the sole token that dispatch selected. It was never pinned + // here: the pin PR (#310) stayed open, so this table sat a row behind + // the chain. Verified live before pinning — symbol() tCBRS, receipt() + // and owner() the chain's token-owner Safe. + tokens[41] = TokenInstance( + "CBRS", + address(0x8Ea1ba9Fc0CF7338B41DdDa5B778a9118274AEA8), + address(0x75E0d127794b9C26eE35c55fbaBcc41c53Ccb37C), + address(0x15925E1c19c0F0d392F6FCb40FdE9144Dd823962) + ); } - /// @notice Returns the 41 production token instance triples on HyperEVM, + /// @notice Returns the 42 production token instance triples on HyperEVM, /// in the same row order as `productionTokensBase()` (the cross-chain /// parity pin asserts the alignment). - /// @return tokens The 41 production token instances on HyperEVM. + /// @return tokens The 42 production token instances on HyperEVM. function productionTokensHyperEvm() internal pure returns (TokenInstance[] memory tokens) { // Deployed on HyperEVM 2026-07-24 (manual-broadcast run 30114307165): // all 29 tokens via the 0.1.1 unified deployer, each wired onto the @@ -740,7 +832,7 @@ library LibTokenInvariants { // (underlying, receipt, receiptVault, wrapped) tuples. The script that // ran it was per-chain and has since been superseded by // `20260807-deploy-missing-tokens`, so this is the record of the run. - tokens = new TokenInstance[](41); + tokens = new TokenInstance[](42); tokens[0] = TokenInstance( "MSTR", 0xE3772C8695c2cf3dcAA2Dd29759f4Bb91a342763, @@ -998,6 +1090,17 @@ library LibTokenInvariants { 0x334ccaD2e7D774F5e6A13437977dD0878926deF8, 0x710A14a41a8Ea2e25376124C48bf9cAdc1E69be5 ); + // CBRS, deployed 2026-08-14 by `20260807-deploy-missing-tokens` (run + // 31845492796) — the sole token that dispatch selected. It was never pinned + // here: the pin PR (#310) stayed open, so this table sat a row behind + // the chain. Verified live before pinning — symbol() tCBRS, receipt() + // and owner() the chain's token-owner Safe. + tokens[41] = TokenInstance( + "CBRS", + 0x8Ea1ba9Fc0CF7338B41DdDa5B778a9118274AEA8, + 0x75E0d127794b9C26eE35c55fbaBcc41c53Ccb37C, + 0x15925E1c19c0F0d392F6FCb40FdE9144Dd823962 + ); } /// @notice Returns the 29 production receipt vault addresses on Base, in