-
Notifications
You must be signed in to change notification settings - Fork 0
/
Review-SBT.sol
146 lines (121 loc) · 3.78 KB
/
Review-SBT.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
interface IExternalNFT is IERC721 {
function ownerOf(uint256 tokenId) external view returns (address);
}
contract CryptoVitaeReviewSBT is Ownable, ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
IExternalNFT public externalNFTContract;
enum Visibility {
Private,
Public
}
struct Review {
Visibility visibility;
uint256 companyNFTId;
}
mapping(uint256 => string) private _tokenURIs;
mapping(uint256 => Review) private _reviews;
mapping(address => uint256[]) private _reviewsByEmployee;
mapping(address => uint256[]) private _reviewsByCompany;
constructor(address _externalNFTContract)
ERC721("CryptoVitaeReviewSBT", "CVR")
Ownable(msg.sender)
{
externalNFTContract = IExternalNFT(_externalNFTContract);
}
modifier onlyNFTHolder(uint256 nftId) {
require(
externalNFTContract.ownerOf(nftId) == msg.sender,
"You must own the NFT from the external contract"
);
_;
}
modifier onlyHolder(uint256 tokenId) {
require(ownerOf(tokenId) == msg.sender, "Not the owner of this SBT");
_;
}
function createSBT(
address employee,
string memory tokenURI,
uint256 companyNFTId
) public onlyNFTHolder(companyNFTId) returns (uint256) {
_tokenIds.increment();
uint256 tokenId = _tokenIds.current();
_mint(employee, tokenId);
_reviews[tokenId] = Review({
visibility: Visibility.Private,
companyNFTId: companyNFTId
});
_reviewsByEmployee[employee].push(tokenId);
_reviewsByCompany[msg.sender].push(tokenId);
_setTokenURI(tokenId, tokenURI);
return tokenId;
}
function approveSBT(uint256 tokenId) public onlyHolder(tokenId) {
require(
_reviews[tokenId].visibility == Visibility.Private,
"SBT is already public"
);
_reviews[tokenId].visibility = Visibility.Public;
}
function getReview(uint256 tokenId)
public
view
returns (
string memory tokenURI,
Visibility visibility,
uint256 companyNFTId
)
{
Review memory review = _reviews[tokenId];
require(
review.visibility == Visibility.Public ||
ownerOf(tokenId) == msg.sender,
"This SBT is private"
);
return (_tokenURIs[tokenId], review.visibility, review.companyNFTId);
}
function getReviewsByEmployee(address employee)
public
view
returns (uint256[] memory)
{
return _reviewsByEmployee[employee];
}
function getReviewsByCompany(address company)
public
view
returns (uint256[] memory)
{
return _reviewsByCompany[company];
}
function _setTokenURI(uint256 tokenId, string memory tokenURI) internal {
_tokenURIs[tokenId] = tokenURI;
}
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
return _tokenURIs[tokenId];
}
function _update(
address to,
uint256 tokenId,
address auth
) internal override(ERC721) returns (address) {
address from = _ownerOf(tokenId);
if (from != address(0) && (to != address(0))) {
revert("Soulbound: Transfer failed");
}
return super._update(to, tokenId, auth);
}
}