lens-modules 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contracts/LensHub.sol +0 -2
- package/contracts/base/LensProfiles.sol +50 -3
- package/contracts/base/upgradeability/VersionedInitializable.sol +50 -0
- package/contracts/interfaces/IHandleTokenURI.sol +11 -0
- package/contracts/interfaces/ILensHandles.sol +106 -0
- package/contracts/interfaces/ILensHubInitializable.sol +28 -0
- package/contracts/interfaces/ILensProfiles.sol +5 -0
- package/contracts/libraries/StorageLib.sol +22 -16
- package/contracts/libraries/constants/Errors.sol +2 -0
- package/contracts/libraries/svgs/Follow/FollowSVG.sol +16 -0
- package/contracts/libraries/svgs/Handle/GintoNordFontSVG.sol +9 -0
- package/contracts/libraries/svgs/Handle/HandleSVG.sol +255 -0
- package/contracts/libraries/svgs/Profile/Body/BodyHoodie.sol +21 -0
- package/contracts/libraries/svgs/Profile/Body/BodyJacket.sol +21 -0
- package/contracts/libraries/svgs/Profile/Body/BodyTShirt.sol +21 -0
- package/contracts/libraries/svgs/Profile/Body/BodyTanktop.sol +21 -0
- package/contracts/libraries/svgs/Profile/Body.sol +119 -0
- package/contracts/libraries/svgs/Profile/Face.sol +145 -0
- package/contracts/libraries/svgs/Profile/Hands.sol +121 -0
- package/contracts/libraries/svgs/Profile/Head.sol +33 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearBeanie.sol +71 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearCrown.sol +67 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearFloral.sol +67 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearGlasses.sol +67 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearHat.sol +79 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearIcecream.sol +55 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearLeafs.sol +67 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearMushroom.sol +83 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearNightcap.sol +67 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearPartyhat.sol +69 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearPlants.sol +71 -0
- package/contracts/libraries/svgs/Profile/Headwear/HeadwearSparkles.sol +55 -0
- package/contracts/libraries/svgs/Profile/Headwear.sol +155 -0
- package/contracts/libraries/svgs/Profile/Helpers.sol +83 -0
- package/contracts/libraries/svgs/Profile/Legs.sol +37 -0
- package/contracts/libraries/svgs/Profile/Logo.sol +167 -0
- package/contracts/libraries/svgs/Profile/ProfileSVG.sol +384 -0
- package/contracts/libraries/svgs/Profile/Shoes.sol +37 -0
- package/contracts/libraries/svgs/Profile/SimpleProfileSVG.sol +8 -0
- package/contracts/misc/ImmutableOwnable.sol +30 -0
- package/contracts/misc/LegacyCollectNFT.sol +126 -0
- package/contracts/misc/LensHubInitializable.sol +49 -0
- package/contracts/misc/PermissionlessCreator.sol +353 -0
- package/contracts/misc/ProfileCreationProxy.sol +66 -0
- package/contracts/misc/PublicActProxy.sol +109 -0
- package/contracts/misc/token-uris/FollowTokenURI.sol +47 -0
- package/contracts/misc/token-uris/HandleTokenURI.sol +42 -0
- package/contracts/misc/token-uris/ProfileTokenURI.sol +57 -0
- package/contracts/misc/token-uris/SimpleProfileTokenURI.sol +57 -0
- package/contracts/modules/act/collect/MultirecipientFeeCollectModule.sol +224 -0
- package/contracts/modules/act/collect/SimpleFeeCollectModule.sol +79 -0
- package/contracts/modules/follow/FeeFollowModule.sol +131 -0
- package/contracts/modules/follow/RevertFollowModule.sol +48 -0
- package/contracts/modules/reference/DegreesOfSeparationReferenceModule.sol +314 -0
- package/contracts/modules/reference/FollowerOnlyReferenceModule.sol +96 -0
- package/contracts/modules/reference/TokenGatedReferenceModule.sol +167 -0
- package/contracts/namespaces/LensHandles.sol +326 -0
- package/contracts/namespaces/TokenHandleRegistry.sol +320 -0
- package/contracts/namespaces/constants/Errors.sol +27 -0
- package/contracts/namespaces/constants/Events.sol +63 -0
- package/contracts/namespaces/constants/Typehash.sol +12 -0
- package/contracts/namespaces/constants/Types.sol +21 -0
- package/package.json +1 -1
package/contracts/LensHub.sol
CHANGED
|
@@ -16,7 +16,6 @@ import {LensImplGetters} from './base/LensImplGetters.sol';
|
|
|
16
16
|
import {LensGovernable} from './base/LensGovernable.sol';
|
|
17
17
|
import {LensProfiles} from './base/LensProfiles.sol';
|
|
18
18
|
import {LensHubEventHooks} from './base/LensHubEventHooks.sol';
|
|
19
|
-
import {LensVersion} from './base/LensVersion.sol';
|
|
20
19
|
|
|
21
20
|
// Libraries
|
|
22
21
|
import {ActionLib} from './libraries/ActionLib.sol';
|
|
@@ -49,7 +48,6 @@ contract LensHub is
|
|
|
49
48
|
LensImplGetters,
|
|
50
49
|
LensHubEventHooks,
|
|
51
50
|
LensHubStorage,
|
|
52
|
-
LensVersion,
|
|
53
51
|
ILensProtocol
|
|
54
52
|
{
|
|
55
53
|
modifier onlyProfileOwnerOrDelegatedExecutor(address expectedOwnerOrDelegatedExecutor, uint256 profileId) {
|
|
@@ -129,11 +129,46 @@ abstract contract LensProfiles is LensBaseERC721, ERC2981CollectionRoyalties, IL
|
|
|
129
129
|
LensBaseERC721.supportsInterface(interfaceId) || ERC2981CollectionRoyalties.supportsInterface(interfaceId);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
function transferFromKeepingDelegates(address from, address to, uint256 tokenId) external {
|
|
133
|
+
//solhint-disable-next-line max-line-length
|
|
134
|
+
if (!_isApprovedOrOwner(msg.sender, tokenId)) {
|
|
135
|
+
revert Errors.NotOwnerOrApproved();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!StorageLib.profileCreatorWhitelisted()[msg.sender]) {
|
|
139
|
+
// Delegates can be maintained on transfers only when executed by whitelisted profile creators, which are
|
|
140
|
+
// trusted entities, for the sake of a better onboarding UX.
|
|
141
|
+
revert Errors.NotAllowed();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (ownerOf(tokenId) != from) {
|
|
145
|
+
revert Errors.InvalidOwner();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (to == address(0)) {
|
|
149
|
+
revert Errors.InvalidParameter();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
_beforeTokenTransferWithoutClearingDelegates(from, to, tokenId);
|
|
153
|
+
|
|
154
|
+
// Clear approvals from the previous owner
|
|
155
|
+
_approve(address(0), tokenId);
|
|
156
|
+
|
|
157
|
+
unchecked {
|
|
158
|
+
--StorageLib.balances()[from];
|
|
159
|
+
++StorageLib.balances()[to];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
StorageLib.getTokenData(tokenId).owner = to;
|
|
163
|
+
|
|
164
|
+
emit Transfer(from, to, tokenId);
|
|
165
|
+
}
|
|
166
|
+
|
|
132
167
|
function _hasTokenGuardianEnabled(address wallet) internal view returns (bool) {
|
|
133
168
|
return
|
|
134
169
|
!wallet.isContract() &&
|
|
135
|
-
|
|
136
|
-
|
|
170
|
+
(StorageLib.tokenGuardianDisablingTimestamp()[wallet] == 0 ||
|
|
171
|
+
block.timestamp < StorageLib.tokenGuardianDisablingTimestamp()[wallet]);
|
|
137
172
|
}
|
|
138
173
|
|
|
139
174
|
function _getRoyaltiesInBasisPointsSlot() internal pure override returns (uint256) {
|
|
@@ -159,4 +194,16 @@ abstract contract LensProfiles is LensBaseERC721, ERC2981CollectionRoyalties, IL
|
|
|
159
194
|
}
|
|
160
195
|
super._beforeTokenTransfer(from, to, tokenId);
|
|
161
196
|
}
|
|
162
|
-
|
|
197
|
+
|
|
198
|
+
function _beforeTokenTransferWithoutClearingDelegates(
|
|
199
|
+
address from,
|
|
200
|
+
address to,
|
|
201
|
+
uint256 tokenId
|
|
202
|
+
) internal whenNotPaused {
|
|
203
|
+
if (from != address(0) && _hasTokenGuardianEnabled(from)) {
|
|
204
|
+
// Cannot transfer profile if the guardian is enabled, except at minting time.
|
|
205
|
+
revert Errors.GuardianEnabled();
|
|
206
|
+
}
|
|
207
|
+
super._beforeTokenTransfer(from, to, tokenId);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.15;
|
|
3
|
+
|
|
4
|
+
import {Errors} from '../../libraries/constants/Errors.sol';
|
|
5
|
+
import {StorageLib} from '../../libraries/StorageLib.sol';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title VersionedInitializable
|
|
9
|
+
*
|
|
10
|
+
* @dev Helper contract to implement initializer functions. To use it, replace
|
|
11
|
+
* the constructor with a function that has the `initializer` modifier.
|
|
12
|
+
* WARNING: Unlike constructors, initializer functions must be manually
|
|
13
|
+
* invoked. This applies both to deploying an Initializable contract, as well
|
|
14
|
+
* as extending an Initializable contract via inheritance.
|
|
15
|
+
* WARNING: When used with inheritance, manual care must be taken to not invoke
|
|
16
|
+
* a parent initializer twice, or ensure that all initializers are idempotent,
|
|
17
|
+
* because this is not dealt with automatically as with constructors.
|
|
18
|
+
*
|
|
19
|
+
* This is slightly modified from [Aave's version.](https://github.com/aave/protocol-v2/blob/6a503eb0a897124d8b9d126c915ffdf3e88343a9/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol)
|
|
20
|
+
*
|
|
21
|
+
* @author Lens Protocol, inspired by Aave's implementation, which is in turn inspired by OpenZeppelin's
|
|
22
|
+
* Initializable contract
|
|
23
|
+
*/
|
|
24
|
+
abstract contract VersionedInitializable {
|
|
25
|
+
address private immutable originalImpl;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @dev Modifier to use in the initializer function of a contract.
|
|
29
|
+
*/
|
|
30
|
+
modifier initializer() {
|
|
31
|
+
if (address(this) == originalImpl) {
|
|
32
|
+
revert Errors.CannotInitImplementation();
|
|
33
|
+
}
|
|
34
|
+
if (getRevision() <= StorageLib.getLastInitializedRevision()) {
|
|
35
|
+
revert Errors.Initialized();
|
|
36
|
+
}
|
|
37
|
+
StorageLib.setLastInitializedRevision(getRevision());
|
|
38
|
+
_;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
constructor() {
|
|
42
|
+
originalImpl = address(this);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @dev returns the revision number of the contract
|
|
47
|
+
* Needs to be defined in the inherited class as a constant.
|
|
48
|
+
**/
|
|
49
|
+
function getRevision() internal pure virtual returns (uint256);
|
|
50
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.6.0;
|
|
4
|
+
|
|
5
|
+
import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title ILensHandles
|
|
9
|
+
* @author Lens Protocol
|
|
10
|
+
*
|
|
11
|
+
* @notice This is the interface for the LensHandles contract that is responsible for minting and burning handle NFTs.
|
|
12
|
+
* A handle is composed of a local name and a namespace, separated by a dot.
|
|
13
|
+
* Example: `satoshi.lens` is a handle composed of the local name `satoshi` and the namespace `lens`.
|
|
14
|
+
*/
|
|
15
|
+
interface ILensHandles is IERC721 {
|
|
16
|
+
/**
|
|
17
|
+
* @notice Mints a handle NFT in the given namespace.
|
|
18
|
+
* @custom:permissions Only LensHandles contract's owner or LensHub.
|
|
19
|
+
*
|
|
20
|
+
* @param to The address to mint the handle to.
|
|
21
|
+
* @param localName The local name of the handle (the part before ".lens").
|
|
22
|
+
*
|
|
23
|
+
* @return uint256 The ID of the handle NFT minted.
|
|
24
|
+
*/
|
|
25
|
+
function mintHandle(address to, string calldata localName) external returns (uint256);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @notice Burns a handle NFT.
|
|
29
|
+
* @custom:permissions Owner of Handle NFT.
|
|
30
|
+
*
|
|
31
|
+
* @param tokenId The ID of the handle NFT to burn.
|
|
32
|
+
*/
|
|
33
|
+
function burn(uint256 tokenId) external;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @notice Gets the namespace of the contract. It's 'lens' for the LensHandles contract.
|
|
37
|
+
*
|
|
38
|
+
* @return string The namespace of the contract.
|
|
39
|
+
*/
|
|
40
|
+
function getNamespace() external pure returns (string memory);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @notice Gets the hash of the namespace of the contract. It's keccak256('lens') for the LensHandles contract.
|
|
44
|
+
*
|
|
45
|
+
* @return bytes32 The hash of the namespace of the contract.
|
|
46
|
+
*/
|
|
47
|
+
function getNamespaceHash() external pure returns (bytes32);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @notice Returns whether `tokenId` exists.
|
|
51
|
+
*
|
|
52
|
+
* Tokens start existing when they are minted (`_mint`),
|
|
53
|
+
* and stop existing when they are burned (`_burn`).
|
|
54
|
+
*
|
|
55
|
+
* @return bool Whether the token exists.
|
|
56
|
+
*/
|
|
57
|
+
function exists(uint256 tokenId) external view returns (bool);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @notice Returns the amount of tokens in circulation.
|
|
61
|
+
*
|
|
62
|
+
* @return uint256 The current total supply of tokens.
|
|
63
|
+
*/
|
|
64
|
+
function totalSupply() external view returns (uint256);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @notice Returns the HandleTokenURI contract address.
|
|
68
|
+
*
|
|
69
|
+
* @return address The HandleTokenURI contract address.
|
|
70
|
+
*/
|
|
71
|
+
function getHandleTokenURIContract() external view returns (address);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @notice Sets the HandleTokenURI contract address.
|
|
75
|
+
* @custom:permissions Only LensHandles contract's owner
|
|
76
|
+
*
|
|
77
|
+
* @param handleTokenURIContract The HandleTokenURI contract address to set.
|
|
78
|
+
*/
|
|
79
|
+
function setHandleTokenURIContract(address handleTokenURIContract) external;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @notice DANGER: Triggers disabling the profile protection mechanism for the msg.sender, which will allow
|
|
83
|
+
* transfers or approvals over profiles held by it.
|
|
84
|
+
* Disabling the mechanism will have a timelock before it becomes effective, allowing the owner to re-enable
|
|
85
|
+
* the protection back in case of being under attack.
|
|
86
|
+
* The protection layer only applies to EOA wallets.
|
|
87
|
+
*/
|
|
88
|
+
function DANGER__disableTokenGuardian() external;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @notice Enables back the profile protection mechanism for the msg.sender, preventing profile transfers or
|
|
92
|
+
* approvals (except when revoking them).
|
|
93
|
+
* The protection layer only applies to EOA wallets.
|
|
94
|
+
*/
|
|
95
|
+
function enableTokenGuardian() external;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @notice Returns the timestamp at which the Token Guardian will become effectively disabled.
|
|
99
|
+
*
|
|
100
|
+
* @param wallet The address to check the timestamp for.
|
|
101
|
+
*
|
|
102
|
+
* @return uint256 The timestamp at which the Token Guardian will become effectively disabled.
|
|
103
|
+
* Max 256-bit unsigned integer value if enabled.
|
|
104
|
+
*/
|
|
105
|
+
function getTokenGuardianDisablingTimestamp(address wallet) external view returns (uint256);
|
|
106
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.6.0;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @title ILensHub
|
|
7
|
+
* @author Lens Protocol
|
|
8
|
+
*
|
|
9
|
+
* @notice This is the interface for the LensHub contract, the main entry point for the Lens Protocol.
|
|
10
|
+
* You'll find all the events and external functions, as well as the reasoning behind them here.
|
|
11
|
+
*/
|
|
12
|
+
interface ILensHubInitializable {
|
|
13
|
+
/**
|
|
14
|
+
* @notice Initializes the LensHub, setting the initial governance address, the name and symbol of the profiles
|
|
15
|
+
* in the LensNFTBase contract, and Protocol State (Paused).
|
|
16
|
+
* @dev This is assuming a proxy pattern is implemented.
|
|
17
|
+
* @custom:permissions Callable once.
|
|
18
|
+
*
|
|
19
|
+
* @param name The name of the Profile NFT.
|
|
20
|
+
* @param symbol The symbol of the Profile NFT.
|
|
21
|
+
* @param newGovernance The governance address to set.
|
|
22
|
+
*/
|
|
23
|
+
function initialize(
|
|
24
|
+
string calldata name,
|
|
25
|
+
string calldata symbol,
|
|
26
|
+
address newGovernance
|
|
27
|
+
) external;
|
|
28
|
+
}
|
|
@@ -29,4 +29,9 @@ interface ILensProfiles is ILensERC721 {
|
|
|
29
29
|
* @return uint256 The timestamp at which the Token Guardian will become effectively disabled. Zero if enabled.
|
|
30
30
|
*/
|
|
31
31
|
function getTokenGuardianDisablingTimestamp(address wallet) external view returns (uint256);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @notice allows transferring of profile but keeping the delegate settings
|
|
35
|
+
*/
|
|
36
|
+
function transferFromKeepingDelegates(address from, address to, uint256 tokenId) external;
|
|
32
37
|
}
|
|
@@ -8,7 +8,7 @@ library StorageLib {
|
|
|
8
8
|
// uint256 constant NAME_SLOT = 0;
|
|
9
9
|
// uint256 constant SYMBOL_SLOT = 1;
|
|
10
10
|
uint256 constant TOKEN_DATA_MAPPING_SLOT = 2;
|
|
11
|
-
|
|
11
|
+
uint256 constant BALANCES_SLOT = 3;
|
|
12
12
|
// uint256 constant TOKEN_APPROVAL_MAPPING_SLOT = 4;
|
|
13
13
|
// uint256 constant OPERATOR_APPROVAL_MAPPING_SLOT = 5;
|
|
14
14
|
// Slot 6 is deprecated in Lens V2. In V1 it was used for ERC-721 Enumerable's `ownedTokens`.
|
|
@@ -97,9 +97,9 @@ library StorageLib {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
function tokenGuardianDisablingTimestamp()
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
internal
|
|
101
|
+
pure
|
|
102
|
+
returns (mapping(address => uint256) storage _tokenGuardianDisablingTimestamp)
|
|
103
103
|
{
|
|
104
104
|
assembly {
|
|
105
105
|
_tokenGuardianDisablingTimestamp.slot := TOKEN_GUARDIAN_DISABLING_TIMESTAMP_MAPPING_SLOT
|
|
@@ -114,6 +114,12 @@ library StorageLib {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
function balances() internal pure returns (mapping(address => uint256) storage _balances) {
|
|
118
|
+
assembly {
|
|
119
|
+
_balances.slot := BALANCES_SLOT
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
117
123
|
function blockedStatus(
|
|
118
124
|
uint256 blockerProfileId
|
|
119
125
|
) internal pure returns (mapping(uint256 => bool) storage _blockedStatus) {
|
|
@@ -131,9 +137,9 @@ library StorageLib {
|
|
|
131
137
|
}
|
|
132
138
|
|
|
133
139
|
function profileIdByHandleHash()
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
internal
|
|
141
|
+
pure
|
|
142
|
+
returns (mapping(bytes32 => uint256) storage _profileIdByHandleHash)
|
|
137
143
|
{
|
|
138
144
|
assembly {
|
|
139
145
|
_profileIdByHandleHash.slot := PROFILE_ID_BY_HANDLE_HASH_MAPPING_SLOT
|
|
@@ -141,9 +147,9 @@ library StorageLib {
|
|
|
141
147
|
}
|
|
142
148
|
|
|
143
149
|
function profileCreatorWhitelisted()
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
internal
|
|
151
|
+
pure
|
|
152
|
+
returns (mapping(address => bool) storage _profileCreatorWhitelisted)
|
|
147
153
|
{
|
|
148
154
|
assembly {
|
|
149
155
|
_profileCreatorWhitelisted.slot := PROFILE_CREATOR_WHITELIST_MAPPING_SLOT
|
|
@@ -151,9 +157,9 @@ library StorageLib {
|
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
function migrationAdminWhitelisted()
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
160
|
+
internal
|
|
161
|
+
pure
|
|
162
|
+
returns (mapping(address => bool) storage _migrationAdminWhitelisted)
|
|
157
163
|
{
|
|
158
164
|
assembly {
|
|
159
165
|
_migrationAdminWhitelisted.slot := MIGRATION_ADMINS_WHITELISTED_MAPPING_SLOT
|
|
@@ -161,9 +167,9 @@ library StorageLib {
|
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
function legacyCollectFollowValidationHelper()
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
170
|
+
internal
|
|
171
|
+
pure
|
|
172
|
+
returns (mapping(address => uint256) storage _legacyCollectFollowValidationHelper)
|
|
167
173
|
{
|
|
168
174
|
assembly {
|
|
169
175
|
_legacyCollectFollowValidationHelper.slot := LEGACY_COLLECT_FOLLOW_VALIDATION_HELPER_MAPPING_SLOT
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
library FollowSVG {
|
|
5
|
+
uint8 private constant MAX_GOLD_TOKEN_ID = 10;
|
|
6
|
+
|
|
7
|
+
function getFollowSVG(uint256 followTokenId) public pure returns (string memory) {
|
|
8
|
+
if (followTokenId <= MAX_GOLD_TOKEN_ID) {
|
|
9
|
+
return
|
|
10
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="275" height="275" fill="none"><g><path fill="url(#b)" d="M0 0h275v275H0z"/><path fill="url(#c)" stroke="#B96326" stroke-linecap="square" stroke-linejoin="round" stroke-width="4" d="M168.9 116.8v0a1 1 0 0 1-1.8-.8v0-2.7c-1.1-37.7-58.1-37.7-59.1 0v2.7a1 1 0 0 1-1.9.8v0l-2-2C76.8 89 36.5 129.3 62.5 156.6l2 2a113.3 113.3 0 0 0 73.1 31.3s0 0 0 0 41.8 0 73.2-31.3a81 81 0 0 0 2-2c26-27.4-14.4-67.6-41.9-41.6l-2 1.9Z"/><g><path fill="#B96326" d="M127.3 152.2a1 1 0 0 0-1-1.3H125a1 1 0 0 1-1-1v-1.8c0-.6.4-1 1-1h2.8a1 1 0 0 0 1-.8l.7-3.1a1 1 0 0 0-1-1.2h-1.7a1 1 0 0 1-1-1v-2c0-.5.4-1 1-1h3.2a1 1 0 0 0 1-.7l1-4.6a1 1 0 0 1 1-.8h3a1 1 0 0 1 1 1.2l-.9 3.7a1 1 0 0 0 1 1.2h3a1 1 0 0 0 1-.7l1.2-4.6a1 1 0 0 1 1-.8h3a1 1 0 0 1 1 1.2l-1 3.7a1 1 0 0 0 1 1.2h1.8a1 1 0 0 1 1 1.3l-.5 1.8a1 1 0 0 1-1 .8H146a1 1 0 0 0-1 .7l-.7 3.1a1 1 0 0 0 1 1.3h1.8a1 1 0 0 1 1 1.2l-.5 1.9a1 1 0 0 1-1 .7h-2.8a1 1 0 0 0-1 .8l-1.3 5.5a1 1 0 0 1-1 .8h-3a1 1 0 0 1-1-1.3l1.2-4.5a1 1 0 0 0-1-1.3h-3.1a1 1 0 0 0-1 .8l-1.3 5.5a1 1 0 0 1-1 .8h-3a1 1 0 0 1-1-1.3l1.1-4.5Zm10.8-5a1 1 0 0 0 1-.8l.7-3.3a1 1 0 0 0-1-1.2h-3.2a1 1 0 0 0-1 .7l-.8 3.3a1 1 0 0 0 1 1.3h3.3Z"/></g></g><defs><radialGradient id="b" cx="0" cy="0" r="1" gradientTransform="matrix(275 -275 362 362 0 275)" gradientUnits="userSpaceOnUse"><stop stop-color="#FFE7A5"/><stop offset="1" stop-color="#FFF2CE"/></radialGradient><radialGradient id="c" cx="0" cy="0" r="1" gradientTransform="matrix(0 83 -132 0 137.5 107.1)" gradientUnits="userSpaceOnUse"><stop stop-color="#FFDF85"/><stop offset=".9" stop-color="#F8C944"/></radialGradient></defs></svg>';
|
|
11
|
+
} else {
|
|
12
|
+
return
|
|
13
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="275" height="275" fill="none"><g><path fill="url(#green)" d="M0 0h275v275H0z"/><path fill="#A0D170" stroke="#000" stroke-linecap="square" stroke-linejoin="round" stroke-width="4" d="M168.9 116.8v0a1 1 0 0 1-1.8-.8v0-2.7c-1.1-37.7-58.1-37.7-59.1 0v2.7a1 1 0 0 1-1.9.8v0l-2-2C76.8 89 36.5 129.3 62.5 156.6l2 2a113.3 113.3 0 0 0 73.1 31.3s41.8 0 73.2-31.3a81 81 0 0 0 2-2c26-27.4-14.4-67.6-41.9-41.6l-2 1.9Z"/><g><path fill="#000" d="M127.3 152.2a1 1 0 0 0-1-1.3H125a1 1 0 0 1-1-1v-1.8c0-.6.4-1 1-1h2.8a1 1 0 0 0 1-.8l.7-3.1a1 1 0 0 0-1-1.2h-1.7a1 1 0 0 1-1-1v-2c0-.5.4-1 1-1h3.2a1 1 0 0 0 1-.7l1-4.6a1 1 0 0 1 1-.8h3a1 1 0 0 1 1 1.2l-.9 3.7a1 1 0 0 0 1 1.2h3a1 1 0 0 0 1-.7l1.2-4.6a1 1 0 0 1 1-.8h3a1 1 0 0 1 1 1.2l-1 3.7a1 1 0 0 0 1 1.2h1.8a1 1 0 0 1 1 1.3l-.5 1.8a1 1 0 0 1-1 .8H146a1 1 0 0 0-1 .7l-.7 3.1a1 1 0 0 0 1 1.3h1.8a1 1 0 0 1 1 1.2l-.5 1.9a1 1 0 0 1-1 .7h-2.8a1 1 0 0 0-1 .8l-1.3 5.5a1 1 0 0 1-1 .8h-3a1 1 0 0 1-1-1.3l1.2-4.5a1 1 0 0 0-1-1.3h-3.1a1 1 0 0 0-1 .8l-1.3 5.5a1 1 0 0 1-1 .8h-3a1 1 0 0 1-1-1.3l1.1-4.5Zm10.8-5a1 1 0 0 0 1-.8l.7-3.3a1 1 0 0 0-1-1.2h-3.2a1 1 0 0 0-1 .7l-.8 3.3a1 1 0 0 0 1 1.3h3.3Z"/></g></g><defs><radialGradient id="green" cx="0" cy="0" r="1" gradientTransform="matrix(275 -275 362 362 0 275)" gradientUnits="userSpaceOnUse"><stop stop-color="#DFFFBF"/><stop offset="1" stop-color="#EFD"/></radialGradient></defs></svg>';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
library GintoNordFontSVG {
|
|
5
|
+
function getFontStyle() external pure returns (string memory) {
|
|
6
|
+
return
|
|
7
|
+
'<style>@font-face{font-family:"Ginto Nord Medium";src:url(data:application/font-woff;charset=utf-8;base64,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) format("woff"); font-weight:normal;font-style:normal;}</style>';
|
|
8
|
+
}
|
|
9
|
+
}
|