forked from storyprotocol/protocol-periphery
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Implementation to Tokenizer Module and OwnableERC20 (#144)
* feat: tokenizer module * fix: inherit IERC165 & additional checks in tokenizer * fix: use `isExpiredNow` in license registry * tests: add tests and final changes * chore: linting * fix: add BUSL license & move whitelist dispute flag
- Loading branch information
1 parent
71912fb
commit df18d84
Showing
10 changed files
with
787 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.26; | ||
|
||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; | ||
|
||
/// @title Ownable ERC20 Interface | ||
/// @notice Interface for the Ownable ERC20 token | ||
interface IOwnableERC20 is IERC20, IERC165 { | ||
/// @notice Struct for the initialization data | ||
/// @param name The name of the token | ||
/// @param symbol The symbol of the token | ||
/// @param cap The cap of the token | ||
/// @param initialOwner The initial owner of the token | ||
struct InitData { | ||
string name; | ||
string symbol; | ||
uint256 cap; | ||
address initialOwner; | ||
} | ||
|
||
/// @notice Initializes the token | ||
/// @param initData The initialization data | ||
function initialize(address ipId, bytes memory initData) external; | ||
|
||
/// @notice Mints tokens | ||
/// @param to The address to mint tokens to | ||
/// @param amount The amount of tokens to mint | ||
function mint(address to, uint256 amount) external; | ||
|
||
/// @notice Returns the upgradable beacon | ||
function upgradableBeacon() external view returns (address); | ||
|
||
/// @notice Returns the ip id to whom this fractionalized token belongs to | ||
function ipId() external view returns (address); | ||
} |
40 changes: 40 additions & 0 deletions
40
contracts/interfaces/modules/tokenizer/ITokenizerModule.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.26; | ||
|
||
import { IModule } from "@storyprotocol/core/interfaces/modules/base/IModule.sol"; | ||
|
||
/// @title Tokenizer Module Interface | ||
/// @notice Interface for the Tokenizer Module | ||
interface ITokenizerModule is IModule { | ||
/// @notice Event emitted when a token template is whitelisted | ||
/// @param tokenTemplate The address of the token template | ||
/// @param allowed The whitelisting status | ||
event TokenTemplateWhitelisted(address tokenTemplate, bool allowed); | ||
|
||
/// @notice Event emitted when an IP is tokenized | ||
/// @param ipId The address of the IP | ||
/// @param token The address of the token | ||
event IPTokenized(address ipId, address token); | ||
|
||
/// @notice Whitelists a token template | ||
/// @param tokenTemplate The address of the token template | ||
/// @param allowed The whitelisting status | ||
function whitelistTokenTemplate(address tokenTemplate, bool allowed) external; | ||
|
||
/// @notice Tokenizes an IP | ||
/// @param ipId The address of the IP | ||
/// @param tokenTemplate The address of the token template | ||
/// @param initData The initialization data for the token | ||
/// @return token The address of the newly created token | ||
function tokenize(address ipId, address tokenTemplate, bytes calldata initData) external returns (address token); | ||
|
||
/// @notice Returns the fractionalized token for an IP | ||
/// @param ipId The address of the IP | ||
/// @return token The address of the token | ||
function getFractionalizedToken(address ipId) external view returns (address token); | ||
|
||
/// @notice Checks if a token template is whitelisted | ||
/// @param tokenTemplate The address of the token template | ||
/// @return allowed The whitelisting status (true if whitelisted, false if not) | ||
function isWhitelistedTokenTemplate(address tokenTemplate) external view returns (bool allowed); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.26; | ||
|
||
import { IERC165 } from "@openzeppelin/contracts/interfaces/IERC165.sol"; | ||
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
// solhint-disable-next-line max-line-length | ||
import { ERC20CappedUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20CappedUpgradeable.sol"; | ||
|
||
import { Errors } from "../../lib/Errors.sol"; | ||
import { IOwnableERC20 } from "../../interfaces/modules/tokenizer/IOwnableERC20.sol"; | ||
|
||
/// @title OwnableERC20 | ||
/// @notice A capped ERC20 token with an owner that can mint tokens. | ||
contract OwnableERC20 is IOwnableERC20, ERC20CappedUpgradeable, OwnableUpgradeable { | ||
/// @dev Storage structure for the OwnableERC20 | ||
/// @param ipId The ip id to whom this fractionalized token belongs to | ||
/// @custom:storage-location erc7201:story-protocol-periphery.OwnableERC20 | ||
struct OwnableERC20Storage { | ||
address ipId; | ||
} | ||
|
||
// solhint-disable-next-line max-line-length | ||
// keccak256(abi.encode(uint256(keccak256("story-protocol-periphery.OwnableERC20")) - 1)) & ~bytes32(uint256(0xff)); | ||
bytes32 private constant OwnableERC20StorageLocation = | ||
0xc4b74d5382372ff8ada6effed0295109822b72fe030fc4cd981ca0e25adfab00; | ||
|
||
/// @notice The upgradable beacon of this contract | ||
address public immutable UPGRADABLE_BEACON; | ||
|
||
constructor(address _upgradableBeacon) { | ||
UPGRADABLE_BEACON = _upgradableBeacon; | ||
_disableInitializers(); | ||
} | ||
|
||
/// @notice Initializes the token | ||
/// @param initData The initialization data | ||
function initialize(address ipId, bytes memory initData) external virtual initializer { | ||
if (ipId == address(0)) revert Errors.OwnableERC20__ZeroIpId(); | ||
|
||
InitData memory initData = abi.decode(initData, (InitData)); | ||
|
||
__ERC20Capped_init(initData.cap); | ||
__ERC20_init(initData.name, initData.symbol); | ||
__Ownable_init(initData.initialOwner); | ||
|
||
OwnableERC20Storage storage $ = _getOwnableERC20Storage(); | ||
$.ipId = ipId; | ||
} | ||
|
||
/// @notice Mints tokens to the specified address. | ||
/// @param to The address to mint tokens to. | ||
/// @param amount The amount of tokens to mint. | ||
function mint(address to, uint256 amount) external virtual onlyOwner { | ||
_mint(to, amount); | ||
} | ||
|
||
/// @notice Returns the upgradable beacon | ||
function upgradableBeacon() external view returns (address) { | ||
return UPGRADABLE_BEACON; | ||
} | ||
|
||
/// @notice Returns the ip id to whom this fractionalized token belongs to | ||
function ipId() external view returns (address) { | ||
return _getOwnableERC20Storage().ipId; | ||
} | ||
|
||
/// @notice Returns whether the contract supports an interface | ||
/// @param interfaceId The interface ID | ||
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { | ||
return interfaceId == type(IOwnableERC20).interfaceId || interfaceId == type(IERC165).interfaceId; | ||
} | ||
|
||
/// @dev Returns the storage struct of OwnableERC20. | ||
function _getOwnableERC20Storage() private pure returns (OwnableERC20Storage storage $) { | ||
assembly { | ||
$.slot := OwnableERC20StorageLocation | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.