PloutoRegistry
The registry is the protocol's address book and the single source of truth for whether PLOUTO exists. It is Ownable2Step, deliberately small, and mostly a set of one-way doors.
Immutable Pons wiring
Fixed at construction and never changeable:
address public immutable ponsFactory;address public immutable ponsFeeEscrow;address public immutable expectedLauncher;The constructor requires bytecode at the factory and the escrow. expectedLauncher is the address expected to have executed the launch, and it is what prevents an attacker registering their own Pons launch.
Wiring the protocol
function wireProtocol(address revenueRouter_, address gravityStaking_, address buybackExecutor_, address reserve_) external onlyOwnerCallable exactly once — a second call reverts with AlreadyWired(). Every address must be non-zero and have bytecode. This exists as a separate step because the four contracts are deployed after the registry.
The one-way door
function setPloutoTokenOnce(address token, address curve) external onlyOwnerThis is the most consequential function in the protocol. It validates against the live Pons factory record, not against the caller's claims:
- Basic checks
Not already initialized. Protocol wired. Both addresses non-zero and carrying bytecode.
- Factory record
record.exists;record.token == token;record.curve == curve;record.deployer == expectedLauncher;record.creatorFeeRecipient == revenueRouter;record.pairToken == address(0).- Curve cross-check
The curve's own
token(),pairToken()andfactory()must agree. A spoofed factory record alone is not enough.- Supply
totalSupply()must be non-zero, read bystaticcallso a non-conforming token reverts rather than silently passing.
Each failure has its own error: LaunchNotFound, TokenMismatch, CurveMismatch, UnexpectedLauncher, FeeRecipientMismatch, NotNativeQuote, ZeroSupply, NoCode, AlreadyInitialized, NotWired.
The initialization gate
function initialized() public view returns (bool) { return ploutoToken != address(0);}Everything downstream reads this. GravityStaking.stake reverts with NotInitialized if the token is unset; PloutoRevenueRouter.routeUnallocatedRevenue does the same; the frontend gates every control on it.
Events
event ProtocolWired(address revenueRouter, address gravityStaking, address buybackExecutor, address reserve);event PloutoInitialized( address indexed token, address indexed curve, address indexed creatorFeeRecipient, address launchDeployer, address pairToken, uint256 totalSupply, uint256 blockNumber);PloutoInitialized fires once, ever. It is the canonical on-chain record of the launch.
What the registry cannot do
- Hold or move value. It has no
receive(), no token balance and no transfer function. - Change the token after initialization.
- Grant itself permissions over the other contracts.
- Be re-wired.
Ownership uses Ownable2Step, so a transfer requires the new owner to accept — a mistyped address cannot orphan the contract.