Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion script/DeployBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract DeployBase {
*/
function deploy(address registrar_, address migrationAdmin_) public virtual returns (address implementation_, address proxy_) {
implementation_ = address(new MToken(registrar_, migrationAdmin_));
proxy_ = address(new ERC1967Proxy(implementation_, abi.encodeCall(MToken.initialize, ())));
proxy_ = address(new ERC1967Proxy(implementation_, abi.encodeCall(MToken.initialize, ("M by M0", "M"))));
}

function _getExpectedMTokenImplementation(
Expand Down
42 changes: 37 additions & 5 deletions src/MToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pragma solidity 0.8.26;
import { ERC20Extended } from "../lib/common/src/ERC20Extended.sol";
import { UIntMath } from "../lib/common/src/libs/UIntMath.sol";
import { Migratable } from "../lib/common/src/Migratable.sol";
import { Bytes32String } from "../lib/common/src/libs/Bytes32String.sol";

import { IERC20 } from "../lib/common/src/interfaces/IERC20.sol";

Expand All @@ -16,12 +17,29 @@ import { IMToken } from "./interfaces/IMToken.sol";
import { ContinuousIndexing } from "./abstract/ContinuousIndexing.sol";
import { ContinuousIndexingMath } from "./libs/ContinuousIndexingMath.sol";

abstract contract MTokenStorageLayout {
/// @custom:storage-location erc7201:m0.storage.MToken
struct MTokenStorage {
bytes32 name;
bytes32 symbol;
}

// keccak256(abi.encode(uint256(keccak256("m0.storage.MToken")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant _M_TOKEN_STORAGE_SLOT = 0xeb521740570240fc3b71275bd090460409d92adf7cec95ba2df10066ee73c700;

function _getMTokenStorage() internal pure returns (MTokenStorage storage $) {
assembly {
$.slot := _M_TOKEN_STORAGE_SLOT
}
}
}

/**
* @title MToken
* @author M^0 Labs
* @author M0 Labs
* @notice ERC20 M Token living on other chains.
*/
contract MToken is IMToken, ContinuousIndexing, ERC20Extended, Migratable {
contract MToken is IMToken, ContinuousIndexing, ERC20Extended, Migratable, MTokenStorageLayout {
/* ============ Structs ============ */

/**
Expand Down Expand Up @@ -70,9 +88,9 @@ contract MToken is IMToken, ContinuousIndexing, ERC20Extended, Migratable {
* @param registrar_ The address of the Registrar contract.
* @param migrationAdmin_ The address of a migration admin.
*/
constructor(address registrar_, address migrationAdmin_) ContinuousIndexing() ERC20Extended("M by M^0", "M", 6) {
constructor(address registrar_, address migrationAdmin_) ContinuousIndexing() ERC20Extended("M by M0", "M", 6) {
_disableInitializers();

if ((registrar = registrar_) == address(0)) revert ZeroRegistrar();
if ((portal = RegistrarReader.getPortal(registrar_)) == address(0)) revert ZeroPortal();
if ((migrationAdmin = migrationAdmin_) == address(0)) revert ZeroMigrationAdmin();
Expand All @@ -81,8 +99,13 @@ contract MToken is IMToken, ContinuousIndexing, ERC20Extended, Migratable {
/* ============ Initializer ============ */

/// @inheritdoc IMToken
function initialize() external initializer {
function initialize(string memory name_, string memory symbol_) external initializer {
_initialize();

MTokenStorage storage $ = _getMTokenStorage();

$.name = Bytes32String.toBytes32(name_);
$.symbol = Bytes32String.toBytes32(symbol_);
}

/* ============ Interactive Functions ============ */
Expand Down Expand Up @@ -138,6 +161,15 @@ contract MToken is IMToken, ContinuousIndexing, ERC20Extended, Migratable {
}

/* ============ View/Pure Functions ============ */
/// @inheritdoc IERC20
function name() external view override(IERC20, ERC20Extended) returns (string memory name_) {
return Bytes32String.toString(_getMTokenStorage().name);
}

/// @inheritdoc IERC20
function symbol() external view override(IERC20, ERC20Extended) returns (string memory symbol_) {
return Bytes32String.toString(_getMTokenStorage().symbol);
}

/// @inheritdoc IMToken
function totalEarningSupply() public view returns (uint240 totalEarningSupply_) {
Expand Down
8 changes: 6 additions & 2 deletions src/interfaces/IMToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,12 @@ interface IMToken is IContinuousIndexing, IERC20Extended {
*/
function stopEarning(address account) external;

/// @notice Initializes the Proxy's storage.
function initialize() external;
/**
* @notice Initializes the Proxy's storage.
* @param name The name of the token.
* @param symbol The symbol of the token.
*/
function initialize(string memory name, string memory symbol) external;

/**
* @notice Performs an arbitrarily defined migration.
Expand Down
2 changes: 1 addition & 1 deletion test/MToken.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ contract MTokenTests is TestUtils {
_registrar.setPortal(_portal);

_implementation = new MTokenHarness(address(_registrar), _migrationAdmin);
_mToken = MTokenHarness(address(new ERC1967Proxy(address(_implementation), abi.encodeCall(IMToken.initialize, ()))));
_mToken = MTokenHarness(address(new ERC1967Proxy(address(_implementation), abi.encodeCall(IMToken.initialize, ("M by M0", "M")))));

_mToken.setLatestIndex(_expectedCurrentIndex = 1_100000068703);
}
Expand Down
2 changes: 1 addition & 1 deletion test/Migrate.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ contract MigrationTests is Test {
);

_implementation = new MToken(_registrar, _migrationAdmin);
_mToken = MToken(address(new ERC1967Proxy(address(_implementation), abi.encodeCall(IMToken.initialize, ()))));
_mToken = MToken(address(new ERC1967Proxy(address(_implementation), abi.encodeCall(IMToken.initialize, ("M by M0", "M")))));
}

function test_migration() external {
Expand Down
Loading