memoscan
← all memos

Memo 0xd31bbf25…0140d5 on Ethereum

contract PseudonymPairs { uint entropy; function getRandomNumber() internal returns (uint){ entropy = uint(keccak256(abi.encodePacked(now, msg.sender, blockhash(block.number - 1), entropy))); return entropy; } uint maxValue = 2**256-1; uint schedule; uint period = 28 days; uint hour; struct Reg { bool rank; uint id; bool[] signatures; bool verified; } struct Token { mapping(address => uint) balanceOf; mapping (address => mapping (address => uint)) allowed; } struct Data { mapping(address => Reg) registry; address[] shuffler; mapping(uint => bool) disputed; Token[3] tokens; uint personhoodNonce; mapping(address => uint) proofOfPersonhood; } mapping(uint => Data) data; function pseudonymEvent() public view returns (uint) { return schedule + period + hour * 3600; } modifier scheduler() { if(block.timestamp > pseudonymEvent()) { schedule += period; hour = getRandomNumber()%24; } _; } function isReg(address _account) public view returns (bool) { return data[schedule].registry[_account].signatures.length != 0; } function register() public scheduler { require(isReg(msg.sender) == false && data[schedule].tokens[1].balanceOf[msg.sender] >= 1); data[schedule].tokens[1].balanceOf[msg.sender]--; uint id; if(data[schedule].shuffler.length != 0) { id += getRandomNumber() % data[schedule].shuffler.length; data[period].registry[data[period].shuffler[id]].id = data[period].shuffler.length; data[schedule].shuffler.push(data[schedule].shuffler[id]); } else data[schedule].shuffler.push(); data[schedule].shuffler[id] = msg.sender; data[schedule].registry[msg.sender] = Reg(true, id, new bool[](1), false); data[schedule+period].tokens[0].balanceOf[msg.sender]++; } function immigrate() public scheduler { require(isReg(msg.sender) == false && data[schedule].tokens[0].balanceOf[msg.sender] >= 1); data[schedule].tokens[0].balanceOf[msg.sender]--; data[schedule].registry[msg.sender] = Reg(false, getRandomNumber(), new bool[](2), false); data[schedule].tokens[0].balanceOf[data[schedule-period].shuffler[getRandomNumber()%data[schedule-period].shuffler.length]]++; } function transferRegistrationKey(address _to) public scheduler { require(isReg(msg.sender) == true && isReg(_to) == false); if(data[schedule].registry[msg.sender].rank == true) data[schedule].shuffler[data[schedule].registry[msg.sender].id] = _to; data[schedule].registry[_to] = data[schedule].registry[msg.sender]; delete data[schedule].registry[msg.sender]; } function pairVerified(uint _pair) internal view returns (bool) { address peer1 = data[schedule-period].shuffler[_pair]; address peer2 = data[schedule-period].shuffler[_pair + 1]; return (data[schedule-period].registry[peer1].signatures[0] == true && data[schedule-period].registry[peer2].signatures[0] == true); } function dispute() public scheduler { require(data[schedule-period].registry[msg.sender].rank == true); uint pair = data[schedule-period].registry[msg.sender].id/2; require(pairVerified(pair) == false); data[schedule-period].disputed[pair] = true; } function getPair(address _account) internal view returns (uint) { if(data[schedule-period].registry[_account].rank == true) return data[schedule-period].registry[_account].id/2; return data[schedule-period].registry[msg.sender].id%(data[schedule-period].shuffler.length/2); } function reassign() public scheduler { require(data[schedule-period].disputed[getPair(msg.sender)] == true); delete data[schedule-period].registry[msg.sender]; data[schedule-period].registry[msg.sender] = Reg(false, getRandomNumber(), new bool[](2), false); } function verifyPersonhood(address _account) public scheduler returns (uint) { require(data[schedule].proofOfPersonhood[_account] != 0); return data[schedule].proofOfPersonhood[_account]; } function lockProofOfPersonhood() public scheduler { require(data[schedule].tokens[2].balanceOf[msg.sender] >= 1); require(data[schedule].proofOfPersonhood[msg.sender] == 0); data[schedule].tokens[2].balanceOf[msg.sender]--; data[schedule].personhoodNonce++; data[schedule].proofOfPersonhood[msg.sender] = data[schedule].personhoodNonce; } function transferPersonhoodKey(address _account) public scheduler { require(data[schedule].proofOfPersonhood[msg.sender] == 0 && _account != msg.sender); data[schedule].proofOfPersonhood[_account] = data[schedule].proofOfPersonhood[msg.sender]; delete data[schedule].proofOfPersonhood[msg.sender]; } function collectPersonhood() public scheduler { require(data[schedule-period].registry[msg.sender].verified = false); require(pairVerified(getPair(msg.sender)) == true); if(data[schedule-period].registry[msg.sender].rank == false) require(data[schedule-period].registry[msg.sender].signatures[0] == true && data[schedule-period].registry[msg.sender].signatures[1] == true); data[schedule].tokens[1].balanceOf[msg.sender]++; data[schedule].tokens[2].balanceOf[msg.sender]++; data[schedule-period].registry[msg.sender].verified = true; } function verify(address _account, address _signer) internal { require(_account != _signer && data[schedule-period].registry[_signer].rank == true); uint pair = getPair(_account); require(data[schedule-period].disputed[pair] == false && pair == getPair(_signer)); if(data[schedule-period].registry[_account].rank == true) data[schedule-period].registry[_account].signatures[0] = true; else data[schedule-period].registry[_account].signatures[data[schedule-period].registry[_signer].id%2] = true; } function verifyAccount(address _account) public scheduler { verify(_account, msg.sender); } function uploadSignature(address _account, bytes memory _signature) public scheduler { bytes32 r; bytes32 s; uint8 v; assembly { r := mload(add(_signature,0x20)) s := mload(add(_signature,0x40)) v := and(mload(add(_signature, 0x41)), 0xFF) } if (v < 27) v += 27; bytes32 msgHash = keccak256(abi.encodePacked(_account, schedule)); verify(_account, ecrecover(msgHash, v, r, s)); } function transfer(address _from, address _to, uint _value, uint _token) internal { require(data[schedule].tokens[_token].balanceOf[_from] >= _value); data[schedule].tokens[_token].balanceOf[_from] -= _value; data[schedule].tokens[_token].balanceOf[_to] += _value; } function delegate(address _spender, uint _value, uint _token) internal { data[schedule].tokens[_token].allowed[msg.sender][_spender] = _value; } function collect(address _from, address _to, uint _value, uint _token) internal { require(data[schedule].tokens[_token].allowed[_from][msg.sender] >= _value); transfer(_from, _to, _value, _token); data[schedule].tokens[_token].allowed[_from][msg.sender] -= _value; } function transferImmigrationToken(address _to, uint _value) public scheduler { transfer(msg.sender, _to, _value, 0); } function transferRegistrationToken(address _to, uint _value) public scheduler { transfer(msg.sender, _to, _value, 1); } function transferVerifiedToken(address _to, uint _value) public scheduler { transfer(msg.sender, _to, _value, 2); } function delegateImmigrationToken(address _spender, uint _value) public scheduler { delegate(_spender, _value, 0); } function delegateRegistrationToken(address _spender, uint _value) public scheduler { delegate(_spender, _value, 1); } function delegateVerifiedToken(address _spender, uint _value) public scheduler { delegate(_spender, _value, 2); } function collectImmigrationToken(address _from, address _to, uint _value) public scheduler { collect(_from, _to, _value, 0); } function collectRegistrationToken(address _from, address _to, uint _value) public scheduler { collect(_from, _to, _value, 1); } function collectVerifiedToken(address _from, address _to, uint _value) public scheduler { collect(_from, _to, _value, 2); } function initiateNetwork() public { require(block.timestamp > pseudonymEvent()); schedule = 198000 + ((block.timestamp - 198000)/ 7 days) * 7 days - 21 days; require(data[schedule-period].shuffler.length < 2); hour = getRandomNumber()%24; data[schedule].tokens[1].balanceOf[msg.sender] = maxValue; } }