SKIP TO CONTENT

Demo build — mock protocol data. No chain, no ABIs yet.

  • SYNCING: ……

Deploy.s.sol

Foundry deployment script: wires the whole system together in dependency order.

192 lines8.2 KBSolidity
Source of script/Deploy.s.sol, 192 lines of Solidity
1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.24;
3 
4import {Script, console2} from "forge-std/Script.sol";
5 
6import {K401} from "../src/K401.sol";
7import {K401Treasury} from "../src/K401Treasury.sol";
8import {K401Oracle} from "../src/K401Oracle.sol";
9import {K401Distributor} from "../src/K401Distributor.sol";
10import {K401Staking} from "../src/K401Staking.sol";
11import {K401SeatRegistry} from "../src/K401SeatRegistry.sol";
12import {K401Seat6551, K401Seat6551Account} from "../src/K401Seat6551.sol";
13import {ERC6551Registry} from "../src/ERC6551Registry.sol";
14import {K401FeeSplitter} from "../src/K401FeeSplitter.sol";
15import {K401StockDesk} from "../src/K401StockDesk.sol";
16import {K401BondDepository} from "../src/K401BondDepository.sol";
17import {K401Buyback} from "../src/K401Buyback.sol";
18import {K401Lens} from "../src/K401Lens.sol";
19 
20/**
21 * @notice Full ordered deployment + wiring for $401K "The Firm".
22 *
23 * Required env:
24 * PRIVATE_KEY deployer key
25 * USDG USDG token address
26 * K401_USDG_PAIR canonical 401K/USDG UniV2 pair (must already exist and be seeded)
27 * ROUTER UniV2-compatible router
28 * Optional env:
29 * OWNER protocol owner (default: deployer)
30 * TEAM team fee receiver (default: deployer)
31 * LP_RECEIVER POL receiver (default: OWNER)
32 * INITIAL_SUPPLY initial 401K supply, wei (default: 0)
33 * SUPPLY_OWNER initial supply recipient (default: deployer)
34 * ERC6551_REGISTRY existing ERC-6551 registry (default: deploy a fresh one)
35 * POL_MANAGER address allowed to move 401K in/out of the pair fee-free (POL ops).
36 * Leave unset and the deployer pays the normal 5% when seeding liquidity;
37 * that fee is not lost, it just routes through the FeeSplitter.
38 *
39 * The pair MUST exist before running this script: the oracle binds to it immutably.
40 */
41contract Deploy is Script {
42 struct Deployment {
43 address k401;
44 address mirror;
45 address treasury;
46 address oracle;
47 address staking;
48 address registry;
49 address distributor;
50 address erc6551Registry;
51 address seatAccountImpl;
52 address seat6551;
53 address stockDesk;
54 address feeSplitter;
55 address bonds;
56 address buyback;
57 address lens;
58 }
59 
60 function run() external returns (Deployment memory d) {
61 uint256 pk = vm.envUint("PRIVATE_KEY");
62 address deployer = vm.addr(pk);
63 
64 address usdg = vm.envAddress("USDG");
65 address pair = vm.envAddress("K401_USDG_PAIR");
66 address router = vm.envAddress("ROUTER");
67 address owner = vm.envOr("OWNER", deployer);
68 address team = vm.envOr("TEAM", deployer);
69 address lpReceiver = vm.envOr("LP_RECEIVER", owner);
70 uint256 initialSupply = vm.envOr("INITIAL_SUPPLY", uint256(0));
71 address supplyOwner = vm.envOr("SUPPLY_OWNER", deployer);
72 address existing6551 = vm.envOr("ERC6551_REGISTRY", address(0));
73 address polManager = vm.envOr("POL_MANAGER", address(0));
74 
75 vm.startBroadcast(pk);
76 
77 // 1. Token (deployer must stay owner until wiring is done).
78 K401 k401 = new K401(uint96(initialSupply), supplyOwner, deployer);
79 d.k401 = address(k401);
80 d.mirror = k401.mirrorERC721();
81 
82 // 2. Reserve + pricing.
83 K401Treasury treasury = new K401Treasury(address(k401), usdg, deployer);
84 K401Oracle oracle = new K401Oracle(pair, address(k401), usdg);
85 d.treasury = address(treasury);
86 d.oracle = address(oracle);
87 
88 // 3. Game layer + staking + emission.
89 K401SeatRegistry registry = new K401SeatRegistry(address(k401), deployer);
90 K401Staking staking = new K401Staking(address(k401), address(registry), deployer);
91 K401Distributor distributor =
92 new K401Distributor(address(k401), address(oracle), address(treasury), address(staking), deployer);
93 d.registry = address(registry);
94 d.staking = address(staking);
95 d.distributor = address(distributor);
96 
97 // 4. ERC-6551.
98 address erc6551Registry = existing6551;
99 if (erc6551Registry == address(0)) erc6551Registry = address(new ERC6551Registry());
100 K401Seat6551Account impl = new K401Seat6551Account();
101 K401Seat6551 seat6551 = new K401Seat6551(erc6551Registry, address(impl), d.mirror);
102 d.erc6551Registry = erc6551Registry;
103 d.seatAccountImpl = address(impl);
104 d.seat6551 = address(seat6551);
105 
106 // 5. Revenue plumbing.
107 K401StockDesk stockDesk =
108 new K401StockDesk(usdg, address(oracle), address(registry), address(seat6551), deployer);
109 K401FeeSplitter splitter = new K401FeeSplitter(address(k401), usdg, deployer);
110 K401BondDepository bonds =
111 new K401BondDepository(address(k401), address(oracle), address(treasury), deployer);
112 K401Buyback buyback = new K401Buyback(address(k401), usdg, address(treasury), address(oracle), deployer);
113 d.stockDesk = address(stockDesk);
114 d.feeSplitter = address(splitter);
115 d.bonds = address(bonds);
116 d.buyback = address(buyback);
117 
118 // 6. Wiring — K401.
119 k401.setSeatRegistry(address(registry));
120 k401.setStaking(address(staking));
121 k401.setFeeSplitter(address(splitter));
122 k401.mapPair(pair, true);
123 k401.setWhitelist(address(staking), true);
124 k401.setWhitelist(address(treasury), true);
125 k401.setWhitelist(address(stockDesk), true);
126 k401.setWhitelist(address(bonds), true);
127 k401.setWhitelist(address(buyback), true);
128 k401.setWhitelist(address(distributor), true);
129 // Optional: a protocol-owned-liquidity manager that moves 401K into the pair fee-free.
130 // NOTE: whitelisting is permanent. Only ever point this at a contract you control.
131 if (polManager != address(0)) k401.setWhitelist(polManager, true);
132 k401.addMinter(address(treasury));
133 k401.addMinter(address(distributor));
134 k401.addBurner(address(registry));
135 k401.addBurner(address(buyback));
136 
137 // 7. Wiring — modules.
138 registry.setStaking(address(staking));
139 registry.setStockDesk(address(stockDesk));
140 staking.setDistributor(address(distributor));
141 treasury.addDepositor(address(bonds));
142 treasury.addPolToken(pair);
143 stockDesk.setRouter(router);
144 splitter.wire(router, address(stockDesk), address(treasury), lpReceiver, address(buyback), team);
145 
146 // 8. Lens.
147 K401Lens lens = new K401Lens(
148 address(k401),
149 address(treasury),
150 address(oracle),
151 address(distributor),
152 address(staking),
153 address(registry),
154 address(seat6551),
155 address(stockDesk),
156 address(bonds)
157 );
158 d.lens = address(lens);
159 
160 // 9. Hand ownership over, if requested.
161 if (owner != deployer) {
162 k401.transferOwnership(owner);
163 treasury.transferOwnership(owner);
164 registry.transferOwnership(owner);
165 staking.transferOwnership(owner);
166 distributor.transferOwnership(owner);
167 stockDesk.transferOwnership(owner);
168 splitter.transferOwnership(owner);
169 bonds.transferOwnership(owner);
170 buyback.transferOwnership(owner);
171 }
172 
173 vm.stopBroadcast();
174 
175 console2.log("K401 ", d.k401);
176 console2.log("Mirror (ERC721) ", d.mirror);
177 console2.log("Treasury ", d.treasury);
178 console2.log("Oracle ", d.oracle);
179 console2.log("SeatRegistry ", d.registry);
180 console2.log("Staking ", d.staking);
181 console2.log("Distributor ", d.distributor);
182 console2.log("ERC6551Registry ", d.erc6551Registry);
183 console2.log("SeatAccountImpl ", d.seatAccountImpl);
184 console2.log("Seat6551 ", d.seat6551);
185 console2.log("StockDesk ", d.stockDesk);
186 console2.log("FeeSplitter ", d.feeSplitter);
187 console2.log("BondDepository ", d.bonds);
188 console2.log("Buyback ", d.buyback);
189 console2.log("Lens ", d.lens);
190 }
191}
192 

Click any line number to deep-link to it — the target line highlights on load.