Skip to content

Commit 2da168a

Browse files
committed
Begin implementing hooks
1 parent 29c8303 commit 2da168a

File tree

2 files changed

+143
-1
lines changed

2 files changed

+143
-1
lines changed

src/interfaces/IProposalTypesConfigurator.sol

+5-1
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@ interface IProposalTypesConfigurator {
7575
FUNCTIONS
7676
//////////////////////////////////////////////////////////////*/
7777

78-
function initialize(address _governor, ProposalType[] calldata _proposalTypes) external;
78+
function initialize(address payable _governor, ProposalType[] calldata _proposalTypes) external;
7979

80+
/*
8081
function proposalTypes(uint8 proposalTypeId) external view returns (ProposalType memory);
8182
function assignedScopes(uint8 proposalTypeId, bytes24 scopeKey) external view returns (Scope[] memory);
8283
function scopeExists(bytes24 key) external view returns (bool);
84+
*/
8385

8486
function setProposalType(
8587
uint8 proposalTypeId,
@@ -90,6 +92,7 @@ interface IProposalTypesConfigurator {
9092
address module
9193
) external;
9294

95+
/*
9396
function setScopeForProposalType(
9497
uint8 proposalTypeId,
9598
bytes24 key,
@@ -105,4 +108,5 @@ interface IProposalTypesConfigurator {
105108
function disableScope(uint8 proposalTypeId, bytes24 scopeKey, uint8 idx) external;
106109
function validateProposedTx(bytes calldata proposedTx, uint8 proposalTypeId, bytes24 key) external;
107110
function validateProposalData(address[] memory targets, bytes[] memory calldatas, uint8 proposalTypeId) external;
111+
*/
108112
}
+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.19;
3+
4+
import {IProposalTypesConfigurator} from "src/interfaces/IProposalTypesConfigurator.sol";
5+
import {AgoraGovernor} from "src/AgoraGovernor.sol";
6+
import {IHooks} from "src/interfaces/IHooks.sol";
7+
import {Hooks} from "src/libraries/Hooks.sol";
8+
9+
contract ProposalTypesConfigurator is IProposalTypesConfigurator {
10+
using Hooks for IHooks;
11+
/*//////////////////////////////////////////////////////////////
12+
EVENTS
13+
//////////////////////////////////////////////////////////////*/
14+
15+
event ScopeCreated(uint8 indexed proposalTypeId, bytes24 indexed scopeKey, bytes4 selector, string description);
16+
event ScopeDisabled(uint8 indexed proposalTypeId, bytes24 indexed scopeKey);
17+
18+
/*//////////////////////////////////////////////////////////////
19+
IMMUTABLE STORAGE
20+
//////////////////////////////////////////////////////////////*/
21+
22+
AgoraGovernor public governor;
23+
24+
/// @notice Max value of `quorum` and `approvalThreshold` in `ProposalType`
25+
uint16 public constant PERCENT_DIVISOR = 10_000;
26+
27+
/*//////////////////////////////////////////////////////////////
28+
STORAGE
29+
//////////////////////////////////////////////////////////////*/
30+
31+
mapping(uint8 proposalTypeId => ProposalType) internal _proposalTypes;
32+
mapping(uint8 proposalTypeId => mapping(bytes24 key => Scope[])) internal _assignedScopes;
33+
mapping(bytes24 key => bool) internal _scopeExists;
34+
35+
/*//////////////////////////////////////////////////////////////
36+
MODIFIERS
37+
//////////////////////////////////////////////////////////////*/
38+
39+
modifier onlyAdminOrTimelock() {
40+
if (msg.sender != governor.admin() && msg.sender != governor.timelock()) revert NotAdminOrTimelock();
41+
_;
42+
}
43+
44+
/*//////////////////////////////////////////////////////////////
45+
FUNCTIONS
46+
//////////////////////////////////////////////////////////////*/
47+
48+
/**
49+
* @notice Initialize the contract with the governor and proposal types.
50+
* @param _governor Address of the governor contract.
51+
* @param _proposalTypesInit Array of ProposalType structs to initialize the contract with.
52+
*/
53+
function initialize(address payable _governor, ProposalType[] calldata _proposalTypesInit) public {
54+
if (address(governor) != address(0)) revert AlreadyInit();
55+
if (_governor == address(0)) revert InvalidGovernor();
56+
57+
governor = AgoraGovernor(_governor);
58+
59+
for (uint8 i = 0; i < _proposalTypesInit.length; i++) {
60+
_setProposalType(
61+
i,
62+
_proposalTypesInit[i].quorum,
63+
_proposalTypesInit[i].approvalThreshold,
64+
_proposalTypesInit[i].name,
65+
_proposalTypesInit[i].description,
66+
_proposalTypesInit[i].module
67+
);
68+
}
69+
}
70+
71+
function getHookPermissions() public pure returns (Hooks.Permissions memory) {
72+
return Hooks.Permissions({
73+
beforeInitialize: false,
74+
afterInitialize: false,
75+
beforeQuorumCalculation: true,
76+
afterQuorumCalculation: false,
77+
beforeVote: true,
78+
afterVote: true,
79+
beforePropose: true,
80+
afterPropose: false,
81+
beforeCancel: false,
82+
afterCancel: false,
83+
beforeExecute: false,
84+
afterExecute: false
85+
});
86+
}
87+
88+
/*//////////////////////////////////////////////////////////////
89+
HOOKS
90+
//////////////////////////////////////////////////////////////*/
91+
92+
93+
/// @notice The hook called before quorum calculation is performed
94+
function beforeQuorumCalculation(address sender, uint256 timepoint) external override view returns (uint256) {
95+
uint256 _beforeQuorum = (governor.token().getPastTotalSupply(timepoint) * _proposalTypes[0].quorum) / governor.quorumDenominator();
96+
return _beforeQuorum;
97+
}
98+
99+
/*//////////////////////////////////////////////////////////////
100+
STORAGE
101+
//////////////////////////////////////////////////////////////*/
102+
/**
103+
* @notice Set the parameters for a proposal type. Only callable by the admin or timelock.
104+
* @param proposalTypeId Id of the proposal type
105+
* @param quorum Quorum percentage, scaled by `PERCENT_DIVISOR`
106+
* @param approvalThreshold Approval threshold percentage, scaled by `PERCENT_DIVISOR`
107+
* @param name Name of the proposal type
108+
* @param description Describes the proposal type
109+
* @param module Address of module that can only use this proposal type
110+
*/
111+
function setProposalType(
112+
uint8 proposalTypeId,
113+
uint16 quorum,
114+
uint16 approvalThreshold,
115+
string calldata name,
116+
string calldata description,
117+
address module
118+
) external override onlyAdminOrTimelock {
119+
_setProposalType(proposalTypeId, quorum, approvalThreshold, name, description, module);
120+
}
121+
122+
function _setProposalType(
123+
uint8 proposalTypeId,
124+
uint16 quorum,
125+
uint16 approvalThreshold,
126+
string calldata name,
127+
string calldata description,
128+
address module
129+
) internal {
130+
if (quorum > PERCENT_DIVISOR) revert InvalidQuorum();
131+
if (approvalThreshold > PERCENT_DIVISOR) revert InvalidApprovalThreshold();
132+
133+
_proposalTypes[proposalTypeId] = ProposalType(quorum, approvalThreshold, name, description, module, true);
134+
135+
emit ProposalTypeSet(proposalTypeId, quorum, approvalThreshold, name, description);
136+
}
137+
}
138+

0 commit comments

Comments
 (0)