Rebasing tokens like Mountain Protocol's USDM are powerful for users but require special handling by developers. Because the balanceOf() an address changes daily, you can't use it as a stable measure of a user's "share." Let's explore the correct way to handle this.
The Problem with Simple Balance Tracking
If you track a user's deposit in your dApp using balanceOf(), the daily rebase will break your accounting. A user's balance will increase on its own, and your contract won't know if it's from a new deposit or a rebase event.
Wrong way:
solidity
// DO NOT DO THIS
mapping(address => uint256) public userDeposits;
function deposit(uint256 amount) external {
usdmToken.transferFrom(msg.sender, address(this), amount);
userDeposits[msg.sender] += amount; // This is now incorrect after a rebase
}
The Solution: Tracking Shares, Not Balances
The correct method is to create a "shares" system. Your contract tracks a user's proportion of the total funds it holds, not the absolute amount.
Correct way (Conceptual):
solidity
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IRebasingUSDM is IERC20 {
// A rebasing token often has a 'shares' mechanism
function sharesOf(address account) external view returns (uint256);
function getSharesByAmount(uint256 amount) external view returns (uint256);
}
contract MyDApp {
IRebasingUSDM public usdmToken;
mapping(address => uint256) public userShares;
uint256 public totalShares;
function deposit(uint256 amount) external {
// Convert the amount of USDM to a fixed number of shares
uint256 sharesToMint = usdmToken.getSharesByAmount(amount);
userShares[msg.sender] += sharesToMint;
totalShares += sharesToMint;
usdmToken.transferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 sharesToBurn) external {
// When a user withdraws, their shares are converted back to the
// current (rebased) amount of USDM.
uint256 amountToWithdraw = (usdmToken.balanceOf(address(this)) * sharesToBurn) / totalShares;
userShares[msg.sender] -= sharesToBurn;
totalShares -= sharesToBurn;
usdmToken.transfer(msg.sender, amountToWithdraw);
}
}
By using shares, your application becomes compatible with the daily Rewards distribution of the Mountain Protocol. For full integration details, the official community documentation is the definitive Guide.
Top comments (0)