Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/brown-cooks-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`Checkpoints`: removed redundant memory usage
26 changes: 14 additions & 12 deletions contracts/utils/structs/Checkpoints.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ library Checkpoints {
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint224 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
Checkpoint224 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
Expand All @@ -131,21 +131,22 @@ library Checkpoints {
uint256 pos = self.length;

if (pos > 0) {
// Copying to memory is important here.
Checkpoint224 memory last = _unsafeAccess(self, pos - 1);
Checkpoint224 storage last = _unsafeAccess(self, pos - 1);
uint32 lastKey = last._key;
uint224 lastValue = last._value;

// Checkpoint keys must be non-decreasing.
if (last._key > key) {
if (lastKey > key) {
revert CheckpointUnorderedInsertion();
}

// Update or push new checkpoint
if (last._key == key) {
if (lastKey == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint224({_key: key, _value: value}));
}
return (last._value, value);
return (lastValue, value);
} else {
self.push(Checkpoint224({_key: key, _value: value}));
return (0, value);
Expand Down Expand Up @@ -492,7 +493,7 @@ library Checkpoints {
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint160 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
Checkpoint160 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
Expand All @@ -519,21 +520,22 @@ library Checkpoints {
uint256 pos = self.length;

if (pos > 0) {
// Copying to memory is important here.
Checkpoint160 memory last = _unsafeAccess(self, pos - 1);
Checkpoint160 storage last = _unsafeAccess(self, pos - 1);
uint96 lastKey = last._key;
uint160 lastValue = last._value;

// Checkpoint keys must be non-decreasing.
if (last._key > key) {
if (lastKey > key) {
revert CheckpointUnorderedInsertion();
}

// Update or push new checkpoint
if (last._key == key) {
if (lastKey == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint160({_key: key, _value: value}));
}
return (last._value, value);
return (lastValue, value);
} else {
self.push(Checkpoint160({_key: key, _value: value}));
return (0, value);
Expand Down
13 changes: 7 additions & 6 deletions scripts/generate/templates/Checkpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function latestCheckpoint(${opts.historyTypeName} storage self)
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});
}
}
Expand Down Expand Up @@ -152,21 +152,22 @@ function _insert(
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) {
if (lastKey == key) {
_unsafeAccess(self, pos - 1).${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);
Expand Down