-
Notifications
You must be signed in to change notification settings - Fork 1
/
ScrollBadge.sol
98 lines (76 loc) · 3.24 KB
/
ScrollBadge.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
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Attestation} from "@eas/contracts/IEAS.sol";
import {decodeBadgeData} from "../Common.sol";
import {IScrollBadge} from "../interfaces/IScrollBadge.sol";
import {IScrollBadgeResolver} from "../interfaces/IScrollBadgeResolver.sol";
import {AttestationBadgeMismatch, Unauthorized} from "../Errors.sol";
/// @title ScrollBadge
/// @notice This contract implements the basic functionalities of a Scroll badge.
/// It serves as the base contract for more complex badge functionalities.
abstract contract ScrollBadge is IScrollBadge {
// The global Scroll badge resolver contract.
address public immutable resolver;
// wallet address => badge count
mapping(address => uint256) private _userBadgeCount;
/// @dev Creates a new ScrollBadge instance.
/// @param resolver_ The address of the global Scroll badge resolver contract.
constructor(address resolver_) {
resolver = resolver_;
}
/// @inheritdoc IScrollBadge
function issueBadge(Attestation calldata attestation) public returns (bool) {
// only callable from resolver
if (msg.sender != address(resolver)) {
revert Unauthorized();
}
// delegate logic to subcontract
if (!onIssueBadge(attestation)) {
return false;
}
_userBadgeCount[attestation.recipient] += 1;
emit IssueBadge(attestation.uid);
return true;
}
/// @inheritdoc IScrollBadge
function revokeBadge(Attestation calldata attestation) public returns (bool) {
// only callable from resolver
if (msg.sender != address(resolver)) {
revert Unauthorized();
}
// delegate logic to subcontract
if (!onRevokeBadge(attestation)) {
return false;
}
_userBadgeCount[attestation.recipient] -= 1;
emit RevokeBadge(attestation.uid);
return true;
}
/// @notice A resolver callback that should be implemented by child contracts.
/// @param {attestation} The new attestation.
/// @return Whether the attestation is valid.
function onIssueBadge(Attestation calldata /*attestation*/) internal virtual returns (bool) {
return true;
}
/// @notice A resolver callback that should be implemented by child contracts.
/// @param {attestation} The existing attestation to be revoked.
/// @return Whether the attestation can be revoked.
function onRevokeBadge(Attestation calldata /*attestation*/) internal virtual returns (bool) {
return true;
}
/// @inheritdoc IScrollBadge
function getAndValidateBadge(bytes32 uid) public view returns (Attestation memory) {
Attestation memory attestation = IScrollBadgeResolver(resolver).getAndValidateBadge(uid);
(address badge, ) = decodeBadgeData(attestation.data);
if (badge != address(this)) {
revert AttestationBadgeMismatch(uid);
}
return attestation;
}
/// @inheritdoc IScrollBadge
function badgeTokenURI(bytes32 uid) public view virtual returns (string memory);
/// @inheritdoc IScrollBadge
function hasBadge(address user) public view virtual returns (bool) {
return _userBadgeCount[user] > 0;
}
}