Skip to content

Commit 01d7219

Browse files
committed
Merge branch 'governor-dvp-poc' into dvp-actions-poc
2 parents d19c3e7 + d68b715 commit 01d7219

File tree

1 file changed

+55
-59
lines changed

1 file changed

+55
-59
lines changed

src/L2ArbitrumToken.sol

Lines changed: 55 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -44,47 +44,11 @@ contract L2ArbitrumToken is
4444
/// @notice The time at which the next mint is allowed - timestamp
4545
uint256 public nextMint;
4646

47-
/// @dev History of the total amount of delegated tokens
48-
/// The initial value is an estimate of the total delegation at the time of upgrade proposal creation.
49-
/// Another proposal can be made later to update this value if needed.
50-
Checkpoints.History private _totalDelegationHistory;
51-
52-
/// @notice Called at proposal #1
53-
/// @param initialTotalDelegation The initial total delegation at the time of upgrade proposal creation.
54-
/// This is an estimate since it is chosen at proposal creation time and not effective until the proposal is executed.
55-
function postUpgradeInit1(uint256 initialTotalDelegation) external onlyOwner {
56-
_totalDelegationHistory.push(initialTotalDelegation);
57-
}
58-
59-
/// @notice Called at proposal #2
60-
/// @param initialEstimationErrorAdjustment The amount the initialTotalDelegation was off by, negated. This is added to the current total delegation.
61-
function postUpgradeInit2(int256 initialEstimationErrorAdjustment) external onlyOwner {
62-
_totalDelegationHistory.push(
63-
uint256(int256(_totalDelegationHistory.latest()) + initialEstimationErrorAdjustment)
64-
);
65-
}
66-
67-
/// @notice Get the current total delegation
68-
/// @return The current total delegation
69-
function getTotalDelegation()
70-
external
71-
view
72-
returns (uint256)
73-
{
74-
return _totalDelegationHistory.latest();
75-
}
76-
77-
/// @notice Get the total delegation at a specific block number
78-
/// If the blockNumber is prior to the first checkpoint, returns 0
79-
/// @param blockNumber The block number to get the total delegation at
80-
/// @return The total delegation at the given block number
81-
function getTotalDelegationAt(uint256 blockNumber)
82-
external
83-
view
84-
returns (uint256)
85-
{
86-
return _totalDelegationHistory.getAtBlock(blockNumber);
87-
}
47+
/// @dev History of the change in total amount of delegated tokens
48+
/// Tracks the delta between total delegation at a given block and the anchor
49+
/// The anchor is set via setTotalDelegationAnchor as a standalone one-time operation
50+
Checkpoints.History private _totalDelegationDeltaHistory;
51+
uint256 private _totalDelegationAnchor;
8852

8953
constructor() {
9054
_disableInitializers();
@@ -114,6 +78,11 @@ contract L2ArbitrumToken is
11478
_transferOwnership(_owner);
11579
}
11680

81+
function setTotalDelegationAnchor(uint256 totalDelegationAnchor) external onlyOwner {
82+
require(_totalDelegationAnchor == 0, "ARB: ANCHOR_ALREADY_SET");
83+
_totalDelegationAnchor = totalDelegationAnchor;
84+
}
85+
11786
/// @notice Allows the owner to mint new tokens
11887
/// @dev Only allows minting below an inflation cap.
11988
/// Set to once per year, and a maximum of 2%.
@@ -129,12 +98,48 @@ contract L2ArbitrumToken is
12998
_mint(recipient, amount);
13099
}
131100

101+
/// @notice Get the current total delegation
102+
/// @dev If the anchor is unset, returns 0
103+
/// @return The current total delegation
104+
function getTotalDelegation() external view returns (uint256) {
105+
uint256 __totalDelegationAnchor = _totalDelegationAnchor;
106+
if (__totalDelegationAnchor == 0) {
107+
return 0;
108+
}
109+
return _adjustByAnchor(_totalDelegationDeltaHistory.latest(), __totalDelegationAnchor);
110+
}
111+
112+
/// @notice Get the total delegation at a specific block number
113+
/// @dev If the anchor is unset, or the block number is before the first checkpoint, returns 0
114+
/// @param blockNumber The block number to get the total delegation at
115+
/// @return The total delegation at the given block number
116+
function getTotalDelegationAt(uint256 blockNumber) external view returns (uint256) {
117+
uint256 __totalDelegationAnchor = _totalDelegationAnchor;
118+
if (
119+
__totalDelegationAnchor == 0
120+
|| blockNumber < _totalDelegationDeltaHistory._checkpoints[0]._blockNumber
121+
) {
122+
return 0;
123+
}
124+
return _adjustByAnchor(
125+
_totalDelegationDeltaHistory.getAtBlock(blockNumber), __totalDelegationAnchor
126+
);
127+
}
132128

133-
function _updateDelegationHistory(
134-
address fromDelegate,
135-
address toDelegate,
136-
uint256 amount
137-
) internal {
129+
/// @dev Helper function to adjust a delegation delta checkpoint return value by an anchor
130+
/// The checkpoint return value is stored as a uint224, but we treat it as a signed int224.
131+
/// This is why the casting is a bit complex.
132+
function _adjustByAnchor(uint256 checkpointReturnValue, uint256 anchor)
133+
internal
134+
pure
135+
returns (uint256)
136+
{
137+
return uint256(int224(uint224(checkpointReturnValue)) + int256(anchor));
138+
}
139+
140+
function _updateDelegationHistory(address fromDelegate, address toDelegate, uint256 amount)
141+
internal
142+
{
138143
if (fromDelegate != toDelegate) {
139144
int256 delta = 0;
140145
if (fromDelegate != address(0)) {
@@ -144,32 +149,23 @@ contract L2ArbitrumToken is
144149
delta += int256(amount);
145150
}
146151
if (delta != 0) {
147-
_totalDelegationHistory.push(
148-
uint256(int256(_totalDelegationHistory.latest()) + delta)
149-
);
152+
int224 latestDelta = int224(uint224(_totalDelegationDeltaHistory.latest()));
153+
_totalDelegationDeltaHistory.push(uint256(latestDelta + delta));
150154
}
151155
}
152156
}
153157

154158
function _delegate(address delegator, address delegatee) internal virtual override {
155159
super._delegate(delegator, delegatee);
156-
_updateDelegationHistory(
157-
delegates(delegator),
158-
delegatee,
159-
balanceOf(delegator)
160-
);
160+
_updateDelegationHistory(delegates(delegator), delegatee, balanceOf(delegator));
161161
}
162162

163163
function _afterTokenTransfer(address from, address to, uint256 amount)
164164
internal
165165
override(ERC20Upgradeable, ERC20VotesUpgradeable)
166166
{
167167
super._afterTokenTransfer(from, to, amount);
168-
_updateDelegationHistory(
169-
delegates(from),
170-
delegates(to),
171-
amount
172-
);
168+
_updateDelegationHistory(delegates(from), delegates(to), amount);
173169
}
174170

175171
function _mint(address to, uint256 amount)

0 commit comments

Comments
 (0)