From 79efc53edfdc01bfdbbe7f47ef7b9e2567f55afb Mon Sep 17 00:00:00 2001 From: toninorair Date: Wed, 4 Jun 2025 16:40:44 -0400 Subject: [PATCH 1/4] Adjust earner rate model --- src/rateModels/EarnerRateModel.sol | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/rateModels/EarnerRateModel.sol b/src/rateModels/EarnerRateModel.sol index be5bf286..59df4c44 100644 --- a/src/rateModels/EarnerRateModel.sol +++ b/src/rateModels/EarnerRateModel.sol @@ -64,14 +64,21 @@ 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(); + + // 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 with outstanding balance, + // it is safe to return `earnerRate` as the effective rate. + if (earnerRate_ <= minterRate_ && IMinterGateway(minterGateway).totalInactiveOwedM() == 0) return earnerRate_; + return UIntMath.min256( - maxRate(), - getExtraSafeEarnerRate( - IMinterGateway(minterGateway).totalActiveOwedM(), - IMToken(mToken).totalEarningSupply(), - IMinterGateway(minterGateway).minterRate() - ) + earnerRate_, + getExtraSafeEarnerRate(totalActiveOwedM_, IMToken(mToken).totalEarningSupply(), minterRate_) ); } From 15371728cd273e5fe9cc04d34f3729fc2b75ce28 Mon Sep 17 00:00:00 2001 From: toninorair Date: Wed, 4 Jun 2025 16:45:03 -0400 Subject: [PATCH 2/4] Adjust earner rate model --- src/rateModels/EarnerRateModel.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rateModels/EarnerRateModel.sol b/src/rateModels/EarnerRateModel.sol index 59df4c44..2f025327 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 ============ */ From d3e1521632b72becab060623678106d789d901a2 Mon Sep 17 00:00:00 2001 From: toninorair Date: Wed, 4 Jun 2025 21:49:34 -0400 Subject: [PATCH 3/4] Make model better --- src/rateModels/EarnerRateModel.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/rateModels/EarnerRateModel.sol b/src/rateModels/EarnerRateModel.sol index 2f025327..7a327d79 100644 --- a/src/rateModels/EarnerRateModel.sol +++ b/src/rateModels/EarnerRateModel.sol @@ -67,19 +67,17 @@ contract EarnerRateModel is IEarnerRateModel { 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 with outstanding balance, + // 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_ && IMinterGateway(minterGateway).totalInactiveOwedM() == 0) return earnerRate_; + if (earnerRate_ <= minterRate_ && totalActiveOwedM_ >= totalEarningSupply_) return earnerRate_; return - UIntMath.min256( - earnerRate_, - getExtraSafeEarnerRate(totalActiveOwedM_, IMToken(mToken).totalEarningSupply(), minterRate_) - ); + UIntMath.min256(earnerRate_, getExtraSafeEarnerRate(totalActiveOwedM_, totalEarningSupply_, minterRate_)); } /// @inheritdoc IEarnerRateModel From fa60bccd1927f54aee2a00ff76b69ea6f14161cf Mon Sep 17 00:00:00 2001 From: toninorair Date: Wed, 4 Jun 2025 22:28:15 -0400 Subject: [PATCH 4/4] Add script --- script/DeployEarnerRateModel.s.sol | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 script/DeployEarnerRateModel.s.sol 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_); + } +}