Assessment reports>Takara Lend Contracts>Low findings>Markets entered automatically can be exited
Category: Business Logic

Markets entered automatically can be exited

Low Severity
Low Impact
Medium Likelihood

Description

In the Comptroller contract, enterAllMarkets is a newly added function that enters all of the nondeprecated markets upon request from a TToken contract:

+function enterAllMarkets(address account) public override returns (uint256[] memory) {
+    address[] memory assetsAddresses = new address[](allMarkets.length);
+
+    bool isRTokenContract;
+
+    for (uint256 i = 0; i < allMarkets.length; i++) {
+        assetsAddresses[i] = address(allMarkets[i]);
+
+        if (assetsAddresses[i] == msg.sender) {
+            isRTokenContract = true;
+        }
+    }
+
+    require(isRTokenContract, "Sender must be a TToken contract");
+
+    uint256 len = assetsAddresses.length;
+
+    uint256[] memory results = new uint256[](len);
+
+    for (uint256 i = 0; i < len; i++) {
+        // Prevent paused asset enter market
+        if (borrowGuardianPaused[assetsAddresses[i]]) continue;
+
+        TToken tToken = TToken(assetsAddresses[i]);
+        results[i] = uint256(addToMarketInternal(tToken, account));
+    }
+
+    return results;
+}

This function is called in TToken whenever someone mints assets:

function mintFresh(address minter, uint256 mintAmount) internal returns (uint256, uint256) {
    // [...]

+   comptroller.enterAllMarkets(minter);

    return (uint256(Error.NO_ERROR), vars.actualMintAmount);
}

However, although this additional call makes depositors enter all the markets, the exitMarket function was not changed at all, and users can still exit markets for which they do not have any borrow balance.

Impact

Users may bundle transactions or operate through a smart wallet in order to immediately exit all the markets they do not wish to stay entered in, after minting assets. This reduces this contract change from a restriction to a convenience, because the action can be undone transactionally.

Additionally, this implementation favors sophisticated users, because regular users will either not realize that they can exit markets they do not wish to stay entered in or exit in a separate manually submitted public-mempool transaction, which risks a liquidation occuring before the exit is confirmed.

Recommendations

If remaining in all nondeprecated markets is mandatory, then we recommend disabling exitMarket for the markets that enterAllMarkets enters.

Alternatively, if this is a single-transaction convenience, then we recommend adding a parameter to the mint function that allows users to opt out of this automatic entry, so that unsophisticated users have the same easy ability to opt out of this convenience as sophisticated ones. Another way to implement this option, if the function interface for minting should not be changed from the upstream implementation, is to have an account-specific setting that users can arbitrarily change by calling a function on the Comptroller contract.

Remediation

This issue has been acknowledged by Takara Lend, and a fix was implemented in commit 7ee9b938. The enterAllMarkets function has been removed.

Zellic © 2025Back to top ↑