Skip to content

Commit d7a3a96

Browse files
author
user
committed
review
1 parent c720069 commit d7a3a96

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

src/GovernanceToken.sol

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
66
import {ERC20Permit, Nonces} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
77
import {ERC20Votes} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
88

9+
//@audit vlad. ок
910
contract GovernanceToken is ERC20, ERC20Permit, ERC20Votes {
1011
constructor() ERC20("GovernanceToken", "GTK") ERC20Permit("GovernanceToken") {}
1112

src/Governor.sol

+22-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ contract Governor is EIP712 {
3939

4040
address public immutable i_guardian;
4141

42+
//@audit vlad. Не нужно, address "достаётся" при `ECDSA.recover()`
4243
string public constant BALLOT_TYPEHASH = "Ballot(uint256 proposalId,bool support)"; // include address voter?
4344

4445
string public constant GOVERNOR_NAME = "Governor";
@@ -58,6 +59,8 @@ contract Governor is EIP712 {
5859
uint256 eta;
5960
address[] targets;
6061
uint256[] values;
62+
//@audit vlad. Везде в коде ты переводишь string в bytes когда обрабатываешь
63+
// Поэтому можно сразу `bytes[]` использовать
6164
string[] signatures;
6265
bytes[] calldatas;
6366
uint256 startBlock;
@@ -148,6 +151,7 @@ contract Governor is EIP712 {
148151
}
149152

150153
uint256 latestProposal = latestProposalIds[msg.sender];
154+
//@note норм
151155
if (latestProposal != 0) {
152156
ProposalState proposalState = state(latestProposal);
153157
if (proposalState == ProposalState.Active || proposalState == ProposalState.Pending) {
@@ -163,6 +167,7 @@ contract Governor is EIP712 {
163167

164168
Proposal storage newProposal = proposals[proposalId];
165169

170+
//@audit vlad. вроде бы unreacheable
166171
// potentially unreachable?
167172
if (newProposal.id != 0) {
168173
revert Governor__ProposalIdCollision();
@@ -182,6 +187,7 @@ contract Governor is EIP712 {
182187
newProposal.canceled = false;
183188
newProposal.executed = false;
184189

190+
//@audit vlad. не важно, всё норм
185191
// should this be before the proposal is created?
186192
latestProposalIds[msg.sender] = proposalId;
187193

@@ -222,6 +228,7 @@ contract Governor is EIP712 {
222228
* @dev Transactions are executed by the Timelock contract
223229
* @dev Values sent to the contracts are sent by the Timelock contract
224230
*/
231+
//@audit vlad. почему это payable?
225232
function execute(uint256 proposalId) external payable {
226233
if (state(proposalId) != ProposalState.Queued) {
227234
revert Governor__ProposalIsNotQueued();
@@ -300,8 +307,13 @@ contract Governor is EIP712 {
300307
* @dev Maybe add address voter to Ballot struct and check if signer == voter
301308
*/
302309
function castVoteBySig(uint256 proposalId, bool support, uint8 v, bytes32 r, bytes32 s) external {
310+
//@audit vlad. Не, шанс коллизии слишком маленький. Из-за парадокса дней рождений шанс 1 коллизии 50% за 2^80 попыток
311+
// По фану можешь посмотреть с какой скоростью твой ноут печатает числа в цикле
312+
// При этом коллизия любых адресов, а делегаты 1 токена это супер мало адресов. Потом скину дискуссию по этому поводу (сейчас инета нету)
303313
// any checks at all? can it cast a random persons vote in case of random signature spam? sounds like i am not really understading something, missing out
304-
// возможно ли в теории наспамить в эту функицю кучу подписей, с идеей что хоть одна попадется, в который я угадаю параметры proposalId и support и при этом signer это участник DAO и он делегировал токены, чтобы его голос засчитался? трудно наверно но мозг мой вот так подумал
314+
// возможно ли в теории наспамить в эту функицю кучу подписей, с идеей что хоть одна попадется,
315+
// в который я угадаю параметры proposalId и support и при этом signer это участник DAO и он делегировал токены,
316+
//чтобы его голос засчитался? трудно наверно но мозг мой вот так подумал
305317
// add address voter to the signature and the check signer == voter?
306318
bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support));
307319
bytes32 digest = _hashTypedDataV4(structHash);
@@ -363,6 +375,7 @@ contract Governor is EIP712 {
363375
* @dev Queue single transaction in the Timelock contract
364376
*
365377
*/
378+
//@note норм
366379
function _queueTransaction(
367380
uint256 proposalId,
368381
address target,
@@ -373,6 +386,9 @@ contract Governor is EIP712 {
373386
) internal {
374387
bytes32 txHash = keccak256(abi.encode(proposalId, target, value, signature, data, eta));
375388

389+
//@audit vlad. С комментарием согласен
390+
// Также хочу заметить, что в нынешнем дизайне proposal не сможет содержать 2 одинаковых действия
391+
// То есть у них будут одинаковые параметры и одинаковый хэш. Вроде бы у Compaund это свойство есть тоже
376392
// may be unnecessary check, because there is no way to manually queue a transaction in the timelock contract
377393
// as a check for collision, it's really unlikely since txHash includes proposalId and proposal.eta
378394
if (i_timelock.queuedTransactions(txHash)) {
@@ -389,6 +405,7 @@ contract Governor is EIP712 {
389405
*
390406
* @dev Cast a vote on a proposal
391407
*/
408+
//@note норм
392409
function _castVote(address voter, uint256 proposalId, bool support) internal {
393410
if (state(proposalId) != ProposalState.Active) {
394411
revert Governor__ProposalIsNotActive();
@@ -423,8 +440,10 @@ contract Governor is EIP712 {
423440
*
424441
* @dev Check if the proposal meets the quorum
425442
*/
443+
//@note норм
426444
function _checkProposalMeetsQuorum(uint256 proposalId) internal view returns (bool) {
427445
Proposal storage proposal = proposals[proposalId];
446+
//@audit vlad. Precision loss не будет, ну или он слишком малый
428447
uint256 quorumAmount = (i_token.getPastTotalSupply(proposal.startBlock - 1)) * quorumVotes() / 100; // precision loss?
429448

430449
if (proposal.forVotes + proposal.againstVotes >= quorumAmount) {
@@ -445,6 +464,7 @@ contract Governor is EIP712 {
445464
*
446465
* @notice Get the state of a proposal
447466
*/
467+
//@note вроде норм, надеюсь ты с логикой здесь разобрался
448468
function state(uint256 proposalId) public view returns (ProposalState proposalState) {
449469
if (proposalId == 0 || proposalId > proposalCount) {
450470
revert Governor__InvalidProposalId();
@@ -474,6 +494,7 @@ contract Governor is EIP712 {
474494
/**
475495
* @return uint256 The threshold of votes needed to propose
476496
*/
497+
//@audit vlad. Не учитывает что токен имеет 18 decimals, считай proposalThreshold и нету
477498
function proposalThreshold() public pure returns (uint256) {
478499
return 1000;
479500
}

src/Timelock.sol

+7
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ contract Timelock is ITimelock, Ownable {
104104
revert Timelock__TransactionIsNotQueued();
105105
}
106106

107+
//@note можно запустить только в период [eta; GRACE_PERIOD]
107108
if (block.timestamp < eta) {
108109
revert Timelock__DelayHasNotPassed();
109110
} else if (block.timestamp >= eta + GRACE_PERIOD) {
@@ -112,12 +113,17 @@ contract Timelock is ITimelock, Ownable {
112113

113114
bytes memory callData;
114115

116+
//@note норм
115117
if (bytes(signature).length == 0) {
116118
callData = data;
117119
} else {
118120
callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);
119121
}
120122

123+
//@audit vlad. Ха-ха-ха попался, а откуда в этом контракте ETH появится а?
124+
// Сейчас оффлайн, поэтому не приведу примеры issues из репортов
125+
// Это было в Moonwell на C4, JOJO на Sherlock и ещё пару раз
126+
// Но это распространённая ошибка, забывают `payable receive()` добавить
121127
(bool success,) = target.call{value: value}(callData);
122128
if (!success) {
123129
revert Timelock__TransactionExecutionReverted();
@@ -136,6 +142,7 @@ contract Timelock is ITimelock, Ownable {
136142
*
137143
* @notice Cancel a single transaction
138144
*/
145+
//@note норм
139146
function cancelTransaction(
140147
uint256 proposalId,
141148
address target,

0 commit comments

Comments
 (0)