Skip to content

Commit 3bfa073

Browse files
committed
paranoia commit, revert
1 parent 3e53065 commit 3bfa073

File tree

6 files changed

+374
-437
lines changed

6 files changed

+374
-437
lines changed

src/FlexVotingClient.sol

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.20;
33

4+
import "forge-std/console2.sol";
5+
46
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
57
import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol";
68
import {IFractionalGovernor} from "src/interfaces/IFractionalGovernor.sol";
@@ -69,6 +71,7 @@ abstract contract FlexVotingClient {
6971
uint128 abstainVotes;
7072
}
7173

74+
/// TODO need to check that this still works
7275
/// @dev Map proposalId to an address to whether they have voted on this proposal.
7376
mapping(uint256 => mapping(address => bool)) private proposalVotersHasVoted;
7477

@@ -112,6 +115,7 @@ abstract contract FlexVotingClient {
112115
return "rolled-up vote from governance token holders";
113116
}
114117

118+
// TODO rename to avoid collision with FlexVotingDelegatable.
115119
/// @dev Delegates the present contract's voting rights with `GOVERNOR` to itself.
116120
function _selfDelegate() internal {
117121
IVotingToken(GOVERNOR.token()).delegate(address(this));
@@ -202,13 +206,11 @@ abstract contract FlexVotingClient {
202206
);
203207
}
204208

205-
/// @dev Checkpoints the _user's current raw balance.
206-
function _checkpointRawBalanceOf(address _user) internal {
207-
balanceCheckpoints[_user].push(IVotingToken(GOVERNOR.token()).clock(), _rawBalanceOf(_user));
208-
}
209+
function _applyDeltaToCheckpoint(
210+
Checkpoints.Trace208 storage _checkpoint,
211+
int256 _delta
212+
) internal returns (uint208 _prevTotal, uint208 _newTotal) {
209213

210-
/// @dev Checkpoints the total balance after applying `_delta`.
211-
function _checkpointTotalBalance(int256 _delta) internal {
212214
// The casting in this function is safe since:
213215
// - if oldTotal + delta > int256.max it will panic and revert.
214216
// - if |delta| <= oldTotal
@@ -226,12 +228,27 @@ abstract contract FlexVotingClient {
226228
// uint256.max + int256.min > uint208.max
227229
// Substituting again:
228230
// wrapped(int256.min) > uint208.max, which will revert when safecast.
229-
uint256 _oldTotal = uint256(totalBalanceCheckpoints.latest());
230-
uint256 _newTotal = uint256(int256(_oldTotal) + _delta);
231+
_prevTotal = _checkpoint.latest();
232+
int256 _castTotal = int256(uint256(_prevTotal));
233+
console2.log("david applyDelta", _castTotal);
234+
console2.log("david applyDelta", _delta);
235+
_newTotal = SafeCast.toUint208(uint256(_castTotal + _delta));
236+
237+
uint48 _timepoint = IVotingToken(GOVERNOR.token()).clock();
238+
_checkpoint.push(_timepoint, _newTotal);
239+
}
231240

232-
totalBalanceCheckpoints.push(
233-
IVotingToken(GOVERNOR.token()).clock(), SafeCast.toUint208(_newTotal)
234-
);
241+
/// @dev Checkpoints the _user's current raw balance.
242+
function _checkpointRawBalanceOf(
243+
address _user,
244+
int256 _delta
245+
) internal virtual returns (uint208 _prevTotal, uint208 _newTotal) {
246+
(_prevTotal, _newTotal) = _applyDeltaToCheckpoint(balanceCheckpoints[_user], _delta);
247+
}
248+
249+
/// @dev Checkpoints the total balance after applying `_delta`.
250+
function _checkpointTotalBalance(int256 _delta) internal virtual {
251+
_applyDeltaToCheckpoint(totalBalanceCheckpoints, _delta);
235252
}
236253

237254
/// @notice Returns the `_user`'s raw balance at `_timepoint`.

src/FlexVotingDelegatable.sol

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.20;
33

4+
import "forge-std/console2.sol";
5+
46
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
57
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
68
import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol";
@@ -43,39 +45,34 @@ abstract contract FlexVotingDelegatable is Context, FlexVotingClient {
4345
address oldDelegate = delegates(account);
4446
_delegatee[account] = delegatee;
4547

48+
// TODO There is a bug here: if you didn't have a delegate before and you
49+
// implicitly self-delegated, then _updateDelegateBalance will attempt to
50+
// subtract from the old delegate's balance, which will be zero. This will
51+
int256 _delta = int256(uint256(_rawBalanceOf(account)));
4652
emit DelegateChanged(account, oldDelegate, delegatee);
47-
_updateDelegateBalance(oldDelegate, delegatee, _rawBalanceOf(account));
53+
_updateDelegateBalance(oldDelegate, delegatee, _delta);
4854
}
4955

50-
// @dev Moves delegated votes from one delegate to another.
51-
function _updateDelegateBalance(address from, address to, uint208 amount) internal virtual {
52-
if (from == to || amount == 0) return;
53-
54-
if (from != address(0)) {
55-
(uint256 oldValue, uint256 newValue) =
56-
_push(FlexVotingClient.balanceCheckpoints[from], _subtract, amount);
57-
emit DelegateWeightChanged(from, oldValue, newValue);
58-
}
59-
if (to != address(0)) {
60-
(uint256 oldValue, uint256 newValue) =
61-
_push(FlexVotingClient.balanceCheckpoints[to], _add, amount);
62-
emit DelegateWeightChanged(to, oldValue, newValue);
63-
}
56+
function _checkpointRawBalanceOf(
57+
address _user,
58+
int256 _delta
59+
) internal virtual override returns (uint208 _prevTotal, uint208 _newTotal) {
60+
address _proxy = delegates(_user);
61+
// TODO it's a bit confusing to call "checkpoint" on a user but then get the
62+
// user's delegate's voting weight back.
63+
(_prevTotal, _newTotal) = _applyDeltaToCheckpoint(balanceCheckpoints[_proxy], _delta);
6464
}
6565

66-
function _push(
67-
Checkpoints.Trace208 storage store,
68-
function(uint208, uint208) view returns (uint208) fn,
69-
uint208 delta
70-
) private returns (uint208 oldValue, uint208 newValue) {
71-
return store.push(IVotingToken(GOVERNOR.token()).clock(), fn(store.latest(), delta));
72-
}
66+
// @dev Moves delegated votes from one delegate to another.
67+
function _updateDelegateBalance(address from, address to, int256 _delta) internal virtual {
68+
if (from == to || _delta == 0) return;
7369

74-
function _add(uint208 a, uint208 b) private pure returns (uint208) {
75-
return a + b;
76-
}
70+
// Decrement old delegate's weight.
71+
(uint208 _oldFrom, uint208 _newFrom) = _checkpointRawBalanceOf(from, -_delta);
72+
emit DelegateWeightChanged(from, _oldFrom, _newFrom);
7773

78-
function _subtract(uint208 a, uint208 b) private pure returns (uint208) {
79-
return a - b;
74+
// Increment new delegate's weight.
75+
(uint208 _oldTo, uint208 _newTo) = _checkpointRawBalanceOf(to, _delta);
76+
emit DelegateWeightChanged(to, _oldTo, _newTo);
8077
}
8178
}

0 commit comments

Comments
 (0)