99// - disable renounceOwnership()
1010pragma solidity ^ 0.8.28 ;
1111
12- import { IMintableAndBurnable } from "./IMintableAndBurnable.sol " ;
13- import { ERC20Upgradeable } from "@openzeppelin-upgradeable/token/ERC20/ERC20Upgradeable.sol " ;
14- import { UUPSUpgradeable } from "@openzeppelin-contracts/proxy/utils/UUPSUpgradeable.sol " ;
15- import { Ownable2StepUpgradeable } from "@openzeppelin-upgradeable/access/Ownable2StepUpgradeable.sol " ;
16- import { StorageSlot } from "@openzeppelin/contracts/utils/StorageSlot.sol " ;
12+ import {IMintableAndBurnable} from "./IMintableAndBurnable.sol " ;
13+ import {
14+ ERC20Upgradeable
15+ } from "@openzeppelin-upgradeable/token/ERC20/ERC20Upgradeable.sol " ;
16+ import {
17+ UUPSUpgradeable
18+ } from "@openzeppelin-contracts/proxy/utils/UUPSUpgradeable.sol " ;
19+ import {
20+ OwnableUpgradeable
21+ } from "@openzeppelin-upgradeable/access/OwnableUpgradeable.sol " ;
22+ import {StorageSlot} from "@openzeppelin/contracts/utils/StorageSlot.sol " ;
1723
18- contract MaxBTCERC20 is IMintableAndBurnable , UUPSUpgradeable , ERC20Upgradeable , Ownable2StepUpgradeable {
19- /// @notice Caller is not the ICS20 contract
24+ contract MaxBTCERC20 is
25+ IMintableAndBurnable ,
26+ UUPSUpgradeable ,
27+ ERC20Upgradeable ,
28+ OwnableUpgradeable
29+ {
30+ /// @notice Caller is not allowed
2031 /// @param caller The address of the caller
21- error CallerIsNotICS20 (address caller );
32+ error CallerIsNotAllowed (address caller );
2233
23- /// @notice Provided ICS20 address is invalid
24- error InvalidICS20 ();
34+ struct TokenConfig {
35+ address ics20;
36+ address core;
37+ }
2538
26- /// @notice ERC-7201 slot for the ICS20 contract address
27- /// @dev keccak256(abi.encode(uint256(keccak256("maxbtc.erc20.ics20")) - 1)) & ~bytes32(uint256(0xff))
28- bytes32 private constant ICS20_STORAGE_SLOT = 0xaa9b9403d129a09996409713bb21f8632c135ae1789678b7128d16411b23e500 ;
39+ /// @dev keccak256(abi.encode(uint256(keccak256("maxbtc.erc20.config")) - 1)) & ~bytes32(uint256(0xff))
40+ bytes32 private constant CONFIG_STORAGE_SLOT =
41+ 0x60e64ce940b41f99536b34ed9aceefb0cc4425527635a944fc8718b4d4247c00 ;
42+
43+ function _getCoreConfig () private pure returns (TokenConfig storage $) {
44+ assembly {
45+ $.slot := CONFIG_STORAGE_SLOT
46+ }
47+ }
2948
3049 /// @dev This contract is meant to be deployed by a proxy, so the constructor is not used
3150 // natlint-disable-next-line MissingNotice
@@ -36,31 +55,35 @@ contract MaxBTCERC20 is IMintableAndBurnable, UUPSUpgradeable, ERC20Upgradeable,
3655 /// @notice Initializes the MaxBTCERC20 contract
3756 /// @param owner_ The owner of the contract, allowing it to be upgraded
3857 /// @param ics20_ The ICS20 contract address
58+ /// @param core_ The Core contract address
3959 /// @param name_ The name of the token
4060 /// @param symbol_ The symbol of the token
4161 function initialize (
4262 address owner_ ,
4363 address ics20_ ,
64+ address core_ ,
4465 string calldata name_ ,
4566 string calldata symbol_
46- )
47- external
48- initializer
49- {
67+ ) external initializer {
5068 __ERC20_init (name_, symbol_);
5169 __Ownable_init (owner_);
52-
53- if (ics20_ == address (0 )) {
54- revert InvalidICS20 ();
55- }
56-
57- StorageSlot.getAddressSlot (ICS20_STORAGE_SLOT).value = ics20_;
70+ TokenConfig storage config = _getCoreConfig ();
71+ config.ics20 = ics20_;
72+ config.core = core_;
5873 }
5974
6075 /// @notice Returns the ICS20 contract address
6176 /// @return The ICS20 contract address
6277 function ics20 () external view returns (address ) {
63- return StorageSlot.getAddressSlot (ICS20_STORAGE_SLOT).value;
78+ TokenConfig storage config = _getCoreConfig ();
79+ return config.ics20;
80+ }
81+
82+ /// @notice Returns the Core contract address
83+ /// @return The Core contract address
84+ function core () external view returns (address ) {
85+ TokenConfig storage config = _getCoreConfig ();
86+ return config.core;
6487 }
6588
6689 /// @inheritdoc ERC20Upgradeable
@@ -69,17 +92,19 @@ contract MaxBTCERC20 is IMintableAndBurnable, UUPSUpgradeable, ERC20Upgradeable,
6992 }
7093
7194 /// @inheritdoc IMintableAndBurnable
72- function mint (address mintAddress , uint256 amount ) external onlyICS20 {
95+ function mint (address mintAddress , uint256 amount ) external allowed {
7396 _mint (mintAddress, amount);
7497 }
7598
7699 /// @inheritdoc IMintableAndBurnable
77- function burn (address mintAddress , uint256 amount ) external onlyICS20 {
100+ function burn (address mintAddress , uint256 amount ) external allowed {
78101 _burn (mintAddress, amount);
79102 }
80103
81104 /// @inheritdoc UUPSUpgradeable
82- function _authorizeUpgrade (address ) internal view override (UUPSUpgradeable) onlyOwner { }
105+ function _authorizeUpgrade (
106+ address
107+ ) internal view override (UUPSUpgradeable) onlyOwner {}
83108 // solhint-disable-previous-line no-empty-blocks
84109
85110 /// @notice prevents `owner` from renouncing ownership and potentially locking assets forever
@@ -89,8 +114,12 @@ contract MaxBTCERC20 is IMintableAndBurnable, UUPSUpgradeable, ERC20Upgradeable,
89114 }
90115
91116 /// @notice Modifier to check if the caller is the ICS20 contract
92- modifier onlyICS20 () {
93- require (_msgSender () == StorageSlot.getAddressSlot (ICS20_STORAGE_SLOT).value, CallerIsNotICS20 (_msgSender ()));
117+ modifier allowed () {
118+ TokenConfig storage config = _getCoreConfig ();
119+ require (
120+ _msgSender () == config.ics20 || _msgSender () == config.core,
121+ CallerIsNotAllowed (_msgSender ())
122+ );
94123 _;
95124 }
96125}
0 commit comments