|
1 | 1 | // SPDX-License-Identifier: MIT |
2 | 2 | pragma solidity ^0.8.20; |
3 | 3 |
|
| 4 | +import "forge-std/console2.sol"; |
| 5 | + |
4 | 6 | import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; |
5 | 7 | import {Context} from "@openzeppelin/contracts/utils/Context.sol"; |
6 | 8 | import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol"; |
@@ -43,39 +45,34 @@ abstract contract FlexVotingDelegatable is Context, FlexVotingClient { |
43 | 45 | address oldDelegate = delegates(account); |
44 | 46 | _delegatee[account] = delegatee; |
45 | 47 |
|
| 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))); |
46 | 52 | emit DelegateChanged(account, oldDelegate, delegatee); |
47 | | - _updateDelegateBalance(oldDelegate, delegatee, _rawBalanceOf(account)); |
| 53 | + _updateDelegateBalance(oldDelegate, delegatee, _delta); |
48 | 54 | } |
49 | 55 |
|
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); |
64 | 64 | } |
65 | 65 |
|
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; |
73 | 69 |
|
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); |
77 | 73 |
|
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); |
80 | 77 | } |
81 | 78 | } |
0 commit comments