DCIPs/assets/eip-4519/PoC_SmartNFT/PoC_SmartNFT.sol

273 lines
12 KiB
Solidity

///SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;
import "./smartNFT_interface.sol";
import "./ERC721_interface.sol";
contract smartNFT_SC is ERC721,smartNFT{
enum States { waitingForOwner, engagedWithOwner, waitingForUser, engagedWithUser }
address manufacturer; //Address of manufacturer and owner of Smart Contract
uint256 tokenCounter; //To give a genuine tokenID based on the number of tokens created
mapping(uint256 => address) ownerOfSD; //To khow who is the owner of a specific owner
mapping(address => uint256) tokenIDOfBCA; //To khow which is the tokenID associated to a secure device from the address
mapping(address => uint256) ownerBalance; //To know how many tokens an owner has
mapping(address => uint256) userBalance; //To know how many tokens a user can use
struct Token_Struct{
address approved; //Indicate who can transfer this token, 0 if no one
address SD; //Indicate the address of the secure device associated to this token
address user; //Indicate who can use this secure device
States state; //If blocked (false) then token should be verified by a new user or a new owner
uint256 hashK_OD; //Hash of the Key shared between owner and device
uint256 hashK_UD; //Hash of the Key shared between user and device
uint256 dataEngagement; //Public Key to create K_OD or K_UD depending on token state
uint256 timestamp; //Last time that device updated its proof of live
uint256 timeout; //timeout to verify a device error
}
Token_Struct[] Secure_Token;
constructor() {
manufacturer = msg.sender;
tokenCounter = 1;
Secure_Token.push(Token_Struct(address(0), address(0), address(0), States.waitingForOwner,0,0,0,0,0));
}
function createToken(address _addressSD, address _addressOwner) public virtual override returns (uint256){
//Check if the sender of message is the manufacturer
require(manufacturer == msg.sender);
//Check if the Blockchain Account of the secure device is in the SmartContract
if(tokenFromBCA(_addressSD)==0){
//Create a new token
Secure_Token.push(Token_Struct(address(0), _addressSD, address(0), States.waitingForOwner,0,0,0,block.timestamp,86400));
//Assigning a new tokenId
uint256 _tokenId = tokenCounter ++;
tokenIDOfBCA[_addressSD] = _tokenId;
//Assigning the owner
ownerOfSD[_tokenId] = _addressOwner;
ownerBalance[_addressOwner]++;
//Return tokenId obtained
return(_tokenId);
}else{
//If the BCA already exists then return the _tokenId
return(tokenFromBCA(_addressSD));
}
}
function setUser(uint256 _tokenId, address _addressUser) public virtual override{
//Check the sender and the token state
require((ownerOfSD[_tokenId] == msg.sender) && (Secure_Token[_tokenId].state >= States.engagedWithOwner));
if((Secure_Token[_tokenId].timestamp + Secure_Token[_tokenId].timeout) > block.timestamp){
//Only to avoid overflow, for example, in address 0.
if(userBalance[Secure_Token[_tokenId].user]>0){
//Update the balance of tokens assigned to the old user
userBalance[Secure_Token[_tokenId].user]--;
}
//Update the balance of tokens assigned to the new user
userBalance[_addressUser]++;
//Assign the new user to the token
Secure_Token[_tokenId].user = _addressUser;
//Update the state of the token
Secure_Token[_tokenId].state = States.waitingForUser;
//Erase old key exchange data between device with old user assigned
Secure_Token[_tokenId].dataEngagement =0;
Secure_Token[_tokenId].hashK_UD = 0;
emit UserAssigned(_tokenId,_addressUser);
}else{
Secure_Token[_tokenId].user = address(0);
emit TimeoutAlarm(_tokenId);
}
}
function startOwnerEngagement(uint256 _tokenId, uint256 _dataEngagement, uint256 _hashK_O) public virtual override{
//Check if sender is the Owner of token and the State of token
require(ownerOfSD[_tokenId] == msg.sender);
if((Secure_Token[_tokenId].timestamp + Secure_Token[_tokenId].timeout) > block.timestamp){
Secure_Token[_tokenId].dataEngagement = _dataEngagement;
Secure_Token[_tokenId].hashK_OD = _hashK_O;
}else{
Secure_Token[_tokenId].user = address(0);
emit TimeoutAlarm(_tokenId);
}
}
function ownerEngagement(uint256 _hashK_D) public virtual override{
uint256 _tokenId = tokenFromBCA(msg.sender);
//Check if public key owner-device exists from tokenID of BCA sender
require(Secure_Token[_tokenId].dataEngagement != 0);
require (Secure_Token[_tokenId].hashK_OD == _hashK_D);
require (Secure_Token[_tokenId].state == States.waitingForOwner);
//Erase PK_Owner-Device and update timestamp
Secure_Token[_tokenId].dataEngagement = 0;
Secure_Token[_tokenId].timestamp = block.timestamp;
//Update the state of token
Secure_Token[_tokenId].state = States.engagedWithOwner;
//Send a notification to owner and device
emit OwnerEngaged(_tokenId);
}
function startUserEngagement(uint256 _tokenId, uint256 _dataEngagement, uint256 _hashK_U) public virtual override{
//Check the sender and the state of token
require(Secure_Token[_tokenId].user == msg.sender);
if((Secure_Token[_tokenId].timestamp + Secure_Token[_tokenId].timeout) > block.timestamp){
Secure_Token[_tokenId].dataEngagement = _dataEngagement;
Secure_Token[_tokenId].hashK_UD = _hashK_U;
}else{
Secure_Token[_tokenId].user = address(0);
emit TimeoutAlarm(_tokenId);
}
}
function userEngagement(uint256 _hashK_D) public virtual override{
uint256 _tokenId = tokenFromBCA(msg.sender);
//Check if public key user-device exists from tokenID of BCA sender
require(Secure_Token[_tokenId].dataEngagement != 0);
require (Secure_Token[_tokenId].hashK_UD == _hashK_D);
require (Secure_Token[_tokenId].state == States.waitingForUser);
//Erase PK_User-Device and update timestamp
Secure_Token[_tokenId].dataEngagement = 0;
Secure_Token[_tokenId].timestamp = block.timestamp;
//Update the state of token
Secure_Token[_tokenId].state = States.engagedWithUser;
//Send a notification to user and device
emit UserEngaged(_tokenId);
}
function tokenFromBCA(address _addressSD) public virtual view override returns (uint256){
return(tokenIDOfBCA[_addressSD]);
}
function ownerOfFromBCA(address _addressSD) public virtual view override returns (address){
return(ownerOfSD[tokenIDOfBCA[_addressSD]]);
}
function userOf(uint256 _tokenId) public virtual view override returns (address){
return(Secure_Token[_tokenId].user);
}
function userOfFromBCA(address _addressSD) public virtual override view returns (address){
return(Secure_Token[tokenIDOfBCA[_addressSD]].user);
}
function userBalanceOf(address _addressUser) public virtual override view returns (uint256){
return(userBalance[_addressUser]);
}
function userBalanceOfAnOwner(address _addressUser, address _addressOwner) public virtual override view returns (uint256){
//TODO
}
function getInfoToken(uint256 _tokenId) public view returns ( address _BCA_OWNER,
address _BCA_USER,
address _BCA_SD,
uint8 _state){
_BCA_OWNER = ownerOfSD[_tokenId];
_BCA_USER = Secure_Token[_tokenId].user;
_BCA_SD = Secure_Token[_tokenId].SD;
if(Secure_Token[_tokenId].state == States.waitingForOwner){
_state = 0;
}else if(Secure_Token[_tokenId].state == States.engagedWithOwner){
_state = 1;
}else if(Secure_Token[_tokenId].state == States.waitingForUser){
_state = 2;
}else {
_state = 3;
}
}
function getInfoTokenFromBCA(address _addressSD) public view returns ( address _BCA_OWNER,
address _BCA_USER,
uint256 _tokenId,
uint8 _state){
_tokenId = tokenIDOfBCA[_addressSD];
_BCA_OWNER = ownerOfSD[_tokenId];
_BCA_USER = Secure_Token[_tokenId].user;
if(Secure_Token[_tokenId].state == States.waitingForOwner){
_state = 0;
}else if(Secure_Token[_tokenId].state == States.engagedWithOwner){
_state = 1;
}else if(Secure_Token[_tokenId].state == States.waitingForUser){
_state = 2;
}else {
_state = 3;
}
}
function balanceOf(address _owner) public virtual override view returns (uint256){
return(ownerBalance[_owner]);
}
function ownerOf(uint256 _tokenId) public virtual override view returns (address){
return(ownerOfSD[_tokenId]);
}
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory data) public virtual override payable{
}
function safeTransferFrom(address _from, address _to, uint256 _tokenId) public virtual override payable{
transferFrom(_from, _to, _tokenId);
}
function transferFrom(address _from, address _to, uint256 _tokenId) public virtual override payable{
require((ownerOfSD[_tokenId] == msg.sender)||(Secure_Token[_tokenId].approved == msg.sender));
require(ownerOfSD[_tokenId] == _from);
if((Secure_Token[_tokenId].timestamp + Secure_Token[_tokenId].timeout) > block.timestamp){
ownerOfSD[_tokenId] = _to;
ownerBalance[_from]--;
ownerBalance[_to]++;
//Secure_Token[_tokenId].approved = address(0);
Secure_Token[_tokenId].user = address(0);
Secure_Token[_tokenId].state = States.waitingForOwner;
//Erase old key exchange data between device with old Owner
Secure_Token[_tokenId].dataEngagement = 0;
Secure_Token[_tokenId].hashK_UD = 0;
Secure_Token[_tokenId].hashK_OD = 0;
emit Transfer(_from,_to,_tokenId);
}else{
Secure_Token[_tokenId].user = address(0);
emit TimeoutAlarm(_tokenId);
}
}
function approve(address _approved, uint256 _tokenId) public virtual override payable{
}
function setApprovalForAll(address _operator, bool _approved) public virtual override{
}
function getApproved(uint256 _tokenId) public virtual override view returns (address){
}
function isApprovedForAll(address _owner, address _operator) public virtual override view returns (bool){
}
function checkTimeout(uint256 _tokenId) public virtual override returns (bool){
require(ownerOfSD[_tokenId] == msg.sender);
if((Secure_Token[_tokenId].timestamp + Secure_Token[_tokenId].timeout) > block.timestamp){
return true;
}else{
Secure_Token[_tokenId].user = address(0);
emit TimeoutAlarm(_tokenId);
return false;
}
}
function updateTimestamp() public virtual override{
Secure_Token[tokenFromBCA(msg.sender)].timestamp = block.timestamp;
}
function setTimeout(uint256 _tokenId, uint256 _timeout) public virtual override{
require(ownerOfSD[_tokenId] == msg.sender);
Secure_Token[_tokenId].timeout = _timeout;
}
}