-
Notifications
You must be signed in to change notification settings - Fork 0
/
SoulBound.sol
92 lines (77 loc) · 2.7 KB
/
SoulBound.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract SoulBound is ERC721 {
string public uri;
address public owner;
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
mapping(address => bool) public whitelistedAddresses; // Whitelisted addresses to mint tokens
mapping(address => bool) public tokenMintedAddress; // Addresses that have already minted tokens
IERC20 token;
constructor(
address tokenAddress,
string memory _uri
) ERC721("SoulBound Token", "SBT") {
owner = msg.sender;
token = IERC20(tokenAddress);
uri = _uri;
}
function updateUri(string memory newUri) public onlyOwner {
uri = newUri;
}
function addToWhiteList(address _add) public onlyOwner {
if (whitelistedAddresses[_add]) {
revert("Address is already whitelisted");
}
whitelistedAddresses[_add] = true;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not the owner");
_;
}
modifier onlyWhitelistedUser() {
require(whitelistedAddresses[msg.sender], "Could not mint the token");
_;
}
function safeMint() public onlyWhitelistedUser {
whitelistedAddresses[msg.sender] = false;
tokenMintedAddress[msg.sender] = true;
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(msg.sender, tokenId);
}
function burn(uint256 tokenId) external {
require(
ownerOf(tokenId) == msg.sender,
"Only the owner of the token can burn it"
);
_burn(tokenId);
}
function revoke(uint256 tokenId) external onlyOwner {
_burn(tokenId);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId,
uint256 batchSize
) internal override(ERC721) {
require(from == address(0), "Token not transferable");
super._beforeTokenTransfer(from, to, tokenId, batchSize);
}
function _burn(uint256 tokenId) internal override(ERC721) {
super._burn(tokenId);
}
function tokenURI(
uint256 tokenId
) public view override returns (string memory) {
require(_exists(tokenId), "URI query for nonexistent token");
return super.tokenURI(tokenId);
}
function hasToken() external view returns (bool) {
return tokenMintedAddress[msg.sender];
}
}