pragma solidity 0.5.17; library OperatorParams { // OperatorParams packs values that are commonly used together // into a single uint256 to reduce the cost functions // like querying eligibility. // // An OperatorParams uint256 contains: // - the operator's staked token amount (uint128) // - the operator's creation timestamp (uint64) // - the operator's undelegation timestamp (uint64) // // These are packed as [amount | createdAt | undelegatedAt] // // Staked KEEP is stored in an uint128, // which is sufficient because KEEP tokens have 18 decimals (2^60) // and there will be at most 10^9 KEEP in existence (2^30). // // Creation and undelegation times are stored in an uint64 each. // Thus uint64s would be sufficient for around 3*10^11 years. uint256 constant TIMESTAMP_WIDTH = 64; uint256 constant AMOUNT_WIDTH = 128; uint256 constant TIMESTAMP_MAX = (2**TIMESTAMP_WIDTH) - 1; uint256 constant AMOUNT_MAX = (2**AMOUNT_WIDTH) - 1; uint256 constant CREATION_SHIFT = TIMESTAMP_WIDTH; uint256 constant AMOUNT_SHIFT = 2 * TIMESTAMP_WIDTH; function pack( uint256 amount, uint256 createdAt, uint256 undelegatedAt ) internal pure returns (uint256) { // Check for staked amount overflow. // We shouldn't actually ever need this. require(amount <= AMOUNT_MAX, "uint128 overflow"); // Bitwise OR the timestamps together. // The resulting number is equal or greater than either, // and tells if we have a bit set outside the 64 available bits. require( (createdAt | undelegatedAt) <= TIMESTAMP_MAX, "uint64 overflow" ); return ((amount << AMOUNT_SHIFT) | (createdAt << CREATION_SHIFT) | undelegatedAt); } function unpack(uint256 packedParams) internal pure returns ( uint256 amount, uint256 createdAt, uint256 undelegatedAt ) { amount = getAmount(packedParams); createdAt = getCreationTimestamp(packedParams); undelegatedAt = getUndelegationTimestamp(packedParams); } function getAmount(uint256 packedParams) internal pure returns (uint256) { return (packedParams >> AMOUNT_SHIFT) & AMOUNT_MAX; } function setAmount(uint256 packedParams, uint256 amount) internal pure returns (uint256) { return pack( amount, getCreationTimestamp(packedParams), getUndelegationTimestamp(packedParams) ); } function getCreationTimestamp(uint256 packedParams) internal pure returns (uint256) { return (packedParams >> CREATION_SHIFT) & TIMESTAMP_MAX; } function setCreationTimestamp( uint256 packedParams, uint256 creationTimestamp ) internal pure returns (uint256) { return pack( getAmount(packedParams), creationTimestamp, getUndelegationTimestamp(packedParams) ); } function getUndelegationTimestamp(uint256 packedParams) internal pure returns (uint256) { return packedParams & TIMESTAMP_MAX; } function setUndelegationTimestamp( uint256 packedParams, uint256 undelegationTimestamp ) internal pure returns (uint256) { return pack( getAmount(packedParams), getCreationTimestamp(packedParams), undelegationTimestamp ); } function setAmountAndCreationTimestamp( uint256 packedParams, uint256 amount, uint256 creationTimestamp ) internal pure returns (uint256) { return pack( amount, creationTimestamp, getUndelegationTimestamp(packedParams) ); } }