Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Obtaining values by destructuring #28

Open
chunteng-web3 opened this issue Mar 8, 2023 · 0 comments
Open

Obtaining values by destructuring #28

chunteng-web3 opened this issue Mar 8, 2023 · 0 comments

Comments

@chunteng-web3
Copy link

When using sol2ink, it seems unable to properly properly obtain values by destructuring.

For example, in this section:

struct balanceDecreaseAllowedLocalVars {
    uint256 decimals;
    uint256 liquidationThreshold;
    uint256 totalCollateralInETH;
    uint256 totalDebtInETH;
    uint256 avgLiquidationThreshold;
    uint256 amountToDecreaseInETH;
    uint256 collateralBalanceAfterDecrease;
    uint256 liquidationThresholdAfterDecrease;
    uint256 healthFactorAfterDecrease;
    bool reserveUsageAsCollateralEnabled;
  }

  /**
   * @dev Checks if a specific balance decrease is allowed
   * (i.e. doesn't bring the user borrow position health factor under HEALTH_FACTOR_LIQUIDATION_THRESHOLD)
   * @param asset The address of the underlying asset of the reserve
   * @param user The address of the user
   * @param amount The amount to decrease
   * @param reservesData The data of all the reserves
   * @param userConfig The user configuration
   * @param reserves The list of all the active reserves
   * @param oracle The address of the oracle contract
   * @return true if the decrease of the balance is allowed
   **/
  function balanceDecreaseAllowed(
    address asset,
    address user,
    uint256 amount,
    mapping(address => DataTypes.ReserveData) storage reservesData,
    DataTypes.UserConfigurationMap calldata userConfig,
    mapping(uint256 => address) storage reserves,
    uint256 reservesCount,
    address oracle
  ) external view returns (bool) {
    if (!userConfig.isBorrowingAny() || !userConfig.isUsingAsCollateral(reservesData[asset].id)) {
      return true;
    }

    balanceDecreaseAllowedLocalVars memory vars;

    (, vars.liquidationThreshold, , vars.decimals, ) = reservesData[asset]
      .configuration
      .getParams();

    if (vars.liquidationThreshold == 0) {
      return true;
    }

    (
      vars.totalCollateralInETH,
      vars.totalDebtInETH,
      ,
      vars.avgLiquidationThreshold,

    ) = calculateUserAccountData(user, reservesData, userConfig, reserves, reservesCount, oracle);

    if (vars.totalDebtInETH == 0) {
      return true;
    }

    vars.amountToDecreaseInETH = IPriceOracleGetter(oracle).getAssetPrice(asset).mul(amount).div(
      10**vars.decimals
    );

    vars.collateralBalanceAfterDecrease = vars.totalCollateralInETH.sub(vars.amountToDecreaseInETH);

    //if there is a borrow, there can't be 0 collateral
    if (vars.collateralBalanceAfterDecrease == 0) {
      return false;
    }

    vars.liquidationThresholdAfterDecrease = vars
      .totalCollateralInETH
      .mul(vars.avgLiquidationThreshold)
      .sub(vars.amountToDecreaseInETH.mul(vars.liquidationThreshold))
      .div(vars.collateralBalanceAfterDecrease);

    uint256 healthFactorAfterDecrease = calculateHealthFactorFromBalances(
      vars.collateralBalanceAfterDecrease,
      vars.totalDebtInETH,
      vars.liquidationThresholdAfterDecrease
    );

    return healthFactorAfterDecrease >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD;
  }

The converted code is like this:

// ...
pub fn balance_decrease_allowed(
    &self,
    asset: AccountId,
    user: AccountId,
    amount: u128,
    reserves_data: Mapping<AccountId, data_types::reserve_data>,
    user_config: data_types::user_configuration_map,
    reserves: Mapping<u128, AccountId>,
    reserves_count: u128,
    oracle: AccountId,
) -> Result<bool, Error> {
    if !user_config.is_borrowing_any()?
        || !user_config.is_using_as_collateral(reserves_data[asset].id)?
    {
        return Ok(true)
    };
    (_, _, _, _, _) = reserves_data[asset].configuration.get_params()?;
    if vars.liquidation_threshold == 0 {
        return Ok(true)
    }
    (_, _, _, _, _) = self._calculate_user_account_data(
        user,
        reserves_data,
        user_config,
        reserves,
        reserves_count,
        oracle,
    )?;
    if vars.total_debt_in_eth == 0 {
        return Ok(true)
    }
    vars.amount_to_decrease_in_eth = i_price_oracle_getter(oracle)?
        .get_asset_price(asset)?
        .mul(amount)?
        .div(10.pow(vars.decimals))?;
    vars.collateral_balance_after_decrease = vars
        .total_collateral_in_eth
        .sub(vars.amount_to_decrease_in_eth)?;
    if vars.collateral_balance_after_decrease == 0 {
        return Ok(false)
    }
    vars.liquidation_threshold_after_decrease = vars
        .total_collateral_in_eth
        .mul(vars.avg_liquidation_threshold)?
        .sub(
            vars.amount_to_decrease_in_eth
                .mul(vars.liquidation_threshold)?,
        )?
        .div(vars.collateral_balance_after_decrease)?;
    let mut health_factor_after_decrease: u128 = self._calculate_health_factor_from_balances(
        vars.collateral_balance_after_decrease,
        vars.total_debt_in_eth,
        vars.liquidation_threshold_after_decrease,
    )?;
    return Ok(health_factor_after_decrease >= generic_logic.health_factor_liquidation_threshold)
}
// Skipping the irrelevant

As you can see, vars is not properly defined here.
It attempted to obtain value by destructuring:

 (_, _, _, _, _) = reserves_data[asset].configuration.get_params()?;

but it's ignoring all the obtained values.

To fix this at the moment, this is what I did:

// ToDo: Check the code here as the generated code failed to obtain configurations
    let vars:BalanceDecreaseAllowedLocalVars = BalanceDecreaseAllowedLocalVars::new();

    (_, vars.liquidation_threshold, _, vars.decimals, _) = reserves_data[asset].configuration.get_params()?;
    
    if vars.liquidation_threshold == 0 {
        return Ok(true)
    }

    (vars.total_collateral_in_eth, vars.total_debt_in_eth, _, vars.avg_liquidation_threshold, _) = calculate_user_account_data(
        user,
        reserves_data,
        user_config,
        reserves,
        reserves_count,
        oracle,
    )?;

    if vars.total_debt_in_eth == 0 {
        return Ok(true)
    }
    // ToDo: Cross-contract calling here.
    // vars.amount_to_decrease_in_eth = i_price_oracle_getter(oracle)?
    //     .get_asset_price(asset)?
    //     .mul(amount)?
    //     .div(10.pow(vars.decimals))?;
    vars.collateral_balance_after_decrease = vars
        .total_collateral_in_eth
        .sub(vars.amount_to_decrease_in_eth)?;
    if vars.collateral_balance_after_decrease == 0 {
        return Ok(false)
    }
    vars.liquidation_threshold_after_decrease = vars
        .total_collateral_in_eth
        .mul(vars.avg_liquidation_threshold)?
        .sub(
            vars.amount_to_decrease_in_eth
                .mul(vars.liquidation_threshold)?,
        )?
        .div(vars.collateral_balance_after_decrease)?;
    let mut health_factor_after_decrease: u128 = calculate_health_factor_from_balances(
        vars.collateral_balance_after_decrease,
        vars.total_debt_in_eth,
        vars.liquidation_threshold_after_decrease,
    )?;
    return Ok(health_factor_after_decrease >= HEALTH_FACTOR_LIQUIDATION_THRESHOLD)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant