0x668143c4…385fsent to0xb305f876…42f1·#10,580,203·0xd31bbf25…0140d5
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;
}
}