@@ -4,6 +4,7 @@ pragma solidity 0.8.26;
44
55import { ERC20Extended } from "../lib/common/src/ERC20Extended.sol " ;
66import { UIntMath } from "../lib/common/src/libs/UIntMath.sol " ;
7+ import { Migratable } from "../lib/common/src/Migratable.sol " ;
78
89import { IERC20 } from "../lib/common/src/interfaces/IERC20.sol " ;
910
@@ -20,7 +21,7 @@ import { ContinuousIndexingMath } from "./libs/ContinuousIndexingMath.sol";
2021 * @author M^0 Labs
2122 * @notice ERC20 M Token living on other chains.
2223 */
23- contract MToken is IMToken , ContinuousIndexing , ERC20Extended {
24+ contract MToken is IMToken , ContinuousIndexing , ERC20Extended , Migratable {
2425 /* ============ Structs ============ */
2526
2627 /**
@@ -41,6 +42,9 @@ contract MToken is IMToken, ContinuousIndexing, ERC20Extended {
4142 /// @inheritdoc IMToken
4243 address public immutable registrar;
4344
45+ /// @inheritdoc IMToken
46+ address public immutable migrationAdmin;
47+
4448 /// @inheritdoc IMToken
4549 uint240 public totalNonEarningSupply;
4650
@@ -62,11 +66,21 @@ contract MToken is IMToken, ContinuousIndexing, ERC20Extended {
6266
6367 /**
6468 * @notice Constructs the M Token contract.
69+ * @dev Sets immutable storage.
6570 * @param registrar_ The address of the Registrar contract.
71+ * @param migrationAdmin_ The address of a migration admin.
6672 */
67- constructor (address registrar_ ) ContinuousIndexing () ERC20Extended ("M by M^0 " , "M " , 6 ) {
73+ constructor (address registrar_ , address migrationAdmin_ ) ContinuousIndexing () ERC20Extended ("M by M^0 " , "M " , 6 ) {
6874 if ((registrar = registrar_) == address (0 )) revert ZeroRegistrar ();
6975 if ((portal = RegistrarReader.getPortal (registrar_)) == address (0 )) revert ZeroPortal ();
76+ if ((migrationAdmin = migrationAdmin_) == address (0 )) revert ZeroMigrationAdmin ();
77+ }
78+
79+ /* ============ Initializer ============ */
80+
81+ /// @inheritdoc IMToken
82+ function initialize () external initializer {
83+ _initialize ();
7084 }
7185
7286 /* ============ Interactive Functions ============ */
@@ -112,6 +126,15 @@ contract MToken is IMToken, ContinuousIndexing, ERC20Extended {
112126 _stopEarning (account_);
113127 }
114128
129+ /**
130+ * @dev Performs the contract migration by calling `migrator_`.
131+ * @param migrator_ The address of a migrator contract.
132+ */
133+ function migrate (address migrator_ ) external {
134+ if (msg .sender != migrationAdmin) revert UnauthorizedMigration ();
135+ _migrate (migrator_);
136+ }
137+
115138 /* ============ View/Pure Functions ============ */
116139
117140 /// @inheritdoc IMToken
@@ -438,4 +461,10 @@ contract MToken is IMToken, ContinuousIndexing, ERC20Extended {
438461 function _revertIfNotPortal () internal view {
439462 if (msg .sender != portal) revert NotPortal ();
440463 }
464+
465+ /// @inheritdoc Migratable
466+ function _getMigrator () internal pure override returns (address migrator_ ) {
467+ // NOTE: in this version only the admin-controlled migration via `migrate()` function is supported
468+ return address (0 );
469+ }
441470}
0 commit comments