@totems/evm 1.0.0
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/LICENSE +261 -0
- package/README.md +28 -0
- package/contracts/Errors.sol +29 -0
- package/contracts/ModMarket.sol +467 -0
- package/contracts/ReentrancyGuard.sol +17 -0
- package/contracts/Shared.sol +45 -0
- package/contracts/Totems.sol +835 -0
- package/interfaces/IMarket.sol +153 -0
- package/interfaces/IRelayFactory.sol +13 -0
- package/interfaces/ITotemTypes.sol +200 -0
- package/interfaces/ITotems.sol +178 -0
- package/mods/TotemMod.sol +136 -0
- package/mods/TotemsLibrary.sol +161 -0
- package/package.json +35 -0
- package/test/helpers.ts +466 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// AUTO-GENERATED - DO NOT EDIT
|
|
3
|
+
// Generated from ModMarket
|
|
4
|
+
pragma solidity ^0.8.28;
|
|
5
|
+
|
|
6
|
+
import "../library/ITotemTypes.sol";
|
|
7
|
+
|
|
8
|
+
interface IMarket {
|
|
9
|
+
// ==================== FUNCTIONS ====================
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @notice Set your referrer fee for mod publishing
|
|
13
|
+
* @dev Referrers earn fees when users publish mods using their address. Fee must be at least minBaseFee. The referrer receives (fee - burnedFee).
|
|
14
|
+
* @param fee The fee amount in wei (must be >= minBaseFee)
|
|
15
|
+
*/
|
|
16
|
+
function setReferrerFee(uint256 fee) external;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @notice Get the fee for creating a totem or publishing a mod
|
|
20
|
+
* @param referrer The referrer address (or zero address for no referrer)
|
|
21
|
+
* @return The total fee required (at least minBaseFee)
|
|
22
|
+
*/
|
|
23
|
+
function getFee(address referrer) external view returns (uint256);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @notice Publish a mod to the marketplace
|
|
27
|
+
* @dev Only the mod's seller (returned by mod.getSeller()) can publish. Validates: contract exists, not already published, name 3-100 chars, summary 10-150 chars, image URL present, valid hooks with no duplicates. Excess payment is refunded to sender.
|
|
28
|
+
* @param mod Deployed mod contract address
|
|
29
|
+
* @param hooks Array of supported hook identifiers (Created, Mint, Burn, Transfer, TransferOwnership)
|
|
30
|
+
* @param price Price in wei to use this mod (paid when totem creator adds the mod)
|
|
31
|
+
* @param details Mod display details (name, summary, image, website, etc.)
|
|
32
|
+
* @param requiredActions Setup actions users must call after totem creation
|
|
33
|
+
* @param referrer Optional referrer address (receives fee minus burned amount)
|
|
34
|
+
*/
|
|
35
|
+
function publish(address mod, ITotemTypes.Hook[] calldata hooks, uint256 price, ITotemTypes.ModDetails calldata details, ITotemTypes.ModRequiredAction[] calldata requiredActions, address payable referrer) external payable;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @notice Update mod price and details
|
|
39
|
+
* @param mod Mod contract address
|
|
40
|
+
* @param newPrice New price in wei
|
|
41
|
+
* @param details New mod details
|
|
42
|
+
*/
|
|
43
|
+
function update(address mod, uint256 newPrice, ITotemTypes.ModDetails calldata details) external;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @notice Update required actions for a mod
|
|
47
|
+
* @param mod Mod contract address
|
|
48
|
+
* @param requiredActions New required setup actions
|
|
49
|
+
*/
|
|
50
|
+
function updateRequiredActions(address mod, ITotemTypes.ModRequiredAction[] calldata requiredActions) external;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @notice Get a single mod by address
|
|
54
|
+
* @param mod Mod contract address
|
|
55
|
+
* @return Mod struct
|
|
56
|
+
*/
|
|
57
|
+
function getMod(address mod) external view returns (ITotemTypes.Mod memory);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @notice Get the usage price for a single mod
|
|
61
|
+
* @param mod Mod contract address
|
|
62
|
+
* @return The price in wei to use this mod
|
|
63
|
+
*/
|
|
64
|
+
function getModFee(address mod) external view returns (uint256);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @notice Get required actions for a mod (setup actions called after totem creation)
|
|
68
|
+
* @param mod Mod contract address
|
|
69
|
+
* @return Array of required actions
|
|
70
|
+
*/
|
|
71
|
+
function getModRequiredActions(address mod) external view returns (ITotemTypes.ModRequiredAction[] memory);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @notice Get multiple mods by their addresses
|
|
75
|
+
* @param contracts Array of mod contract addresses
|
|
76
|
+
* @return Array of Mod structs
|
|
77
|
+
*/
|
|
78
|
+
function getMods(address[] calldata contracts) external view returns (ITotemTypes.Mod[] memory);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @notice Get the total usage price for multiple mods
|
|
82
|
+
* @dev Useful for calculating total cost when creating a totem with multiple mods
|
|
83
|
+
* @param contracts Array of mod contract addresses
|
|
84
|
+
* @return Total price in wei for all mods combined
|
|
85
|
+
*/
|
|
86
|
+
function getModsFee(address[] calldata contracts) external view returns (uint256);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @notice Get the hooks supported by a mod
|
|
90
|
+
* @dev Hooks determine when the mod is called (Created, Mint, Burn, Transfer, TransferOwnership)
|
|
91
|
+
* @param mod Mod contract address
|
|
92
|
+
* @return Array of Hook enum values
|
|
93
|
+
*/
|
|
94
|
+
function getSupportedHooks(address mod) external view returns (ITotemTypes.Hook[] memory);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @notice Check if a mod requires unlimited minting capability
|
|
98
|
+
* @dev Mods with needsUnlimited=true can mint tokens without supply cap restrictions. Returns false for unpublished mods.
|
|
99
|
+
* @param mod Mod contract address
|
|
100
|
+
* @return True if the mod needs unlimited minting capability
|
|
101
|
+
*/
|
|
102
|
+
function isUnlimitedMinter(address mod) external view returns (bool);
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @notice List mods with pagination
|
|
106
|
+
* @param perPage Number of results per page
|
|
107
|
+
* @param cursor Index to start from (for pagination)
|
|
108
|
+
* @return mods_ Array of Mod structs
|
|
109
|
+
* @return nextCursor Next cursor value
|
|
110
|
+
* @return hasMore Whether more results exist
|
|
111
|
+
*/
|
|
112
|
+
function listMods(uint32 perPage, uint256 cursor) external view returns (ITotemTypes.Mod[] memory mods_, uint256 nextCursor, bool hasMore);
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @notice Ordered list of all published mod addresses (for pagination)
|
|
116
|
+
*/
|
|
117
|
+
function modList(uint256) external view returns (address);
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @notice Fee amount that is always burned (set once in constructor, never changed)
|
|
121
|
+
*/
|
|
122
|
+
function burnedFee() external view returns (uint256);
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @notice Minimum base fee for mod publishing (set once in constructor, never changed)
|
|
126
|
+
*/
|
|
127
|
+
function minBaseFee() external view returns (uint256);
|
|
128
|
+
|
|
129
|
+
// ==================== EVENTS ====================
|
|
130
|
+
|
|
131
|
+
event ModPublished(address indexed mod);
|
|
132
|
+
event ModUpdated(address indexed mod);
|
|
133
|
+
|
|
134
|
+
// ==================== ERRORS ====================
|
|
135
|
+
|
|
136
|
+
error DuplicateHook(ITotemTypes.Hook hook);
|
|
137
|
+
error EmptyModImage();
|
|
138
|
+
error EmptyModName();
|
|
139
|
+
error EmptyModSummary();
|
|
140
|
+
error InsufficientFee(uint256 required, uint256 provided);
|
|
141
|
+
error InvalidContractAddress();
|
|
142
|
+
error InvalidHook(ITotemTypes.Hook hook);
|
|
143
|
+
error ModAlreadyPublished(address mod);
|
|
144
|
+
error ModNameTooLong(uint256 length);
|
|
145
|
+
error ModNameTooShort(uint256 length);
|
|
146
|
+
error ModNotFound(address mod);
|
|
147
|
+
error ModSummaryTooLong(uint256 length);
|
|
148
|
+
error ModSummaryTooShort(uint256 length);
|
|
149
|
+
error NoHooksSpecified();
|
|
150
|
+
error ReferrerFeeTooLow(uint256 minFee);
|
|
151
|
+
error TransferFailed();
|
|
152
|
+
error Unauthorized();
|
|
153
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
interface IRelayFactory {
|
|
5
|
+
event RelayCreated(
|
|
6
|
+
string indexed ticker,
|
|
7
|
+
address indexed relayContract
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
function createRelay(
|
|
11
|
+
string calldata ticker
|
|
12
|
+
) external returns (address);
|
|
13
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title ITotemTypes
|
|
6
|
+
* @notice Interface and types for the Totems ecosystem
|
|
7
|
+
* @dev This library provides core types and structures for Totems and Mods
|
|
8
|
+
*/
|
|
9
|
+
interface ITotemTypes {
|
|
10
|
+
|
|
11
|
+
struct RelayInfo {
|
|
12
|
+
address relay;
|
|
13
|
+
string standard;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// @notice Valid hook identifiers
|
|
17
|
+
enum Hook {
|
|
18
|
+
Created,
|
|
19
|
+
Mint,
|
|
20
|
+
Burn,
|
|
21
|
+
Transfer,
|
|
22
|
+
TransferOwnership
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @notice Display details for a mod
|
|
27
|
+
* @param name Mod name
|
|
28
|
+
* @param summary Short description
|
|
29
|
+
* @param markdown Detailed markdown description
|
|
30
|
+
* @param image Image URL or IPFS hash
|
|
31
|
+
* @param website Website URL
|
|
32
|
+
* @param websiteTickerPath Path template for token-specific pages
|
|
33
|
+
* @param isMinter Whether this mod is a token minter
|
|
34
|
+
*/
|
|
35
|
+
struct ModDetails {
|
|
36
|
+
string name;
|
|
37
|
+
string summary;
|
|
38
|
+
string markdown;
|
|
39
|
+
string image;
|
|
40
|
+
string website;
|
|
41
|
+
string websiteTickerPath;
|
|
42
|
+
bool isMinter;
|
|
43
|
+
bool needsUnlimited;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Input mode for mod action fields
|
|
47
|
+
enum ModActionFieldInputMode {
|
|
48
|
+
// Request input from the user
|
|
49
|
+
DYNAMIC,
|
|
50
|
+
// Predefined static value
|
|
51
|
+
STATIC,
|
|
52
|
+
// Auto-fill with the current totem ticker
|
|
53
|
+
TOTEM
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
struct ModActionField {
|
|
57
|
+
// ex: "totem, mintPerMine"
|
|
58
|
+
string name;
|
|
59
|
+
ModActionFieldInputMode mode;
|
|
60
|
+
// only used for STATIC mode
|
|
61
|
+
string value;
|
|
62
|
+
// Human-readable description of this field for UIs (optional)
|
|
63
|
+
string description;
|
|
64
|
+
// Minimum value constraint for numeric inputs (0 = no minimum)
|
|
65
|
+
uint256 min;
|
|
66
|
+
// Maximum value constraint for numeric inputs (0 = no maximum)
|
|
67
|
+
uint256 max;
|
|
68
|
+
// Is this field expecting to receive totem amounts?
|
|
69
|
+
bool isTotems;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
struct ModRequiredAction {
|
|
73
|
+
// ex: "setup(string totem, uint256 mintPerMine)"
|
|
74
|
+
// (only the ~canonical function signature, no "function" keyword, modifiers, or mutability)
|
|
75
|
+
// Also no return types!
|
|
76
|
+
string signature;
|
|
77
|
+
ModActionField[] inputFields;
|
|
78
|
+
// Is there a msg.value required to perform this action?
|
|
79
|
+
// If > 0 this will make the function payable
|
|
80
|
+
uint256 cost;
|
|
81
|
+
// Explain to users why this action is required for UIs
|
|
82
|
+
string reason;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @notice On-chain Mod entry in the marketplace
|
|
87
|
+
* @param mod The deployed mod contract address
|
|
88
|
+
* @param seller Address that receives payments for this mod
|
|
89
|
+
* @param price Price in wei to use this mod
|
|
90
|
+
* @param details Display details
|
|
91
|
+
* @param hooks Array of supported hook names
|
|
92
|
+
* @param publishedAt Timestamp of publication
|
|
93
|
+
* @param updatedAt Timestamp of last update
|
|
94
|
+
*/
|
|
95
|
+
struct Mod {
|
|
96
|
+
address mod;
|
|
97
|
+
address payable seller;
|
|
98
|
+
uint64 publishedAt;
|
|
99
|
+
uint64 updatedAt;
|
|
100
|
+
uint256 price;
|
|
101
|
+
Hook[] hooks;
|
|
102
|
+
ModDetails details;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @notice Allocation of tokens at creation time
|
|
107
|
+
* @param label Human-readable label
|
|
108
|
+
* @param recipient Address to receive tokens
|
|
109
|
+
* @param amount Amount of tokens
|
|
110
|
+
* @param isMinter Whether this recipient is a minter mod
|
|
111
|
+
*/
|
|
112
|
+
struct MintAllocation {
|
|
113
|
+
address payable recipient;
|
|
114
|
+
bool isMinter;
|
|
115
|
+
uint256 amount;
|
|
116
|
+
string label;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @notice Display details for a totem
|
|
121
|
+
* @param name Totem name
|
|
122
|
+
* @param description Detailed description
|
|
123
|
+
* @param image Image URL or IPFS hash
|
|
124
|
+
* @param website Website URL
|
|
125
|
+
* @param seed Generative seed for totem properties
|
|
126
|
+
*/
|
|
127
|
+
struct TotemDetails {
|
|
128
|
+
bytes32 seed;
|
|
129
|
+
uint8 decimals;
|
|
130
|
+
string ticker;
|
|
131
|
+
string name;
|
|
132
|
+
string description;
|
|
133
|
+
string image;
|
|
134
|
+
string website;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @notice Mods assigned to each hook type
|
|
139
|
+
* @param transfer Mods for transfer hook
|
|
140
|
+
* @param mint Mods for mint hook
|
|
141
|
+
* @param burn Mods for burn hook
|
|
142
|
+
* @param created Mods for created hook
|
|
143
|
+
* @param transferOwnership Mods for transfer ownership hook
|
|
144
|
+
*/
|
|
145
|
+
struct TotemMods {
|
|
146
|
+
address[] transfer;
|
|
147
|
+
address[] mint;
|
|
148
|
+
address[] burn;
|
|
149
|
+
address[] created;
|
|
150
|
+
address[] transferOwnership;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @notice Complete totem information
|
|
155
|
+
* @param creator Address that created the totem
|
|
156
|
+
* @param supply Current circulating supply
|
|
157
|
+
* @param maxSupply Maximum possible supply
|
|
158
|
+
* @param allocations Initial token allocations
|
|
159
|
+
* @param mods Mods for each hook type
|
|
160
|
+
* @param details Display information
|
|
161
|
+
* @param createdAt Creation timestamp
|
|
162
|
+
* @param updatedAt Last update timestamp
|
|
163
|
+
*/
|
|
164
|
+
struct Totem {
|
|
165
|
+
address payable creator;
|
|
166
|
+
uint64 createdAt;
|
|
167
|
+
uint64 updatedAt;
|
|
168
|
+
bool isActive;
|
|
169
|
+
uint256 supply;
|
|
170
|
+
uint256 maxSupply;
|
|
171
|
+
MintAllocation[] allocations;
|
|
172
|
+
TotemMods mods;
|
|
173
|
+
TotemDetails details;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @notice Statistics for a totem
|
|
178
|
+
* @param ticker Token symbol
|
|
179
|
+
* @param mints Total number of mint operations
|
|
180
|
+
* @param burns Total number of burn operations
|
|
181
|
+
* @param transfers Total number of transfers
|
|
182
|
+
* @param holders Total number of unique holders
|
|
183
|
+
*/
|
|
184
|
+
struct TotemStats {
|
|
185
|
+
uint64 mints;
|
|
186
|
+
uint64 burns;
|
|
187
|
+
uint64 transfers;
|
|
188
|
+
uint64 holders;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @notice Fee disbursement information
|
|
193
|
+
* @param recipient Address to receive funds
|
|
194
|
+
* @param amount Amount in wei
|
|
195
|
+
*/
|
|
196
|
+
struct FeeDisbursement {
|
|
197
|
+
address payable recipient;
|
|
198
|
+
uint256 amount;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// AUTO-GENERATED - DO NOT EDIT
|
|
3
|
+
// Generated from Totems
|
|
4
|
+
pragma solidity ^0.8.28;
|
|
5
|
+
|
|
6
|
+
import "../library/ITotemTypes.sol";
|
|
7
|
+
|
|
8
|
+
interface ITotems {
|
|
9
|
+
// ==================== FUNCTIONS ====================
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @notice Creates a new totem with the specified details, allocations, and mods
|
|
13
|
+
*/
|
|
14
|
+
function create(ITotemTypes.TotemDetails calldata details, ITotemTypes.MintAllocation[] calldata allocations, ITotemTypes.TotemMods calldata mods, address payable referrer) external payable;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @notice Burns tokens from a totem, permanently reducing supply
|
|
18
|
+
*/
|
|
19
|
+
function burn(string calldata ticker, address owner, uint256 amount, string calldata memo) external;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @notice Mints tokens for a totem using an authorized minter mod
|
|
23
|
+
*/
|
|
24
|
+
function mint(address mod, address minter, string calldata ticker, uint256 amount, string calldata memo) external payable;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @notice Transfers tokens between addresses
|
|
28
|
+
*/
|
|
29
|
+
function transfer(string calldata ticker, address from, address to, uint256 amount, string calldata memo) external;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @notice Transfers ownership of a totem to a new address
|
|
33
|
+
*/
|
|
34
|
+
function transferOwnership(string calldata ticker, address payable newOwner) external;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @notice Authorizes an existing relay address for a totem
|
|
38
|
+
*/
|
|
39
|
+
function addRelay(string calldata ticker, address relay, string calldata standard) external;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @notice Creates a new relay for a totem using a relay factory
|
|
43
|
+
*/
|
|
44
|
+
function createRelay(string calldata ticker, address relayFactory, string calldata standard) external returns (address relay);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @notice Revokes authorization for a relay from a totem
|
|
48
|
+
*/
|
|
49
|
+
function removeRelay(string calldata ticker, address relay) external;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @notice Gets the relay address for a specific standard on a totem
|
|
53
|
+
*/
|
|
54
|
+
function getRelayOfStandard(string calldata ticker, string calldata standard) external view returns (address);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @notice Gets all authorized relays for a totem
|
|
58
|
+
*/
|
|
59
|
+
function getRelays(string calldata ticker) external view returns (ITotemTypes.RelayInfo[] memory);
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @notice Grants a mod license for a totem, callable only by the proxy mod
|
|
63
|
+
*/
|
|
64
|
+
function setLicenseFromProxy(bytes32 tickerBytes, address mod) external;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @notice Checks if a mod is licensed for a specific totem
|
|
68
|
+
*/
|
|
69
|
+
function isLicensed(string calldata ticker, address mod) external view returns (bool);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @notice Sets the referrer fee for the caller
|
|
73
|
+
*/
|
|
74
|
+
function setReferrerFee(uint256 fee) external;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @notice Gets the fee for creating a totem
|
|
78
|
+
*/
|
|
79
|
+
function getFee(address referrer) external view returns (uint256);
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @notice Retrieves a totem by its ticker symbol
|
|
83
|
+
*/
|
|
84
|
+
function getTotem(string calldata ticker) external view returns (ITotemTypes.Totem memory);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @notice Retrieves multiple totems by their ticker symbols
|
|
88
|
+
*/
|
|
89
|
+
function getTotems(string[] calldata tickers) external view returns (ITotemTypes.Totem[] memory);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @notice Lists totems with pagination support
|
|
93
|
+
*/
|
|
94
|
+
function listTotems(uint32 perPage, uint256 cursor) external view returns (ITotemTypes.Totem[] memory, uint256, bool);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @notice Gets the token balance for an account on a specific totem
|
|
98
|
+
*/
|
|
99
|
+
function getBalance(string calldata ticker, address account) external view returns (uint256);
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @notice Gets the statistics for a totem
|
|
103
|
+
*/
|
|
104
|
+
function getStats(string calldata ticker) external view returns (ITotemTypes.TotemStats memory);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @notice Gets the proxy mod address
|
|
108
|
+
*/
|
|
109
|
+
function getProxyMod() external view returns (address);
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @notice Converts a ticker string to its normalized bytes32 representation
|
|
113
|
+
*/
|
|
114
|
+
function tickerToBytes(string calldata ticker) external pure returns (bytes32);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @notice Fee amount that is always burned (set once in constructor, never changed)
|
|
118
|
+
*/
|
|
119
|
+
function burnedFee() external view returns (uint256);
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @notice Address of the mod market contract
|
|
123
|
+
*/
|
|
124
|
+
function marketContract() external view returns (address);
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @notice Minimum base fee for totem creation (set once in constructor, never changed)
|
|
128
|
+
*/
|
|
129
|
+
function minBaseFee() external view returns (uint256);
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @notice Address of the proxy mod for license delegation
|
|
133
|
+
*/
|
|
134
|
+
function proxyMod() external view returns (address);
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @notice Array of all totem ticker bytes for enumeration
|
|
138
|
+
*/
|
|
139
|
+
function totemList(uint256) external view returns (bytes32);
|
|
140
|
+
|
|
141
|
+
// ==================== EVENTS ====================
|
|
142
|
+
|
|
143
|
+
event RelayAuthorized(string ticker, address indexed relay);
|
|
144
|
+
event RelayRevoked(string ticker, address indexed relay);
|
|
145
|
+
event TotemBurned(string ticker, address indexed owner, uint256 amount);
|
|
146
|
+
event TotemCreated(string ticker, address indexed creator);
|
|
147
|
+
event TotemMinted(string ticker, address indexed minter, address mod, uint256 minted, uint256 payment);
|
|
148
|
+
event TotemOwnershipTransferred(string ticker, address indexed previousOwner, address indexed newOwner);
|
|
149
|
+
event TotemTransferred(string ticker, address indexed from, address indexed to, uint256 amount);
|
|
150
|
+
|
|
151
|
+
// ==================== ERRORS ====================
|
|
152
|
+
|
|
153
|
+
error CannotTransferToUnlimitedMinter();
|
|
154
|
+
error CantSetLicense();
|
|
155
|
+
error DescriptionTooLong(uint256 length);
|
|
156
|
+
error EmptyImage();
|
|
157
|
+
error InsufficientBalance(uint256 required, uint256 available);
|
|
158
|
+
error InsufficientFee(uint256 required, uint256 provided);
|
|
159
|
+
error InvalidAllocation(string message);
|
|
160
|
+
error InvalidCursor();
|
|
161
|
+
error InvalidSeed();
|
|
162
|
+
error InvalidTickerChar(uint8 char);
|
|
163
|
+
error InvalidTickerLength(uint256 length);
|
|
164
|
+
error ModDoesntSupportHook(address mod, ITotemTypes.Hook hook);
|
|
165
|
+
error ModMustSupportUnlimitedMinting(address mod);
|
|
166
|
+
error ModNotMinter(address mod);
|
|
167
|
+
error NameTooLong(uint256 length);
|
|
168
|
+
error NameTooShort(uint256 length);
|
|
169
|
+
error ReferrerFeeTooLow(uint256 minFee);
|
|
170
|
+
error TooManyAllocations();
|
|
171
|
+
error TooManyMods();
|
|
172
|
+
error TotemAlreadyExists(string ticker);
|
|
173
|
+
error TotemNotActive();
|
|
174
|
+
error TotemNotFound(string ticker);
|
|
175
|
+
error TransferFailed();
|
|
176
|
+
error Unauthorized();
|
|
177
|
+
error ZeroSupply();
|
|
178
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import "../library/ITotemTypes.sol";
|
|
5
|
+
import {TotemsLibrary} from "../library/TotemsLibrary.sol";
|
|
6
|
+
|
|
7
|
+
interface ITotemsProxyModGetter {
|
|
8
|
+
function getProxyMod() external view returns (address);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface IMod {
|
|
12
|
+
function getSeller() external view returns (address payable);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface IModTransfer {
|
|
16
|
+
function onTransfer(
|
|
17
|
+
string calldata ticker,
|
|
18
|
+
address from,
|
|
19
|
+
address to,
|
|
20
|
+
uint256 amount,
|
|
21
|
+
string calldata memo
|
|
22
|
+
) external;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface IModMint {
|
|
26
|
+
function onMint(
|
|
27
|
+
string calldata ticker,
|
|
28
|
+
address minter,
|
|
29
|
+
uint256 amount,
|
|
30
|
+
uint256 payment,
|
|
31
|
+
string calldata memo
|
|
32
|
+
) external;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface IModMinter {
|
|
36
|
+
function mint(
|
|
37
|
+
string calldata ticker,
|
|
38
|
+
address minter,
|
|
39
|
+
uint256 amount,
|
|
40
|
+
string calldata memo
|
|
41
|
+
) external payable;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface IModBurn {
|
|
45
|
+
function onBurn(
|
|
46
|
+
string calldata ticker,
|
|
47
|
+
address owner,
|
|
48
|
+
uint256 amount,
|
|
49
|
+
string calldata memo
|
|
50
|
+
) external;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface IModCreated {
|
|
54
|
+
function onCreated(
|
|
55
|
+
string calldata ticker,
|
|
56
|
+
address creator
|
|
57
|
+
) external;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface IModTransferOwnership {
|
|
61
|
+
function onTransferOwnership(
|
|
62
|
+
string calldata ticker,
|
|
63
|
+
address previousOwner,
|
|
64
|
+
address newOwner
|
|
65
|
+
) external;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @title TotemMod
|
|
70
|
+
* @notice Base contract for building mods
|
|
71
|
+
*/
|
|
72
|
+
abstract contract TotemMod {
|
|
73
|
+
|
|
74
|
+
address payable private seller;
|
|
75
|
+
function getSeller() external view returns (address payable) {
|
|
76
|
+
return seller != address(0) ? payable(address(seller)) : payable(address(this));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function isSetupFor(string calldata ticker) virtual external view returns (bool);
|
|
80
|
+
|
|
81
|
+
error InvalidModEventOrigin();
|
|
82
|
+
error NotLicensed();
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
/// @notice Address of the Totems contract
|
|
87
|
+
address public immutable totemsContract;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @notice Constructor
|
|
91
|
+
* @param _totemsContract Totems contract address
|
|
92
|
+
* @param _seller The seller that will publish this mod (gets paid)
|
|
93
|
+
*/
|
|
94
|
+
constructor(address _totemsContract, address payable _seller) {
|
|
95
|
+
totemsContract = _totemsContract;
|
|
96
|
+
seller = _seller;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @notice Ensure caller is the Totems contract
|
|
101
|
+
*/
|
|
102
|
+
modifier onlyTotems() {
|
|
103
|
+
// sender must be either the totems contract or the proxy mod
|
|
104
|
+
if(msg.sender != totemsContract){
|
|
105
|
+
if(msg.sender != ITotemsProxyModGetter(totemsContract).getProxyMod()){
|
|
106
|
+
revert InvalidModEventOrigin();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
_;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @notice Ensure the mod is licensed for the given ticker
|
|
114
|
+
*/
|
|
115
|
+
modifier onlyLicensed(string calldata ticker) {
|
|
116
|
+
if (!TotemsLibrary.hasLicense(totemsContract, ticker, address(this))) {
|
|
117
|
+
revert NotLicensed();
|
|
118
|
+
}
|
|
119
|
+
_;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
modifier onlyCreator(string calldata ticker) {
|
|
123
|
+
address creator = TotemsLibrary.getCreator(totemsContract, ticker);
|
|
124
|
+
if (msg.sender != creator) {
|
|
125
|
+
revert("Only totem creator can call this");
|
|
126
|
+
}
|
|
127
|
+
_;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
modifier onlySetup(string calldata ticker) {
|
|
131
|
+
if (!this.isSetupFor(ticker)) {
|
|
132
|
+
revert("Mod is not setup for this totem");
|
|
133
|
+
}
|
|
134
|
+
_;
|
|
135
|
+
}
|
|
136
|
+
}
|