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编辑  收藏  举报

导航