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

Updating from PR #13

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ contract FM_PC_ExternalPrice_Redeeming_v1 is

// Create and emit the order.
_createAndEmitOrder(
_receiver, _depositAmount, collateralRedeemAmount, issuanceFeeAmount
_receiver, _depositAmount, collateralRedeemAmount, projectFeeAmount

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what was the reason for this change? just curious

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was from the audit check here

InverterNetwork#704 (comment)

);

return (totalCollateralTokenMovedOut, issuanceFeeAmount);
Expand Down
91 changes: 22 additions & 69 deletions src/modules/logicModule/LM_ManualExternalPriceSetter_v1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,31 +71,19 @@ contract LM_ManualExternalPriceSetter_v1 is
/// @dev This role should be granted to trusted price feeders only.
bytes32 public constant PRICE_SETTER_ROLE = "PRICE_SETTER_ROLE";

/// @notice Number of decimal places used for internal price
/// representation
/// @dev All prices are normalized to this precision for consistent
/// calculations regardless of input/output token decimals.
uint8 private constant INTERNAL_DECIMALS = 18;

// -------------------------------------------------------------------------
// State Variables

/// @notice The price for issuing tokens (normalized to
/// INTERNAL_DECIMALS).
/// @notice The price for issuing tokens (in collateral token decimals)
uint private _issuancePrice;

/// @notice The price for redeeming tokens (normalized to
/// INTERNAL_DECIMALS).
/// @notice The price for redeeming tokens (in collateral token decimals)
uint private _redemptionPrice;

/// @notice Decimals of the collateral token (e.g., USDC with 6 decimals).
/// @dev This is the token used to pay/buy with.
uint8 private _collateralTokenDecimals;

/// @notice Decimals of the issuance token (e.g., ISS with 18 decimals).
/// @dev This is the token being bought/sold.
uint8 private _issuanceTokenDecimals;

// -------------------------------------------------------------------------
// Initialization

Expand All @@ -107,13 +95,11 @@ contract LM_ManualExternalPriceSetter_v1 is
) external override(Module_v1) initializer {
__Module_init(orchestrator_, metadata_);

// Decode collateral and issuance token addresses from configData_.
(address collateralToken, address issuanceToken) =
abi.decode(configData_, (address, address));
// Decode collateral token address from configData_.
(address collateralToken) = abi.decode(configData_, (address));

// Store token decimals for price normalization.
_collateralTokenDecimals = IERC20Metadata(collateralToken).decimals();
_issuanceTokenDecimals = IERC20Metadata(issuanceToken).decimals();
}

// -------------------------------------------------------------------------
Expand All @@ -124,23 +110,15 @@ contract LM_ManualExternalPriceSetter_v1 is
external
onlyModuleRole(PRICE_SETTER_ROLE)
{
if (price_ == 0) revert Module__LM_ExternalPriceSetter__InvalidPrice();

// Normalize price to internal decimal precision
_issuancePrice = _normalizePrice(price_, _collateralTokenDecimals);
emit IssuancePriceSet(price_);
_setIssuancePrice(price_);
}

/// @inheritdoc ILM_ManualExternalPriceSetter_v1
function setRedemptionPrice(uint price_)
external
onlyModuleRole(PRICE_SETTER_ROLE)
{
if (price_ == 0) revert Module__LM_ExternalPriceSetter__InvalidPrice();

// Normalize price to internal decimal precision.
_redemptionPrice = _normalizePrice(price_, _issuanceTokenDecimals);
emit RedemptionPriceSet(price_);
_setRedemptionPrice(price_);
}

/// @inheritdoc ILM_ManualExternalPriceSetter_v1
Expand All @@ -153,10 +131,8 @@ contract LM_ManualExternalPriceSetter_v1 is
}

// Normalize and set both prices atomically
_issuancePrice =
_normalizePrice(issuancePrice_, _collateralTokenDecimals);
_redemptionPrice =
_normalizePrice(redemptionPrice_, _issuanceTokenDecimals);
_setIssuancePrice(issuancePrice_);
_setRedemptionPrice(redemptionPrice_);

// Emit events
emit IssuancePriceSet(issuancePrice_);
Expand All @@ -169,8 +145,7 @@ contract LM_ManualExternalPriceSetter_v1 is
/// @dev Example: If price is 2 USDC/ISS, returns 2e18 (2 USDC needed for
/// 1 ISS).
function getPriceForIssuance() external view returns (uint) {
// Convert from internal precision to output token precision.
return _denormalizePrice(_issuancePrice, _issuanceTokenDecimals);
return _issuancePrice;
}

/// @notice Gets current price for token redemption (selling tokens).
Expand All @@ -179,48 +154,26 @@ contract LM_ManualExternalPriceSetter_v1 is
/// @dev Example: If price is 1.9 USDC/ISS, returns 1.9e18 (1.9 USDC
/// received for 1 ISS).
function getPriceForRedemption() external view returns (uint) {
// Convert from internal precision to output token precision.
return _denormalizePrice(_redemptionPrice, _issuanceTokenDecimals);
return _redemptionPrice;
}

//--------------------------------------------------------------------------
// Internal Functions

/// @notice Normalizes a price from token decimals to internal decimals.
/// @param price_ The price to normalize.
/// @param tokenDecimals_ The decimals of the token the price is
/// denominated in.
/// @return The normalized price with INTERNAL_DECIMALS precision.
function _normalizePrice(uint price_, uint8 tokenDecimals_)
internal
pure
returns (uint)
{
if (tokenDecimals_ == INTERNAL_DECIMALS) return price_;

if (tokenDecimals_ > INTERNAL_DECIMALS) {
return price_ / (10 ** (tokenDecimals_ - INTERNAL_DECIMALS));
} else {
return price_ * (10 ** (INTERNAL_DECIMALS - tokenDecimals_));
}
/// @notice Internal function to set the issuance price
/// @param price_ The price to set
function _setIssuancePrice(uint price_) internal {
if (price_ == 0) revert Module__LM_ExternalPriceSetter__InvalidPrice();
_issuancePrice = price_;
emit IssuancePriceSet(price_);
}

/// @notice Denormalizes a price from internal decimals to token decimals.
/// @param price_ The price to denormalize.
/// @param tokenDecimals_ The target token decimals.
/// @return The denormalized price with tokenDecimals_ precision.
function _denormalizePrice(uint price_, uint8 tokenDecimals_)
internal
pure
returns (uint)
{
if (tokenDecimals_ == INTERNAL_DECIMALS) return price_;

if (tokenDecimals_ > INTERNAL_DECIMALS) {
return price_ * (10 ** (tokenDecimals_ - INTERNAL_DECIMALS));
} else {
return price_ / (10 ** (INTERNAL_DECIMALS - tokenDecimals_));
}
/// @notice Internal function to set the redemption price
/// @param price_ The price to set
function _setRedemptionPrice(uint price_) internal {
if (price_ == 0) revert Module__LM_ExternalPriceSetter__InvalidPrice();
_redemptionPrice = price_;
emit RedemptionPriceSet(price_);
}

/// @dev Storage gap for upgradeable contracts.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,8 @@ contract FM_PC_ExternalPrice_Redeeming_v1_Test is ModuleTest {
vm.assume(nonWhitelisted != admin);
vm.assume(nonWhitelisted != address(this));

roleId = _authorizer.generateRoleId(address(fundingManager), WHITELIST_ROLE);
roleId =
_authorizer.generateRoleId(address(fundingManager), WHITELIST_ROLE);
// Prepare buy conditions with a fixed amount
uint minAmount = 1 * 10 ** _token.decimals();
uint maxAmount = 1_000_000 * 10 ** _token.decimals();
Expand Down Expand Up @@ -1077,7 +1078,7 @@ contract FM_PC_ExternalPrice_Redeeming_v1_Test is ModuleTest {

// Given - Setup buying conditions
fundingManager.grantModuleRole(WHITELIST_ROLE, buyer);

// Given - Mint tokens and approve
_token.mint(buyer, buyAmount);
vm.startPrank(buyer);
Expand All @@ -1093,7 +1094,8 @@ contract FM_PC_ExternalPrice_Redeeming_v1_Test is ModuleTest {
// Given - Calculate expected tokens and store initial balances
uint expectedTokens = _calculateExpectedIssuance(buyAmount);
uint buyerBalanceBefore = _token.balanceOf(buyer);
uint projectTreasuryBalanceBefore = _token.balanceOf(fundingManager.getProjectTreasury());
uint projectTreasuryBalanceBefore =
_token.balanceOf(fundingManager.getProjectTreasury());
uint buyerIssuedTokensBefore = issuanceToken.balanceOf(buyer);

// When - Buy tokens with max amount
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;

import {ERC20Issuance_Blacklist_v1} from
"@ex/token/ERC20Issuance_Blacklist_v1.sol";

/**
* @title ERC20Issuance_Blacklist_v1_Exposed
* @dev Contract that exposes internal functions of ERC20Issuance_Blacklist_v1 for testing purposes
*/
contract ERC20Issuance_Blacklist_v1_Exposed is ERC20Issuance_Blacklist_v1 {
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
uint initialSupply_,
address initialAdmin_,
address initialBlacklistManager_
)
ERC20Issuance_Blacklist_v1(
name_,
symbol_,
decimals_,
initialSupply_,
initialAdmin_,
initialBlacklistManager_
)
{}

/**
* @dev Exposes the internal _update function for testing
* @param from_ Address tokens are transferred from
* @param to_ Address tokens are transferred to
* @param amount_ Amount of tokens transferred
*/
function exposed_update(address from_, address to_, uint amount_) public {
_update(from_, to_, amount_);
}

/**
* @dev Exposes the internal _setBlacklistManager function for testing
* @param account_ Address to set privileges for
* @param privileges_ Whether to grant or revoke privileges
*/
function exposed_setBlacklistManager(address account_, bool privileges_)
public
{
_setBlacklistManager(account_, privileges_);
}
}
Copy link

@vendrell46 vendrell46 Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can delete the file if we don't need it anymore

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;

import {LM_ManualExternalPriceSetter_v1} from
"src/modules/logicModule/LM_ManualExternalPriceSetter_v1.sol";
import {IOrchestrator_v1} from
"src/orchestrator/interfaces/IOrchestrator_v1.sol";
import {IAuthorizer_v1} from "@aut/IAuthorizer_v1.sol";

contract LM_ManualExternalPriceSetter_v1_Exposed is
LM_ManualExternalPriceSetter_v1
{
constructor() {}
}
Loading
Loading