forked from JessicaChg/semanticSBT
/
Dao.sol
194 lines (150 loc) · 5.88 KB
/
Dao.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "@openzeppelin/contracts/utils/Strings.sol";
import "../core/SemanticSBTUpgradeable.sol";
import "../interfaces/social/IDao.sol";
contract Dao is IDao, SemanticSBTUpgradeable {
using Strings for uint256;
using Strings for address;
SubjectPO[] private joinDaoSubjectPO;
uint256 constant JOIN_PREDICATE_INDEX = 1;
uint256 constant DAO_URI_PREDICATE_INDEX = 2;
string constant DAO_CLASS_NAME = "Dao";
address public ownerOfDao;
string public daoURI;
bool _setDaoURI;
bool _isFreeJoin;
mapping(address => uint256) ownedTokenId;
address public verifyContract;
modifier onlyDaoOwner{
require(msg.sender == ownerOfDao, "Dao: must be daoOwner");
_;
}
modifier onlyVerifyContract{
require(msg.sender == verifyContract, "Dao: must be verify contract");
_;
}
/* ============ External Functions ============ */
function initialize(
address owner,
address minter,
address verifyContract_,
string memory name_,
string memory symbol_,
string memory baseURI_,
string memory schemaURI_,
string[] memory classes_,
Predicate[] memory predicates_
) external override {
super.initialize(minter, name_, symbol_, baseURI_, schemaURI_, classes_, predicates_);
_setOwner(owner);
_join(owner);
verifyContract = verifyContract_;
}
function setDaoURI(string calldata daoURI_) external {
_setDaoURIInternal(msg.sender, daoURI_);
}
function setName(string calldata newName) external override {
_setName(msg.sender, newName);
}
function setFreeJoin(bool isFreeJoin_) external {
_setFreeJoin(msg.sender, isFreeJoin_);
}
function ownerTransfer(address to) external {
_ownerTransfer(msg.sender, to);
}
function addMember(address[] calldata addr) external onlyDaoOwner {
for (uint256 i = 0; i < addr.length;) {
_join(addr[i]);
unchecked{
i++;
}
}
}
function join() external returns (uint256 tokenId){
require(_isFreeJoin, "Dao: permission denied");
tokenId = _join(msg.sender);
}
function remove(address addr) external returns (uint256 tokenId){
return _remove(msg.sender, addr);
}
function setDaoURIBySigner(address addr, string calldata daoURI_) external onlyVerifyContract {
_setDaoURIInternal(addr, daoURI_);
}
function setFreeJoinBySigner(address addr, bool isFreeJoin_) external onlyVerifyContract {
_setFreeJoin(addr, isFreeJoin_);
}
function addMemberBySigner(address addr,address[] calldata members) external onlyVerifyContract {
require(addr == ownerOfDao, "Dao: permission denied");
for (uint256 i = 0; i < members.length;) {
_join(members[i]);
unchecked{
i++;
}
}
}
function joinBySigner(address addr) external onlyVerifyContract {
require(_isFreeJoin, "Dao: permission denied");
_join(addr);
}
function removeBySigner(address addr, address member) external onlyVerifyContract {
_remove(addr, member);
}
function isFreeJoin() external view returns (bool){
return _isFreeJoin;
}
function isMember(address addr) external view returns (bool){
return ownedTokenId[addr] != 0;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(SemanticSBTUpgradeable) returns (bool) {
return interfaceId == type(IDao).interfaceId ||
super.supportsInterface(interfaceId);
}
/* ============ Internal Functions ============ */
function _setOwner(address owner) internal {
ownerOfDao = owner;
uint256 sIndex = SemanticSBTLogicUpgradeable.addSubject(address(this).toHexString(), DAO_CLASS_NAME, _subjects, _subjectIndex, _classIndex);
joinDaoSubjectPO.push(SubjectPO(JOIN_PREDICATE_INDEX, sIndex));
}
function _setDaoURIInternal(address addr, string memory daoURI_) internal {
require(addr == ownerOfDao, "Dao: must be daoOwner");
daoURI = daoURI_;
string memory rdf = SemanticSBTLogicUpgradeable.buildStringRDFCustom(DAO_CLASS_NAME, address(this).toHexString(), _predicates[DAO_URI_PREDICATE_INDEX].name, string.concat('"', daoURI_, '"'));
if (!_setDaoURI) {
_setDaoURI = true;
emit CreateRDF(0, rdf);
} else {
emit UpdateRDF(0, rdf);
}
}
function _setName(address addr, string memory newName) internal {
require(addr == ownerOfDao, "Dao: must be daoOwner");
_name = newName;
}
function _setFreeJoin(address addr, bool isFreeJoin_) internal {
require(addr == ownerOfDao, "Dao: must be daoOwner");
_isFreeJoin = isFreeJoin_;
}
function _ownerTransfer(address addr, address to) internal {
require(addr == ownerOfDao, "Dao: must be daoOwner");
ownerOfDao = to;
}
function _join(address addr) internal returns (uint256 tokenId){
require(ownedTokenId[addr] == 0, string.concat("Dao:", addr.toHexString(), " already minted"));
tokenId = _addEmptyToken(addr, 0);
ownedTokenId[addr] = tokenId;
_mint(tokenId, addr, new IntPO[](0), new StringPO[](0), new AddressPO[](0),
joinDaoSubjectPO, new BlankNodePO[](0));
}
function _remove(address caller, address addr) internal returns (uint256 tokenId){
require(caller == ownerOfDao || caller == addr, "Dao: permission denied");
tokenId = ownedTokenId[addr];
require(ownedTokenId[addr] != 0, "Dao: not the member of dao");
super._burn(ownedTokenId[addr]);
delete ownedTokenId[addr];
if(addr == ownerOfDao){
ownerOfDao = address(0);
}
return tokenId;
}
}