区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。
狭义来讲,区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式数据结构,并以密码学方式保证的不可篡改和不可伪造的分布式账本。
广义来讲,区块链技术是利用块链式数据结构来验证与存储数据、利用分布式节点共识算法来生成和更新数据、利用密码学的方式保证数据传输和访问的安全、利用由自动化脚本代码组成的智能合约来编程和操作数据的一种全新的分布式基础架构与计算方式。
在区块链技术中的数据有一定的顺序性, 每个数据区块都有一个“哈希值”代码,在链状数据结构中,任意区块中的数据改变都会影响后续与之相关所有区块的信息变化。这一技术确保区块链上的每个区块数据都不能随意被篡改、删除或破坏。因此,区块链技术在保证电子档案完整、真实的基础上还具有较强的追溯性
//SPDX-License-Identifier:MIT
pragma solidity^0.8.0;
import"openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import"./IERC4907.sol";
contract ERC4907 is ERC721URIStorage,IERC4907{
struct UserInfo{
address user;//address of user role
uint64 expires;//unix timestamp,user expires
}
mapping(uint256=>UserInfo)internal _users;
constructor(string memory name_,string memory symbol_)ERC721(name_,symbol_){}
///notice set the user and expires of a NFT
///dev The zero address indicates there is no user
///Throws iftokenId
is not valid NFT
///param user The new user of the NFT
///param expires UNIX timestamp,The new user could use the NFT before expires
function setUser(
uint256 tokenId,
address user,
uint64 expires
)public virtual override{
require(
_isApprovedOrOwner(msg.sender,tokenId),
"ERC721:transfer caller is not owner nor approved"
);
UserInfo storage info=_users[tokenId];
info.user=user;
info.expires=expires;
emit UpdateUser(tokenId,user,expires);
}
///notice Get the user address of an NFT
///dev The zero address indicates that there is no user or the user is expired
///param tokenId The NFT to get the user address for
///return The user address for this NFT
function userOf(uint256 tokenId)
public
view
virtual
override
returns(address)
{
if(uint256(_users[tokenId].expires)>=block.timestamp){
return _users[tokenId].user;
}else{
return address(0);
}
}
///notice Get the user expires of an NFT
///dev The zero value indicates that there is no user
///param tokenId The NFT to get the user expires for
///return The user expires for this NFT
function userExpires(uint256 tokenId)
public
view
virtual
override
returns(uint256)
{
return _users[tokenId].expires;
}
///dev See{IERC165-supportsInterface}.
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override
returns(bool)
{
return
interfaceId==type(IERC4907).interfaceId||
super.supportsInterface(interfaceId);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
)internal virtual override{
super._beforeTokenTransfer(from,to,tokenId);
if(from!=to&&_users[tokenId].user!=address(0)){
delete _users[tokenId];
emit UpdateUser(tokenId,address(0),0);
}
}
}