1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.26;
3
4
import {IGovernor, Governor} from "@openzeppelin/contracts/governance/Governor.sol";
5
import {GovernorSettings} from "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
6
import {GovernorCountingSimple} from "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
7
import {GovernorVotes} from "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
8
import {GovernorVotesQuorumFraction} from "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
9
import {GovernorTimelockControl} from "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
10
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
11
import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";
12
13
/**
14
* @title LockItInGovernor
15
* @author LockItIn Protocol DAO
16
* @notice On-chain governance for the LockItIn Protocol
17
* @dev OpenZeppelin Governor with timestamp-based voting (L2 compatible)
18
*
19
* Governance Parameters:
20
* - Voting Delay: 1 day (time between proposal and voting start)
21
* - Voting Period: 1 week (duration of voting)
22
* - Proposal Threshold: 0 (any token holder can propose)
23
* - Quorum: 1.2% of total supply (12M votes)
24
* - Execution Delay: 2 days (via Timelock)
25
*
26
* Clock Mode:
27
* - Uses timestamp (inherited from LOCKITToken)
28
* - All time parameters are in seconds
29
* - Compatible with Base L2
30
*
31
* Wyoming DAO LLC:
32
* - This contract address serves as the "publicly available identifier"
33
* required by W.S. 17-31-106(b) for the DAO's smart contract
34
*/
35
contract LockItInGovernor is
36
Governor,
37
GovernorSettings,
38
GovernorCountingSimple,
39
GovernorVotes,
40
GovernorVotesQuorumFraction,
41
GovernorTimelockControl
42
{
43
/// @notice Voting delay: 1 day in seconds
44
uint48 public constant INITIAL_VOTING_DELAY = 1 days;
45
46
/// @notice Voting period: 1 week in seconds
47
uint32 public constant INITIAL_VOTING_PERIOD = 1 weeks;
48
49
/// @notice Proposal threshold: 0 (any holder can propose)
50
uint256 public constant INITIAL_PROPOSAL_THRESHOLD = 0;
51
52
/// @notice Quorum numerator: 12 (with denominator 1000 = 1.2%)
53
uint256 public constant INITIAL_QUORUM_NUMERATOR = 12;
54
55
/**
56
* @notice Deploy Governor with LOCKITToken and Timelock
57
* @param _token LOCKITToken address (0x309456d4F1e321dCdf9a8f9245bC660bBA3f30A0)
58
* @param _timelock LockItInTimelock address (0x10DD0b5A0E79a5399AE8d8DD6f3562250696112F)
59
*/
60
constructor(
61
IVotes _token,
62
TimelockController _timelock
63
)
64
Governor("LockItIn Governor")
65
GovernorSettings(
66
INITIAL_VOTING_DELAY,
67
INITIAL_VOTING_PERIOD,
68
INITIAL_PROPOSAL_THRESHOLD
69
)
70
GovernorVotes(_token)
71
GovernorVotesQuorumFraction(INITIAL_QUORUM_NUMERATOR)
72
GovernorTimelockControl(_timelock)
73
{}
74
75
/**
76
* @notice Quorum denominator override for fractional percentages
77
* @dev Default is 100 (whole percentages only). We use 1000 to allow
78
* 1.2% quorum (numerator 12 / denominator 1000 = 1.2%)
79
*/
80
function quorumDenominator() public pure virtual override returns (uint256) {
81
return 1000;
82
}
83
84
// ═══════════════════════════════════════════════════════════════════════
85
// CLOCK OVERRIDES (explicit for L2 clarity)
86
// ═══════════════════════════════════════════════════════════════════════
87
88
function clock() public view override(Governor, GovernorVotes) returns (uint48) {
89
return GovernorVotes.clock();
90
}
91
92
function CLOCK_MODE() public view override(Governor, GovernorVotes) returns (string memory) {
93
return GovernorVotes.CLOCK_MODE();
94
}
95
96
// ═══════════════════════════════════════════════════════════════════════
97
// REQUIRED OVERRIDES
98
// ═══════════════════════════════════════════════════════════════════════
99
100
function votingDelay()
101
public
102
view
103
override(Governor, GovernorSettings)
104
returns (uint256)
105
{
106
return super.votingDelay();
107
}
108
109
function votingPeriod()
110
public
111
view
112
override(Governor, GovernorSettings)
113
returns (uint256)
114
{
115
return super.votingPeriod();
116
}
117
118
function quorum(uint256 timepoint)
119
public
120
view
121
override(Governor, GovernorVotesQuorumFraction)
122
returns (uint256)
123
{
124
return super.quorum(timepoint);
125
}
126
127
function state(uint256 proposalId)
128
public
129
view
130
override(Governor, GovernorTimelockControl)
131
returns (ProposalState)
132
{
133
return super.state(proposalId);
134
}
135
136
function proposalNeedsQueuing(uint256 proposalId)
137
public
138
view
139
override(Governor, GovernorTimelockControl)
140
returns (bool)
141
{
142
return super.proposalNeedsQueuing(proposalId);
143
}
144
145
function proposalThreshold()
146
public
147
view
148
override(Governor, GovernorSettings)
149
returns (uint256)
150
{
151
return super.proposalThreshold();
152
}
153
154
function supportsInterface(bytes4 interfaceId)
155
public
156
view
157
override(Governor)
158
returns (bool)
159
{
160
return super.supportsInterface(interfaceId);
161
}
162
163
function _queueOperations(
164
uint256 proposalId,
165
address[] memory targets,
166
uint256[] memory values,
167
bytes[] memory calldatas,
168
bytes32 descriptionHash
169
)
170
internal
171
override(Governor, GovernorTimelockControl)
172
returns (uint48)
173
{
174
return super._queueOperations(proposalId, targets, values, calldatas, descriptionHash);
175
}
176
177
function _executeOperations(
178
uint256 proposalId,
179
address[] memory targets,
180
uint256[] memory values,
181
bytes[] memory calldatas,
182
bytes32 descriptionHash
183
)
184
internal
185
override(Governor, GovernorTimelockControl)
186
{
187
super._executeOperations(proposalId, targets, values, calldatas, descriptionHash);
188
}
189
190
function _cancel(
191
address[] memory targets,
192
uint256[] memory values,
193
bytes[] memory calldatas,
194
bytes32 descriptionHash
195
)
196
internal
197
override(Governor, GovernorTimelockControl)
198
returns (uint256)
199
{
200
return super._cancel(targets, values, calldatas, descriptionHash);
201
}
202
203
function _executor()
204
internal
205
view
206
override(Governor, GovernorTimelockControl)
207
returns (address)
208
{
209
return super._executor();
210
}
211
}