Skip to content

Commit 0929923

Browse files
committed
Adhere to our code style conventions
1 parent d6cc136 commit 0929923

File tree

2 files changed

+87
-79
lines changed

2 files changed

+87
-79
lines changed

contracts/token/T.sol

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import "@thesis/solidity-contracts/contracts/token/MisfundRecovery.sol";
99

1010
/// @title T token
1111
/// @notice Threshold Network T token.
12+
/// @dev By default, token balance does not account for voting power.
13+
/// This makes transfers cheaper. The downside is that it requires users
14+
/// to delegate to themselves to activate checkpoints and have their
15+
/// voting power tracked.
1216
contract T is ERC20WithPermit, MisfundRecovery, Checkpoints {
1317
/// @notice The EIP-712 typehash for the delegation struct used by
1418
/// `delegateBySig`.
@@ -89,18 +93,18 @@ contract T is ERC20WithPermit, MisfundRecovery, Checkpoints {
8993
// Does not allow to mint more than uint96 can fit. Otherwise, the
9094
// Checkpoint might not fit the balance.
9195
require(
92-
totalSupply + amount <= _maxSupply(),
96+
totalSupply + amount <= maxSupply(),
9397
"Maximum total supply exceeded"
9498
);
95-
_writeCheckpoint(_totalSupplyCheckpoints, _add, safeAmount);
99+
writeCheckpoint(_totalSupplyCheckpoints, add, safeAmount);
96100
}
97101

98102
// When burning:
99103
if (to == address(0)) {
100-
_writeCheckpoint(_totalSupplyCheckpoints, _subtract, safeAmount);
104+
writeCheckpoint(_totalSupplyCheckpoints, subtract, safeAmount);
101105
}
102106

103-
_moveVotingPower(delegates(from), delegates(to), safeAmount);
107+
moveVotingPower(delegates(from), delegates(to), safeAmount);
104108
}
105109

106110
function delegate(address delegator, address delegatee)
@@ -114,6 +118,6 @@ contract T is ERC20WithPermit, MisfundRecovery, Checkpoints {
114118

115119
emit DelegateChanged(delegator, currentDelegate, delegatee);
116120

117-
_moveVotingPower(currentDelegate, delegatee, delegatorBalance);
121+
moveVotingPower(currentDelegate, delegatee, delegatorBalance);
118122
}
119123
}

contracts/utils/Checkpoints.sol

Lines changed: 78 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,15 @@ import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
66
import "@openzeppelin/contracts/utils/math/Math.sol";
77
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
88

9-
/**
10-
* @dev Abstract contract to support checkpoints for Compound-like voting and delegation.
11-
* This implementation supports token supply up to 2^96^ - 1.
12-
*
13-
* This contract keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
14-
* by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
15-
* power can be queried through the public accessors {getVotes} and {getPastVotes}.
16-
*
17-
* By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
18-
* requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
19-
* Enabling self-delegation can easily be done by overriding the {delegates} function. Keep in mind however that this
20-
* will significantly increase the base gas cost of transfers.
21-
*
22-
* NOTE: Extracted from OpenZeppelin ERCVotes.sol. Maybe worth trying to push it upstream there.
23-
*/
9+
/// @title Checkpoints
10+
/// @dev Abstract contract to support checkpoints for Compound-like voting and
11+
/// delegation. This implementation supports token supply up to 2^96 - 1.
12+
/// This contract keeps a history (checkpoints) of each account's vote
13+
/// power. Vote power can be delegated either by calling the {delegate}
14+
/// function directly, or by providing a signature to be used with
15+
/// {delegateBySig}. Voting power can be publicly queried through
16+
/// {getVotes} and {getPastVotes}.
17+
/// NOTE: Extracted from OpenZeppelin ERCVotes.sol.
2418
abstract contract Checkpoints {
2519
struct Checkpoint {
2620
uint32 fromBlock;
@@ -31,18 +25,15 @@ abstract contract Checkpoints {
3125
mapping(address => uint128[]) internal _checkpoints;
3226
uint128[] internal _totalSupplyCheckpoints;
3327

34-
/**
35-
* @dev Emitted when an account changes their delegate.
36-
*/
28+
/// @notice Emitted when an account changes their delegate.
3729
event DelegateChanged(
3830
address indexed delegator,
3931
address indexed fromDelegate,
4032
address indexed toDelegate
4133
);
4234

43-
/**
44-
* @dev Emitted when a token transfer or delegate change results in changes to an account's voting power.
45-
*/
35+
/// @notice Emitted when a balance or delegate change results in changes
36+
/// to an account's voting power.
4637
event DelegateVotesChanged(
4738
address indexed delegate,
4839
uint256 previousBalance,
@@ -51,9 +42,6 @@ abstract contract Checkpoints {
5142

5243
function delegate(address delegator, address delegatee) internal virtual;
5344

54-
/**
55-
* @dev Get the `pos`-th checkpoint for `account`.
56-
*/
5745
function checkpoints(address account, uint32 pos)
5846
public
5947
view
@@ -66,9 +54,7 @@ abstract contract Checkpoints {
6654
checkpoint = Checkpoint(fromBlock, votes);
6755
}
6856

69-
/**
70-
* @dev Get number of checkpoints for `account`.
71-
*/
57+
/// @notice Get number of checkpoints for `account`.
7258
function numCheckpoints(address account)
7359
public
7460
view
@@ -78,9 +64,7 @@ abstract contract Checkpoints {
7864
return SafeCast.toUint32(_checkpoints[account].length);
7965
}
8066

81-
/**
82-
* @dev Get the address `account` is currently delegating to.
83-
*/
67+
/// @notice Get the address `account` is currently delegating to.
8468
function delegates(address account) public view virtual returns (address) {
8569
return _delegates[account];
8670
}
@@ -105,25 +89,26 @@ abstract contract Checkpoints {
10589
view
10690
returns (uint96)
10791
{
108-
return _checkpointsLookup(_checkpoints[account], blockNumber);
92+
return lookupCheckpoint(_checkpoints[account], blockNumber);
10993
}
11094

111-
/**
112-
* @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.
113-
* It is but NOT the sum of all the delegated votes!
114-
*
115-
* Requirements:
116-
*
117-
* - `blockNumber` must have been already mined
118-
*/
95+
/// @notice Retrieve the `totalSupply` at the end of `blockNumber`.
96+
/// Note, this value is the sum of all balances, but it is NOT the
97+
/// sum of all the delegated votes!
98+
/// @param blockNumber The block number to get the total supply at
99+
/// @dev `blockNumber` must have been already mined
119100
function getPastTotalSupply(uint256 blockNumber)
120101
public
121102
view
122103
returns (uint96)
123104
{
124-
return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
105+
return lookupCheckpoint(_totalSupplyCheckpoints, blockNumber);
125106
}
126107

108+
/// @notice Encodes a `blockNumber` and `value` into a single `uint128`
109+
/// checkpoint.
110+
/// @dev `blockNumber` is stored in the first 32 bits, while `value` in the
111+
/// remaining 96 bits.
127112
function encodeCheckpoint(uint32 blockNumber, uint96 value)
128113
internal
129114
pure
@@ -132,46 +117,55 @@ abstract contract Checkpoints {
132117
return (uint128(blockNumber) << 96) | uint128(value);
133118
}
134119

135-
function decodeBlockNumber(uint128 _checkpoint)
120+
/// @notice Decodes a block number from a `uint128` `checkpoint`.
121+
function decodeBlockNumber(uint128 checkpoint)
136122
internal
137123
pure
138124
returns (uint32)
139125
{
140-
return uint32(bytes4(bytes16(_checkpoint)));
126+
return uint32(bytes4(bytes16(checkpoint)));
141127
}
142128

143-
function decodeValue(uint128 _checkpoint) internal pure returns (uint96) {
144-
return uint96(_checkpoint);
129+
/// @notice Decodes a voting value from a `uint128` `checkpoint`.
130+
function decodeValue(uint128 checkpoint) internal pure returns (uint96) {
131+
return uint96(checkpoint);
145132
}
146133

147-
function decodeCheckpoint(uint128 _checkpoint)
134+
/// @notice Decodes a block number and voting value from a `uint128`
135+
/// `checkpoint`.
136+
function decodeCheckpoint(uint128 checkpoint)
148137
internal
149138
pure
150139
returns (uint32 blockNumber, uint96 value)
151140
{
152-
blockNumber = decodeBlockNumber(_checkpoint);
153-
value = decodeValue(_checkpoint);
141+
blockNumber = decodeBlockNumber(checkpoint);
142+
value = decodeValue(checkpoint);
154143
}
155144

156-
/**
157-
* @dev Lookup a value in a list of (sorted) checkpoints.
158-
*/
159-
function _checkpointsLookup(uint128[] storage ckpts, uint256 blockNumber)
145+
/// @notice Lookup a value in a list of (sorted) checkpoints.
146+
/// @param ckpts The checkpoints array to use
147+
/// @param blockNumber Block number when we want to get the checkpoint at
148+
function lookupCheckpoint(uint128[] storage ckpts, uint256 blockNumber)
160149
internal
161150
view
162151
returns (uint96)
163152
{
164-
// We run a binary search to look for the earliest checkpoint taken after `blockNumber`.
165-
//
166-
// During the loop, the index of the wanted checkpoint remains in the range [low-1, high).
167-
// With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.
168-
// - If the middle checkpoint is after `blockNumber`, we look in [low, mid)
169-
// - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)
170-
// Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not
171-
// out of bounds (in which case we're looking too far in the past and the result is 0).
172-
// Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is
173-
// past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out
174-
// the same.
153+
// We run a binary search to look for the earliest checkpoint taken
154+
// after `blockNumber`. During the loop, the index of the wanted
155+
// checkpoint remains in the range [low-1, high). With each iteration,
156+
// either `low` or `high` is moved towards the middle of the range to
157+
// maintain the invariant.
158+
// - If the middle checkpoint is after `blockNumber`,
159+
// we look in [low, mid)
160+
// - If the middle checkpoint is before or equal to `blockNumber`,
161+
// we look in [mid+1, high)
162+
// Once we reach a single value (when low == high), we've found the
163+
// right checkpoint at the index high-1, if not out of bounds (in that
164+
// case we're looking too far in the past and the result is 0).
165+
// Note that if the latest checkpoint available is exactly for
166+
// `blockNumber`, we end up with an index that is past the end of the
167+
// array, so we technically don't find a checkpoint after
168+
// `blockNumber`, but it works out the same.
175169
require(blockNumber < block.number, "Block not yet determined");
176170

177171
uint256 high = ckpts.length;
@@ -189,40 +183,50 @@ abstract contract Checkpoints {
189183
return high == 0 ? 0 : decodeValue(ckpts[high - 1]);
190184
}
191185

192-
/**
193-
* @dev Maximum token supply. Defaults to `type(uint96).max` (2^96^ - 1).
194-
*/
195-
function _maxSupply() internal view virtual returns (uint96) {
186+
/// @notice Maximum token supply. Defaults to `type(uint96).max` (2^96 - 1)
187+
function maxSupply() internal view virtual returns (uint96) {
196188
return type(uint96).max;
197189
}
198190

199-
function _moveVotingPower(
191+
/// @notice Moves voting power from one delegate to another
192+
/// @param src Address of old delegate
193+
/// @param dst Address of new delegate
194+
/// @param amount Voting power amount to transfer between delegates
195+
function moveVotingPower(
200196
address src,
201197
address dst,
202198
uint256 amount
203199
) internal {
204200
if (src != dst && amount > 0) {
205201
if (src != address(0)) {
206-
(uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(
202+
(uint256 oldWeight, uint256 newWeight) = writeCheckpoint(
207203
_checkpoints[src],
208-
_subtract,
204+
subtract,
209205
amount
210206
);
211207
emit DelegateVotesChanged(src, oldWeight, newWeight);
212208
}
213209

214210
if (dst != address(0)) {
215-
(uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(
211+
(uint256 oldWeight, uint256 newWeight) = writeCheckpoint(
216212
_checkpoints[dst],
217-
_add,
213+
add,
218214
amount
219215
);
220216
emit DelegateVotesChanged(dst, oldWeight, newWeight);
221217
}
222218
}
223219
}
224220

225-
function _writeCheckpoint(
221+
/// @notice Writes a new checkpoint based on operating last stored value
222+
/// with a `delta`. Usually, said operation is the `add` or
223+
/// `subtract` functions from this contract, but more complex
224+
/// functions can be passed as parameters.
225+
/// @param ckpts The checkpoints array to use
226+
/// @param op The function to apply over the last value and the `delta`
227+
/// @param delta Variation with respect to last stored value to be used
228+
/// for new checkpoint
229+
function writeCheckpoint(
226230
uint128[] storage ckpts,
227231
function(uint256, uint256) view returns (uint256) op,
228232
uint256 delta
@@ -251,12 +255,12 @@ abstract contract Checkpoints {
251255
}
252256

253257
// slither-disable-next-line dead-code
254-
function _add(uint256 a, uint256 b) internal pure returns (uint256) {
258+
function add(uint256 a, uint256 b) internal pure returns (uint256) {
255259
return a + b;
256260
}
257261

258262
// slither-disable-next-line dead-code
259-
function _subtract(uint256 a, uint256 b) internal pure returns (uint256) {
263+
function subtract(uint256 a, uint256 b) internal pure returns (uint256) {
260264
return a - b;
261265
}
262266
}

0 commit comments

Comments
 (0)