diff --git a/script/DeployEarnerRateModel.s.sol b/script/DeployEarnerRateModel.s.sol new file mode 100644 index 00000000..c6d8ebff --- /dev/null +++ b/script/DeployEarnerRateModel.s.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity 0.8.23; + +import { Script, console2 } from "../lib/forge-std/src/Script.sol"; +import { EarnerRateModel } from "../src/rateModels/EarnerRateModel.sol"; + +contract DeployEarnerRateModel is Script { + // NOTE: Ensure this is the correct MinterGateway testnet/mainnet address. + address internal constant _MINTER_GATEWAY = 0xf7f9638cb444D65e5A40bF5ff98ebE4ff319F04E; //mainnet + // address internal constant _MINTER_GATEWAY = 0x4eDfcfB5F9e55962EF1A2eEf0b56A8FaDbaBA289; // sepolia + + function run() external { + address deployer_ = vm.rememberKey(vm.envUint("PRIVATE_KEY")); + + console2.log("Deployer:", deployer_); + + vm.startBroadcast(deployer_); + + address earnerRateModel_ = address(new EarnerRateModel(_MINTER_GATEWAY)); + + vm.stopBroadcast(); + + console2.log("Earner Rate Model address:", earnerRateModel_); + } +} diff --git a/src/rateModels/EarnerRateModel.sol b/src/rateModels/EarnerRateModel.sol index be5bf286..7a327d79 100644 --- a/src/rateModels/EarnerRateModel.sol +++ b/src/rateModels/EarnerRateModel.sol @@ -16,7 +16,7 @@ import { IEarnerRateModel } from "./interfaces/IEarnerRateModel.sol"; /** * @title Earner Rate Model contract set in TTG (Two Token Governance) Registrar and accessed by MToken. - * @author M^0 Labs + * @author M0 Labs */ contract EarnerRateModel is IEarnerRateModel { /* ============ Variables ============ */ @@ -64,15 +64,20 @@ contract EarnerRateModel is IEarnerRateModel { /// @inheritdoc IRateModel function rate() external view returns (uint256) { + uint256 earnerRate_ = maxRate(); + uint32 minterRate_ = IMinterGateway(minterGateway).minterRate(); + uint240 totalActiveOwedM_ = IMinterGateway(minterGateway).totalActiveOwedM(); + uint240 totalEarningSupply_ = IMToken(mToken).totalEarningSupply(); + + // If there are no active minters or minter rate is zero, do not accrue yield to earners. + if (totalActiveOwedM_ == 0 || minterRate_ == 0) return 0; + + // NOTE: If `earnerRate` <= `minterRate` and there are no deactivated minters in the system, + // it is safe to return `earnerRate` as the effective rate. + if (earnerRate_ <= minterRate_ && totalActiveOwedM_ >= totalEarningSupply_) return earnerRate_; + return - UIntMath.min256( - maxRate(), - getExtraSafeEarnerRate( - IMinterGateway(minterGateway).totalActiveOwedM(), - IMToken(mToken).totalEarningSupply(), - IMinterGateway(minterGateway).minterRate() - ) - ); + UIntMath.min256(earnerRate_, getExtraSafeEarnerRate(totalActiveOwedM_, totalEarningSupply_, minterRate_)); } /// @inheritdoc IEarnerRateModel