evm-workmode

A solidity contract for periodic participant working mode registration
git clone git://holbrook.no/evm_workmode.git
Log | Files | Refs

commit a3ccb8511fc60e8a015bce8da6a351764d4e463b
Author: nolash <dev@holbrook.no>
Date:   Sun,  9 Jan 2022 11:35:52 +0000

Initial commit

Diffstat:
Asolidity/WorkMode.sol | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+), 0 deletions(-)

diff --git a/solidity/WorkMode.sol b/solidity/WorkMode.sol @@ -0,0 +1,113 @@ +pragma solidity ^0.8.0; + +// SPDX-License-Identifier: GPL-3.0-or-later +// File-Version: 1 + +contract WorkMode { + + uint256 public startOfTimes; + uint32 public periodDuration; + mapping(address => uint32 ) public startPeriod; // 0 = not yet active, 1 = (before) start of times, 2 = first period after start of times + mapping(address => uint8[] ) public mode; // modes 1=idle, 2=active, 4=experimental + + event ParticipantAdded(address indexed origin, uint32 startPeriod); + event LogAdded(address indexed origin, uint32 indexed period, uint8 mode); + + constructor(uint32 _periodDuration, uint256 _startOfTimes) { + if (_startOfTimes == 0) { + startOfTimes = block.timestamp; + } else { + startOfTimes = _startOfTimes; + } + periodDuration = _periodDuration; + } + + // Get the current internal period from the current block timestamp. + function getPeriodInternal() private view returns (uint32) { + uint256 delta; + uint32 period; + + delta = block.timestamp - startOfTimes; + period = (uint32(delta) / periodDuration) + 2; + + return period; + } + + // Get the current zero-indexed period from the current block timetamp. + function getPeriod() public view returns (uint32) { + uint32 period; + + period = getPeriodInternal(); + + return period - 1; + } + + // Get the zero-indexed start period for the participant. + function startPeriodFor(address _participant) public view returns (uint32) { + uint32 period; + + period = startPeriod[_participant] - 1; + + return period; + } + + // Get the last internal period a participant added a mode. + function lastPeriodForInternal(address _participant) private view returns (uint32) { + uint256 idx; + uint32 originStartPeriod; + + idx = mode[_participant].length; + if (idx == 0) { + return 1; + } + + originStartPeriod = startPeriod[_participant]; + return originStartPeriod + uint32(idx); + } + + // Get the last zero-indexed period a participant added a mode. + function lastPeriodFor(address _participant) public view returns (uint32) { + uint32 period; + + period = lastPeriodForInternal(_participant); + + return period - 1; + } + + // Set the period to the initial value for an active participant + function checkInit() private { + uint32 nowPeriod; + + if (mode[tx.origin].length == 0) { + startPeriod[tx.origin] = 1; + nowPeriod = getPeriod(); + emit ParticipantAdded(tx.origin, nowPeriod); + } + } + + // Register a new mode. + // + // The period registering for must be explicit, and the mode must be for the next period after the last that was registered. + function set(uint32 _registerPeriod, uint8 _registerMode) public returns (bool) { + uint32 lastPeriod; + uint32 registerPeriodInternal; + + // Activate the participant if not yet active. + checkInit(); + + lastPeriod = lastPeriodForInternal(tx.origin); + registerPeriodInternal = _registerPeriod + 1; + if (registerPeriodInternal <= lastPeriod) { + return false; + } + + if (registerPeriodInternal - lastPeriod > 1) { + revert("period skipped"); + } + + mode[tx.origin].push(_registerMode); + emit LogAdded(tx.origin, _registerPeriod, _registerMode); + + return true; + } +}