Vulnerability: Accounts contains expensive looping
Severity: medium

Description:
`Accounts.getBorrowETH` performs multiple external calls to `GlobalConfig` and `TokenRegistry` within a for loop:\\n```\\nfunction getBorrowETH(\\n    address \\_accountAddr\\n) public view returns (uint256 borrowETH) {\\n    uint tokenNum = globalConfig.tokenInfoRegistry().getCoinLength();\\n    //console.log("tokenNum", tokenNum);\\n    for(uint i = 0; i < tokenNum; i++) {\\n        if(isUserHasBorrows(\\_accountAddr, uint8(i))) {\\n            address tokenAddress = globalConfig.tokenInfoRegistry().addressFromIndex(i);\\n            uint divisor = INT\\_UNIT;\\n            if(tokenAddress != ETH\\_ADDR) {\\n                divisor = 10 \\*\\* uint256(globalConfig.tokenInfoRegistry().getTokenDecimals(tokenAddress));\\n            }\\n            borrowETH = borrowETH.add(getBorrowBalanceCurrent(tokenAddress, \\_accountAddr).mul(globalConfig.tokenInfoRegistry().priceFromIndex(i)).div(divisor));\\n        }\\n    }\\n    return borrowETH;\\n}\\n```\\n\\nThe loop also makes additional external calls and delegatecalls from:\\nTokenRegistry.priceFromIndex:\\n```\\nfunction priceFromIndex(uint index) public view returns(uint256) {\\n    require(index < tokens.length, "coinIndex must be smaller than the coins length.");\\n    address tokenAddress = tokens[index];\\n    // Temp fix\\n    if(Utils.\\_isETH(address(globalConfig), tokenAddress)) {\\n        return 1e18;\\n    }\\n    return uint256(globalConfig.chainLink().getLatestAnswer(tokenAddress));\\n}\\n```\\n\\nAccounts.getBorrowBalanceCurrent:\\n```\\nfunction getBorrowBalanceCurrent(\\n    address \\_token,\\n    address \\_accountAddr\\n) public view returns (uint256 borrowBalance) {\\n    AccountTokenLib.TokenInfo storage tokenInfo = accounts[\\_accountAddr].tokenInfos[\\_token];\\n    uint accruedRate;\\n    if(tokenInfo.getBorrowPrincipal() == 0) {\\n        return 0;\\n    } else {\\n        if(globalConfig.bank().borrowRateIndex(\\_token, tokenInfo.getLastBorrowBlock()) == 0) {\\n            accruedRate = INT\\_UNIT;\\n        } else {\\n            accruedRate = globalConfig.bank().borrowRateIndexNow(\\_token)\\n            .mul(INT\\_UNIT)\\n            .div(globalConfig.bank().borrowRateIndex(\\_token, tokenInfo.getLastBorrowBlock()));\\n        }\\n        return tokenInfo.getBorrowBalance(accruedRate);\\n    }\\n}\\n```\\n\\nIn a worst case scenario, each iteration may perform a maximum of 25+ calls/delegatecalls. Assuming a maximum `tokenNum` of 128 (TokenRegistry.MAX_TOKENS), the gas cost for this method may reach upwards of 2 million for external calls alone.\\nGiven that this figure would only be a portion of the total transaction gas cost, `getBorrowETH` may represent a DoS risk within the `Accounts` contract.

Impact:

Recommended mitigation:
Avoid for loops unless absolutely necessary\\nWhere possible, consolidate multiple subsequent calls to the same contract to a single call, and store the results of calls in local variables for re-use. For example,\\nInstead of this:\\n```\\nuint tokenNum = globalConfig.tokenInfoRegistry().getCoinLength();\\nfor(uint i = 0; i < tokenNum; i++) {\\n  if(isUserHasBorrows(\\_accountAddr, uint8(i))) {\\n    address tokenAddress = globalConfig.tokenInfoRegistry().addressFromIndex(i);\\n    uint divisor = INT\\_UNIT;\\n    if(tokenAddress != ETH\\_ADDR) {\\n      divisor = 10 \\*\\* uint256(globalConfig.tokenInfoRegistry().getTokenDecimals(tokenAddress));\\n    }\\n    borrowETH = borrowETH.add(getBorrowBalanceCurrent(tokenAddress, \\_accountAddr).mul(globalConfig.tokenInfoRegistry().priceFromIndex(i)).div(divisor));\\n  }\\n}\\n```\\n\\nModify `TokenRegistry` to support a single call, and cache intermediate results like this:\\n```\\nTokenRegistry registry = globalConfig.tokenInfoRegistry();\\nuint tokenNum = registry.getCoinLength();\\nfor(uint i = 0; i < tokenNum; i++) {\\n  if(isUserHasBorrows(\\_accountAddr, uint8(i))) {\\n    // here, getPriceFromIndex(i) performs all of the steps as the code above, but with only 1 ext call\\n    borrowETH = borrowETH.add(getBorrowBalanceCurrent(tokenAddress, \\_accountAddr).mul(registry.getPriceFromIndex(i)).div(divisor));\\n  }\\n}\\n```\\n