Update docs
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
const format = require('../format-lines');
|
||||
const { OPTS } = require('./Checkpoints.opts.js');
|
||||
const { OPTS } = require('./Checkpoints.opts');
|
||||
|
||||
// TEMPLATE
|
||||
const header = `\
|
||||
@ -17,10 +17,10 @@ import {Math} from "../math/Math.sol";
|
||||
`;
|
||||
|
||||
const errors = `\
|
||||
/**
|
||||
* @dev A value was attempted to be inserted on a past checkpoint.
|
||||
*/
|
||||
error CheckpointUnorderedInsertion();
|
||||
/**
|
||||
* @dev A value was attempted to be inserted on a past checkpoint.
|
||||
*/
|
||||
error CheckpointUnorderedInsertion();
|
||||
`;
|
||||
|
||||
const template = opts => `\
|
||||
@ -37,7 +37,7 @@ struct ${opts.checkpointTypeName} {
|
||||
* @dev Pushes a (\`key\`, \`value\`) pair into a ${opts.historyTypeName} so that it is stored as the checkpoint.
|
||||
*
|
||||
* Returns previous value and new value.
|
||||
*
|
||||
*
|
||||
* IMPORTANT: Never accept \`key\` as a user input, since an arbitrary \`type(${opts.keyTypeName}).max\` key set will disable the
|
||||
* library.
|
||||
*/
|
||||
@ -45,7 +45,7 @@ function push(
|
||||
${opts.historyTypeName} storage self,
|
||||
${opts.keyTypeName} key,
|
||||
${opts.valueTypeName} value
|
||||
) internal returns (${opts.valueTypeName}, ${opts.valueTypeName}) {
|
||||
) internal returns (${opts.valueTypeName} oldValue, ${opts.valueTypeName} newValue) {
|
||||
return _insert(self.${opts.checkpointFieldName}, key, value);
|
||||
}
|
||||
|
||||
@ -108,20 +108,12 @@ function latest(${opts.historyTypeName} storage self) internal view returns (${o
|
||||
* @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
|
||||
* in the most recent checkpoint.
|
||||
*/
|
||||
function latestCheckpoint(${opts.historyTypeName} storage self)
|
||||
internal
|
||||
view
|
||||
returns (
|
||||
bool exists,
|
||||
${opts.keyTypeName} ${opts.keyFieldName},
|
||||
${opts.valueTypeName} ${opts.valueFieldName}
|
||||
)
|
||||
{
|
||||
function latestCheckpoint(${opts.historyTypeName} storage self) internal view returns (bool exists, ${opts.keyTypeName} ${opts.keyFieldName}, ${opts.valueTypeName} ${opts.valueFieldName}) {
|
||||
uint256 pos = self.${opts.checkpointFieldName}.length;
|
||||
if (pos == 0) {
|
||||
return (false, 0, 0);
|
||||
} else {
|
||||
${opts.checkpointTypeName} memory ckpt = _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1);
|
||||
${opts.checkpointTypeName} storage ckpt = _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1);
|
||||
return (true, ckpt.${opts.keyFieldName}, ckpt.${opts.valueFieldName});
|
||||
}
|
||||
}
|
||||
@ -148,25 +140,26 @@ function _insert(
|
||||
${opts.checkpointTypeName}[] storage self,
|
||||
${opts.keyTypeName} key,
|
||||
${opts.valueTypeName} value
|
||||
) private returns (${opts.valueTypeName}, ${opts.valueTypeName}) {
|
||||
) private returns (${opts.valueTypeName} oldValue, ${opts.valueTypeName} newValue) {
|
||||
uint256 pos = self.length;
|
||||
|
||||
if (pos > 0) {
|
||||
// Copying to memory is important here.
|
||||
${opts.checkpointTypeName} memory last = _unsafeAccess(self, pos - 1);
|
||||
${opts.checkpointTypeName} storage last = _unsafeAccess(self, pos - 1);
|
||||
${opts.keyTypeName} lastKey = last.${opts.keyFieldName};
|
||||
${opts.valueTypeName} lastValue = last.${opts.valueFieldName};
|
||||
|
||||
// Checkpoint keys must be non-decreasing.
|
||||
if(last.${opts.keyFieldName} > key) {
|
||||
if (lastKey > key) {
|
||||
revert CheckpointUnorderedInsertion();
|
||||
}
|
||||
|
||||
// Update or push new checkpoint
|
||||
if (last.${opts.keyFieldName} == key) {
|
||||
_unsafeAccess(self, pos - 1).${opts.valueFieldName} = value;
|
||||
if (lastKey == key) {
|
||||
last.${opts.valueFieldName} = value;
|
||||
} else {
|
||||
self.push(${opts.checkpointTypeName}({${opts.keyFieldName}: key, ${opts.valueFieldName}: value}));
|
||||
}
|
||||
return (last.${opts.valueFieldName}, value);
|
||||
return (lastValue, value);
|
||||
} else {
|
||||
self.push(${opts.checkpointTypeName}({${opts.keyFieldName}: key, ${opts.valueFieldName}: value}));
|
||||
return (0, value);
|
||||
@ -174,7 +167,7 @@ function _insert(
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or \`high\`
|
||||
* @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or \`high\`
|
||||
* if there is none. \`low\` and \`high\` define a section where to do the search, with inclusive \`low\` and exclusive
|
||||
* \`high\`.
|
||||
*
|
||||
@ -198,9 +191,9 @@ function _upperBinaryLookup(
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or
|
||||
* \`high\` if there is none. \`low\` and \`high\` define a section where to do the search, with inclusive \`low\` and
|
||||
* exclusive \`high\`.
|
||||
* @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or \`high\`
|
||||
* if there is none. \`low\` and \`high\` define a section where to do the search, with inclusive \`low\` and exclusive
|
||||
* \`high\`.
|
||||
*
|
||||
* WARNING: \`high\` should not be greater than the array's length.
|
||||
*/
|
||||
@ -224,11 +217,10 @@ function _lowerBinaryLookup(
|
||||
/**
|
||||
* @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
|
||||
*/
|
||||
function _unsafeAccess(${opts.checkpointTypeName}[] storage self, uint256 pos)
|
||||
private
|
||||
pure
|
||||
returns (${opts.checkpointTypeName} storage result)
|
||||
{
|
||||
function _unsafeAccess(
|
||||
${opts.checkpointTypeName}[] storage self,
|
||||
uint256 pos
|
||||
) private pure returns (${opts.checkpointTypeName} storage result) {
|
||||
assembly {
|
||||
mstore(0, self.slot)
|
||||
result.slot := add(keccak256(0, 0x20), pos)
|
||||
@ -241,7 +233,11 @@ function _unsafeAccess(${opts.checkpointTypeName}[] storage self, uint256 pos)
|
||||
module.exports = format(
|
||||
header.trimEnd(),
|
||||
'library Checkpoints {',
|
||||
errors,
|
||||
OPTS.flatMap(opts => template(opts)),
|
||||
format(
|
||||
[].concat(
|
||||
errors,
|
||||
OPTS.map(opts => template(opts)),
|
||||
),
|
||||
).trimEnd(),
|
||||
'}',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user