evm-workmode

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

WorkMode.sol (3058B)


      1 pragma solidity ^0.8.0;
      2 
      3 // SPDX-License-Identifier: GPL-3.0-or-later
      4 // File-Version: 1
      5 
      6 contract WorkMode {
      7 
      8 	uint256 public startOfTimes;
      9 	uint32 public periodDuration;
     10 	mapping(address => uint32 ) public startPeriod; // 0 = not yet active, 1 = (before) start of times, 2 = first period after start of times
     11 	mapping(address => uint8[] ) public mode; // modes 1=idle, 2=active, 4=experimental
     12 
     13 	event ParticipantAdded(address indexed origin, uint32 startPeriod);
     14 	event LogAdded(address indexed origin, uint32 indexed period, uint8 mode);
     15 
     16 	constructor(uint32 _periodDuration, uint256 _startOfTimes) {
     17 		if (_startOfTimes == 0) {
     18 			startOfTimes = block.timestamp;
     19 		} else {
     20 			startOfTimes = _startOfTimes;
     21 		}
     22 		periodDuration = _periodDuration;
     23 	}
     24 
     25 	// Get the current internal period from the current block timestamp.
     26 	function getPeriodInternal() private view returns (uint32) {
     27 		uint256 delta;
     28 		uint32 period;
     29 
     30 		delta = block.timestamp - startOfTimes;
     31 		period = (uint32(delta) / periodDuration) + 2;
     32 
     33 		return period;
     34 	}
     35 
     36 	// Get the current zero-indexed period from the current block timetamp.
     37 	function getPeriod() public view returns (uint32) {
     38 		uint32 period;
     39 	       
     40 		period	= getPeriodInternal();
     41 
     42 		return period - 1;
     43 	}
     44 
     45 	// Get the zero-indexed start period for the participant.
     46 	function startPeriodFor(address _participant) public view returns (uint32) {
     47 		uint32 period;
     48 
     49 		period = startPeriod[_participant] - 1;
     50 
     51 		return period;
     52 	}
     53 
     54 	// Get the last internal period a participant added a mode.
     55 	function lastPeriodForInternal(address _participant) private view returns (uint32) {
     56 		uint256 idx;
     57 		uint32 originStartPeriod;
     58 
     59 		idx = mode[_participant].length;
     60 		if (idx == 0) {
     61 			return 1;
     62 		}
     63 
     64 		originStartPeriod = startPeriod[_participant];
     65 		return originStartPeriod + uint32(idx);
     66 	}
     67 
     68 	// Get the last zero-indexed period a participant added a mode.
     69 	function lastPeriodFor(address _participant) public view returns (uint32) {
     70 		uint32 period;
     71 		
     72 		period = lastPeriodForInternal(_participant);
     73 
     74 		return period - 1;
     75 	}
     76 
     77 	// Set the period to the initial value for an active participant
     78 	function checkInit() private {
     79 		uint32 nowPeriod;
     80 
     81 		if (mode[tx.origin].length == 0) {
     82 			startPeriod[tx.origin] = 1;
     83 			nowPeriod = getPeriod();
     84 			emit ParticipantAdded(tx.origin, nowPeriod);
     85 		}
     86 	}
     87 
     88 	// Register a new mode.
     89 	//
     90 	// The period registering for must be explicit, and the mode must be for the next period after the last that was registered.
     91 	function set(uint32 _registerPeriod, uint8 _registerMode) public returns (bool) {
     92 		uint32 lastPeriod;
     93 		uint32 registerPeriodInternal;
     94 
     95 		// Activate the participant if not yet active.
     96 		checkInit();
     97 
     98 		lastPeriod = lastPeriodForInternal(tx.origin);
     99 		registerPeriodInternal = _registerPeriod + 1;
    100 		if (registerPeriodInternal <= lastPeriod) {
    101 			return false;		
    102 		}
    103 	
    104 		if (registerPeriodInternal - lastPeriod > 1) {
    105 			revert("period skipped");
    106 		}
    107 
    108 		mode[tx.origin].push(_registerMode);
    109 		emit LogAdded(tx.origin, _registerPeriod, _registerMode);
    110 
    111 		return true;
    112 	}
    113 }