Toll Collection and Fees
A Smart Gate can charge a toll for passage. In this chapter, we'll implement toll collection with revenue tracking for the gate owner.
Revenue Table
Add a table to track collected fees:
typescript
// Add to mud.config.ts
GateRevenue: {
keySchema: { gateId: "uint256" },
valueSchema: {
totalCollected: "uint256",
totalUses: "uint32",
lastCollectionTime: "uint256",
},
},Updated Gate System
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { System } from "@latticexyz/world/src/System.sol";
import { GateConfig } from "../codegen/tables/GateConfig.sol";
import { GateRevenue } from "../codegen/tables/GateRevenue.sol";
contract GateTollSystem is System {
error InsufficientToll(uint256 required, uint256 provided);
error NoRevenueToWithdraw(uint256 gateId);
function setToll(uint256 gateId, uint256 amount) public {
address owner = GateConfig.getOwner(gateId);
require(_msgSender() == owner, "Not gate owner");
GateConfig.setToll(gateId, amount);
}
function collectToll(uint256 gateId) public payable {
uint256 toll = GateConfig.getToll(gateId);
if (toll > 0 && msg.value < toll) {
revert InsufficientToll(toll, msg.value);
}
// Update revenue tracking
uint256 totalCollected = GateRevenue.getTotalCollected(gateId);
uint32 totalUses = GateRevenue.getTotalUses(gateId);
GateRevenue.set(
gateId,
totalCollected + msg.value,
totalUses + 1,
block.timestamp
);
}
function withdrawRevenue(uint256 gateId) public {
address owner = GateConfig.getOwner(gateId);
require(_msgSender() == owner, "Not gate owner");
uint256 balance = GateRevenue.getTotalCollected(gateId);
if (balance == 0) {
revert NoRevenueToWithdraw(gateId);
}
// Reset collected amount
GateRevenue.setTotalCollected(gateId, 0);
// Transfer to owner
payable(owner).transfer(balance);
}
}Revenue Dashboard Data
Gate owners can read their revenue from the frontend:
typescript
function useGateRevenue(gateId: string) {
const [revenue, setRevenue] = useState({ total: 0n, uses: 0 });
useEffect(() => {
const data = client.tables.GateRevenue.get({
gateId: BigInt(gateId),
});
if (data) {
setRevenue({
total: data.totalCollected,
uses: data.totalUses,
});
}
}, [gateId]);
return revenue;
}Pricing Strategy Tips
- Free gates build goodwill and traffic
- Low tolls (0.001 ETH) cover gas costs and deter spam
- Premium tolls work for strategic routes with no alternatives
- Dynamic pricing based on demand is possible but adds complexity
In the next chapter, we'll put it all together and deploy a working gate.
Sign in to track your progress.