library Checkpoints:Transform openzeppelin
使用时间戳替换区块号,check数字支持uint256。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library Checkpoints {
struct data{
uint32 fromTime;
uint256 quantity;
}
struct Checkpoint {
mapping (address => mapping (uint32 => data)) checkpoints;
mapping (address => uint32) numCheckpoints;
}
// --------------checkpoint-----------
function _getCurrentQuantity(Checkpoint storage checkpoint,address account) internal view returns (uint256) {
uint32 nCheckpoints = checkpoint.numCheckpoints[account];
return nCheckpoints > 0 ? checkpoint.checkpoints[account][nCheckpoints - 1].quantity : 0;
}
function getCurrentQuantity(Checkpoint storage checkpoint,address account) external view returns (uint256) {
return _getCurrentQuantity(checkpoint,account);
}
function getPriorQuantity(Checkpoint storage checkpoint,address account, uint blockTimestamp) external view returns (uint256) {
return _getPriorQuantity(checkpoint,account,blockTimestamp);
}
function _getPriorQuantity(Checkpoint storage checkpoint,address account, uint blockTimestamp) internal view returns (uint256) {
require(blockTimestamp < block.timestamp, "ShipSell::getPriorQuantity: not yet determined");
uint32 nCheckpoints = checkpoint.numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (checkpoint.checkpoints[account][nCheckpoints - 1].fromTime <= blockTimestamp) {
return checkpoint.checkpoints[account][nCheckpoints - 1].quantity;
}
// Next check implicit zero balance
if (checkpoint.checkpoints[account][0].fromTime > blockTimestamp) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
data memory cp = checkpoint.checkpoints[account][center];
if (cp.fromTime == blockTimestamp) {
return cp.quantity;
} else if (cp.fromTime < blockTimestamp) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoint.checkpoints[account][lower].quantity;
}
function _writeCheckpoint(Checkpoint storage checkpoint,address account, uint256 newQuantity) internal {
uint32 blockTimestamp = uint32(block.timestamp);
uint32 nCheckpoints = checkpoint.numCheckpoints[msg.sender];
if (nCheckpoints > 0 && checkpoint.checkpoints[account][nCheckpoints - 1].fromTime == blockTimestamp) {
checkpoint.checkpoints[account][nCheckpoints - 1].quantity = newQuantity;
} else {
checkpoint.checkpoints[account][nCheckpoints] = data(blockTimestamp, newQuantity);
checkpoint.numCheckpoints[account] = nCheckpoints + 1;
}
}
function WriteCheckpoint(Checkpoint storage checkpoint,address account, uint256 newQuantity) external {
_writeCheckpoint(checkpoint,account,newQuantity);
}
}
mock:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "./Checkpoints.sol";
contract CheckpointsMock{
using Checkpoints for Checkpoints.Checkpoint;
Checkpoints.Checkpoint example;
function write(uint256 amount)external{
uint256 current = Checkpoints.getCurrentQuantity(example,msg.sender);
Checkpoints.WriteCheckpoint(example,msg.sender,current+amount);
}
function readCurrent()public view returns (uint256){
return Checkpoints.getCurrentQuantity(example,msg.sender);
}
function readPrior(uint256 fromTime)public view returns (uint256){
return Checkpoints.getPriorQuantity(example,msg.sender,fromTime);
}
}
posted on 2022-06-24 16:06 angry-baby 阅读(34) 评论(0) 编辑 收藏 举报