214 lines
6.9 KiB
Solidity

pragma solidity >=0.5.0 <0.6.0;
import "./License.sol";
import "./ArbitrationLicense.sol";
import "../common/MessageSigned.sol";
import "../common/SecuredFunctions.sol";
import "../proxy/Proxiable.sol";
/**
* @title UserStore
* @dev Users registry
*/
contract UserStore is MessageSigned, SecuredFunctions, Proxiable {
struct User {
string contactData;
string location;
string username;
}
License public sellingLicenses;
ArbitrationLicense public arbitrationLicenses;
mapping(address => User) public users;
mapping(address => uint) public user_nonce;
/**
* @param _sellingLicenses Sellers licenses contract address
* @param _arbitrationLicenses Arbitrators licenses contract address
*/
constructor(address _sellingLicenses, address _arbitrationLicenses) public
{
init(_sellingLicenses, _arbitrationLicenses);
}
/**
* @dev Initialize contract (used with proxy). Can only be called once
* @param _sellingLicenses Sellers licenses contract address
* @param _arbitrationLicenses Arbitrators licenses contract address
*/
function init(
address _sellingLicenses,
address _arbitrationLicenses
) public {
assert(_initialized == false);
_initialized = true;
sellingLicenses = License(_sellingLicenses);
arbitrationLicenses = ArbitrationLicense(_arbitrationLicenses);
_setOwner(msg.sender);
}
function updateCode(address newCode) public onlyOwner {
updateCodeAddress(newCode);
}
event LicensesChanged(address sender, address oldSellingLicenses, address newSellingLicenses, address oldArbitrationLicenses, address newArbitrationLicenses);
/**
* @dev Initialize contract (used with proxy). Can only be called once
* @param _sellingLicenses Sellers licenses contract address
* @param _arbitrationLicenses Arbitrators licenses contract address
*/
function setLicenses(
address _sellingLicenses,
address _arbitrationLicenses
) public onlyOwner {
emit LicensesChanged(msg.sender, address(sellingLicenses), address(_sellingLicenses), address(arbitrationLicenses), (_arbitrationLicenses));
sellingLicenses = License(_sellingLicenses);
arbitrationLicenses = ArbitrationLicense(_arbitrationLicenses);
}
/**
* @dev Get datahash to be signed
* @param _username Username
* @param _contactData Contact Data ContactType:UserId
* @param _nonce Nonce value (obtained from user_nonce)
* @return bytes32 to sign
*/
function _dataHash(string memory _username, string memory _contactData, uint _nonce) internal view returns (bytes32) {
uint256 cid;
assembly {
cid := chainid()
}
return keccak256(abi.encodePacked(address(this), _username, _contactData, _nonce, cid));
}
/**
* @notice Get datahash to be signed
* @param _username Username
* @param _contactData Contact Data ContactType:UserId
* @return bytes32 to sign
*/
function getDataHash(string calldata _username, string calldata _contactData) external view returns (bytes32) {
return _dataHash(_username, _contactData, user_nonce[msg.sender]);
}
/**
* @dev Get signer address from signature. This uses the signature parameters to validate the signature
* @param _username Status username
* @param _contactData Contact Data ContactType:UserId
* @param _nonce User nonce
* @param _signature Signature obtained from the previous parameters
* @return Signing user address
*/
function _getSigner(
string memory _username,
string memory _contactData,
uint _nonce,
bytes memory _signature
) internal view returns(address) {
bytes32 signHash = _getSignHash(_dataHash(_username, _contactData, _nonce));
return _recoverAddress(signHash, _signature);
}
/**
* @notice Get signer address from signature
* @param _username Status username
* @param _contactData Contact Data ContactType:UserId
* @param _nonce User nonce
* @param _signature Signature obtained from the previous parameters
* @return Signing user address
*/
function getMessageSigner(
string calldata _username,
string calldata _contactData,
uint _nonce,
bytes calldata _signature
) external view returns(address) {
return _getSigner(_username, _contactData, _nonce, _signature);
}
/**
* @dev Adds or updates user information
* @param _user User address to update
* @param _contactData Contact Data ContactType:UserId
* @param _location New location
* @param _username New status username
*/
function _addOrUpdateUser(
address _user,
string memory _contactData,
string memory _location,
string memory _username
) internal {
User storage u = users[_user];
u.contactData = _contactData;
u.location = _location;
u.username = _username;
}
/**
* @notice Adds or updates user information via signature
* @param _signature Signature
* @param _contactData Contact Data ContactType:UserId
* @param _location New location
* @param _username New status username
* @return Signing user address
*/
function addOrUpdateUser(
bytes calldata _signature,
string calldata _contactData,
string calldata _location,
string calldata _username,
uint _nonce
) external returns(address payable _user) {
_user = address(uint160(_getSigner(_username, _contactData, _nonce, _signature)));
require(_nonce == user_nonce[_user], "Invalid nonce");
user_nonce[_user]++;
_addOrUpdateUser(_user, _contactData, _location, _username);
return _user;
}
/**
* @notice Adds or updates user information
* @param _contactData Contact Data ContactType:UserId
* @param _location New location
* @param _username New status username
* @return Signing user address
*/
function addOrUpdateUser(
string calldata _contactData,
string calldata _location,
string calldata _username
) external {
_addOrUpdateUser(msg.sender, _contactData, _location, _username);
}
/**
* @notice Adds or updates user information
* @dev can only be called by the escrow contract
* @param _sender Address that sets the user info
* @param _contactData Contact Data ContactType:UserId
* @param _location New location
* @param _username New status username
* @return Signing user address
*/
function addOrUpdateUser(
address _sender,
string calldata _contactData,
string calldata _location,
string calldata _username
) external onlyAllowedContracts {
_addOrUpdateUser(_sender, _contactData, _location, _username);
}
}