-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathRaft.sol
163 lines (145 loc) · 5.22 KB
/
Raft.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
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.16;
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol";
// import "../node_modules/hardhat/console.sol";
/// @title RAFT Contract
/// @author Otterspace
/// @notice The RAFT NFT gives the owner the ability to create a DAO within Otterspace
/// @dev Inherits from ERC721Enumerable so that we can access useful functions for
/// querying owners of tokens from the web app.
contract Raft is
ERC721EnumerableUpgradeable,
UUPSUpgradeable,
OwnableUpgradeable,
PausableUpgradeable
{
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
mapping(uint256 => string) private _tokenURIs;
mapping(uint256 => mapping(address => bool)) private _admins;
event MetadataUpdate(uint256 indexed tokenId);
event AdminUpdate(
uint256 indexed tokenId,
address indexed admin,
bool isAdded
);
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/**
* @dev Initializes the contract by setting up the initial owner, name and symbol of the ERC721 token and pausing the contract.
* @param nextOwner The address of the initial owner of the contract.
* @param name_ The name of the ERC721 token.
* @param symbol_ The symbol of the ERC721 token.
*/
function initialize(
address nextOwner,
string memory name_,
string memory symbol_
) public initializer {
__ERC721Enumerable_init();
__ERC721_init(name_, symbol_);
__UUPSUpgradeable_init();
__Ownable_init();
// Passing in the owner's address allows an EOA to deploy and set a multi-sig as the owner.
transferOwnership(nextOwner);
// pause the contract by default
_pause();
}
/**
* @dev Mint a new token and assign it to the recipient, with the given URI.
* @param recipient The address to which the newly minted token will be assigned.
* @param uri The URI of the newly minted token.
* @return The ID of the newly minted token.
*/
function mint(
address recipient,
string memory uri
) public virtual returns (uint256) {
// owners can always mint tokens
// non-owners can only mint when the contract is unpaused
require(msg.sender == owner() || !paused(), "mint: unauthorized to mint");
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
require(recipient != address(0), "cannot mint to zero address");
_mint(recipient, newItemId);
_tokenURIs[newItemId] = uri;
return newItemId;
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
/**
* @dev Sets the URI of the token with the given ID.
* Reverts if the token does not exist.
* @param tokenId uint256 ID of the token to set its URI.
* @param uri string URI to assign to the token.
* @notice Only the owner of the contract can call this function.
*/
function setTokenURI(
uint256 tokenId,
string memory uri
) public virtual onlyOwner {
require(_exists(tokenId), "setTokenURI: URI set of nonexistent token");
_tokenURIs[tokenId] = uri;
emit MetadataUpdate(tokenId);
}
/**
* @notice Sets the admins for a given Raft token ID.
* @param tokenId The ID of the token for which to set the admins.
* @param admins An array of addresses to set as admins.
* @param isActive An array of boolean values indicating whether each corresponding admin address should be set as active or inactive.
*/
function setAdmins(
uint256 tokenId,
address[] memory admins,
bool[] memory isActive
) public virtual {
require(
admins.length > 0 && isActive.length > 0,
"setAdmins: invalid input"
);
require(
admins.length == isActive.length,
"setAdmins: admins and isActive must be the same length"
);
require(_exists(tokenId), "setAdmins: tokenId does not exist");
require(
ownerOf(tokenId) == msg.sender || owner() == msg.sender,
"setAdmins: unauthorized"
);
for (uint256 i = 0; i < admins.length; i++) {
_admins[tokenId][admins[i]] = isActive[i];
emit AdminUpdate(tokenId, admins[i], isActive[i]);
}
}
/** @dev Returns a boolean value indicating whether the specified admin address is active for the given token ID.
* @param tokenId The ID of the token.
* @param admin The address of the admin to check.
* @return A boolean value indicating whether the specified admin address is active for the given token ID.
*/
function isAdminActive(
uint256 tokenId,
address admin
) public view virtual returns (bool) {
return _admins[tokenId][admin];
}
/** @dev Returns the URI of a given token.
* @param tokenId The ID of the token to retrieve the URI for.
* @return The URI of the specified token.
*/
function tokenURI(
uint256 tokenId
) public view virtual override returns (string memory) {
return _tokenURIs[tokenId];
}
function _authorizeUpgrade(address) internal override onlyOwner {}
}