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

Fix Review #2

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
100 changes: 88 additions & 12 deletions mento-core/contracts/goodDollar/BancorExchangeProvider.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
) external view virtual returns (uint256 amountOut) {
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledAmountIn = amountIn * tokenPrecisionMultipliers[tokenIn];

if (tokenIn == exchange.tokenAddress) {
require(scaledAmountIn < exchange.tokenSupply, "amountIn is greater than tokenSupply");
// apply exit contribution
scaledAmountIn = (scaledAmountIn * (MAX_WEIGHT - exchange.exitContribution)) / MAX_WEIGHT;
}

Comment on lines +125 to +131
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

Comment on lines +125 to +131
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

uint256 scaledAmountOut = _getScaledAmountOut(exchange, tokenIn, tokenOut, scaledAmountIn);
amountOut = scaledAmountOut / tokenPrecisionMultipliers[tokenOut];
return amountOut;
Expand All @@ -137,19 +144,27 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledAmountOut = amountOut * tokenPrecisionMultipliers[tokenOut];
uint256 scaledAmountIn = _getScaledAmountIn(exchange, tokenIn, tokenOut, scaledAmountOut);
amountIn = scaledAmountIn / tokenPrecisionMultipliers[tokenIn];

if (tokenIn == exchange.tokenAddress) {
// apply exit contribution
scaledAmountIn = (scaledAmountIn * MAX_WEIGHT) / (MAX_WEIGHT - exchange.exitContribution);
require(scaledAmountIn < exchange.tokenSupply, "amountIn is greater than tokenSupply");
}

Comment on lines +147 to +153
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

Comment on lines +147 to +153
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

amountIn = divAndRoundUp(scaledAmountIn, tokenPrecisionMultipliers[tokenIn]);
return amountIn;
}

/// @inheritdoc IBancorExchangeProvider
function currentPrice(bytes32 exchangeId) public view returns (uint256 price) {
// calculates: reserveBalance / (tokenSupply * reserveRatio)
require(exchanges[exchangeId].reserveAsset != address(0), "Exchange does not exist");
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledReserveRatio = uint256(exchange.reserveRatio) * 1e10;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#560.

Fixes issues: #23

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#560.

Fixes issues: #23

UD60x18 denominator = wrap(exchange.tokenSupply).mul(wrap(scaledReserveRatio));
price = unwrap(wrap(exchange.reserveBalance).div(denominator));
return price;
uint256 priceScaled = unwrap(wrap(exchange.reserveBalance).div(denominator));

price = priceScaled / tokenPrecisionMultipliers[exchange.reserveAsset];
Comment on lines +165 to +167
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#560.

Fixes issues: #23

Comment on lines +165 to +167
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#560.

Fixes issues: #23

}

/* ============================================================ */
Expand All @@ -165,9 +180,9 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B

/// @inheritdoc IBancorExchangeProvider
function setReserve(address _reserve) public onlyOwner {
require(address(_reserve) != address(0), "Reserve address must be set");
require(_reserve != address(0), "Reserve address must be set");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#545.

Fixes issues: #79

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#545.

Fixes issues: #79

reserve = IReserve(_reserve);
emit ReserveUpdated(address(_reserve));
emit ReserveUpdated(_reserve);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#545.

Fixes issues: #79

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#545.

Fixes issues: #79

}

/// @inheritdoc IBancorExchangeProvider
Expand Down Expand Up @@ -197,8 +212,21 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
) public virtual onlyBroker returns (uint256 amountOut) {
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledAmountIn = amountIn * tokenPrecisionMultipliers[tokenIn];
uint256 exitContribution = 0;

if (tokenIn == exchange.tokenAddress) {
require(scaledAmountIn < exchange.tokenSupply, "amountIn is greater than tokenSupply");
// apply exit contribution
exitContribution = (scaledAmountIn * exchange.exitContribution) / MAX_WEIGHT;
scaledAmountIn -= exitContribution;
}

Comment on lines +215 to +223
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

Comment on lines +215 to +223
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

uint256 scaledAmountOut = _getScaledAmountOut(exchange, tokenIn, tokenOut, scaledAmountIn);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

executeSwap(exchangeId, tokenIn, scaledAmountIn, scaledAmountOut);
if (exitContribution > 0) {
_accountExitContribution(exchangeId, exitContribution);
}
Comment on lines +227 to +229
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

Comment on lines +227 to +229
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64


amountOut = scaledAmountOut / tokenPrecisionMultipliers[tokenOut];
return amountOut;
Expand All @@ -214,9 +242,26 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledAmountOut = amountOut * tokenPrecisionMultipliers[tokenOut];
uint256 scaledAmountIn = _getScaledAmountIn(exchange, tokenIn, tokenOut, scaledAmountOut);

uint256 exitContribution = 0;
uint256 scaledAmountInWithExitContribution = scaledAmountIn;

if (tokenIn == exchange.tokenAddress) {
// apply exit contribution
scaledAmountInWithExitContribution = (scaledAmountIn * MAX_WEIGHT) / (MAX_WEIGHT - exchange.exitContribution);
require(
scaledAmountInWithExitContribution < exchange.tokenSupply,
"amountIn required is greater than tokenSupply"
);
exitContribution = scaledAmountInWithExitContribution - scaledAmountIn;
}

Comment on lines +245 to +258
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

Comment on lines +245 to +258
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

executeSwap(exchangeId, tokenIn, scaledAmountIn, scaledAmountOut);
if (exitContribution > 0) {
_accountExitContribution(exchangeId, exitContribution);
}
Comment on lines +260 to +262
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

Comment on lines +260 to +262
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64


amountIn = scaledAmountIn / tokenPrecisionMultipliers[tokenIn];
amountIn = divAndRoundUp(scaledAmountInWithExitContribution, tokenPrecisionMultipliers[tokenIn]);
return amountIn;
}

Expand All @@ -242,6 +287,9 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
tokenPrecisionMultipliers[exchange.reserveAsset] = 10 ** (18 - uint256(reserveAssetDecimals));
tokenPrecisionMultipliers[exchange.tokenAddress] = 10 ** (18 - uint256(tokenDecimals));

exchange.reserveBalance = exchange.reserveBalance * tokenPrecisionMultipliers[exchange.reserveAsset];
exchange.tokenSupply = exchange.tokenSupply * tokenPrecisionMultipliers[exchange.tokenAddress];

exchanges[exchangeId] = exchange;
exchangeIds.push(exchangeId);
emit ExchangeCreated(exchangeId, exchange.reserveAsset, exchange.tokenAddress);
Expand All @@ -262,7 +310,7 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B

function _setExitContribution(bytes32 exchangeId, uint32 exitContribution) internal {
require(exchanges[exchangeId].reserveAsset != address(0), "Exchange does not exist");
require(exitContribution <= MAX_WEIGHT, "Exit contribution is too high");
require(exitContribution < MAX_WEIGHT, "Exit contribution is too high");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#549.

Fixes issues: #55

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#549.

Fixes issues: #55


PoolExchange storage exchange = exchanges[exchangeId];
exchange.exitContribution = exitContribution;
Expand Down Expand Up @@ -290,6 +338,37 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
exchanges[exchangeId].tokenSupply = exchange.tokenSupply;
}

/**
* @notice Accounting of exit contribution on a swap.
* @dev Accounting of exit contribution without changing the current price of an exchange.
* this is done by updating the reserve ratio and subtracting the exit contribution from the token supply.
* Formula: newRatio = (Supply * oldRatio) / (Supply - exitContribution)
* @param exchangeId The ID of the pool
* @param exitContribution The amount of the token to be removed from the pool, scaled to 18 decimals
*/
function _accountExitContribution(bytes32 exchangeId, uint256 exitContribution) internal {
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledReserveRatio = uint256(exchange.reserveRatio) * 1e10;
UD60x18 nominator = wrap(exchange.tokenSupply).mul(wrap(scaledReserveRatio));
UD60x18 denominator = wrap(exchange.tokenSupply - exitContribution);
UD60x18 newRatioScaled = nominator.div(denominator);

uint256 newRatio = unwrap(newRatioScaled) / 1e10;

exchanges[exchangeId].reserveRatio = uint32(newRatio);
exchanges[exchangeId].tokenSupply -= exitContribution;
}

Comment on lines +341 to +361
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

Comment on lines +341 to +361
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#557.

Fixes issues: #36, #64

/**
* @notice Division and rounding up if there is a remainder
* @param a The dividend
* @param b The divisor
* @return The result of the division rounded up
*/
function divAndRoundUp(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / b) + (a % b > 0 ? 1 : 0);
}

/**
* @notice Calculate the scaledAmountIn of tokenIn for a given scaledAmountOut of tokenOut
* @param exchange The pool exchange to operate on
Expand All @@ -307,8 +386,6 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
if (tokenIn == exchange.reserveAsset) {
scaledAmountIn = fundCost(exchange.tokenSupply, exchange.reserveBalance, exchange.reserveRatio, scaledAmountOut);
} else {
// apply exit contribution
scaledAmountOut = (scaledAmountOut * MAX_WEIGHT) / (MAX_WEIGHT - exchange.exitContribution);
scaledAmountIn = saleCost(exchange.tokenSupply, exchange.reserveBalance, exchange.reserveRatio, scaledAmountOut);
}
}
Expand Down Expand Up @@ -341,8 +418,6 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
exchange.reserveRatio,
scaledAmountIn
);
// apply exit contribution
scaledAmountOut = (scaledAmountOut * (MAX_WEIGHT - exchange.exitContribution)) / MAX_WEIGHT;
}
}

Expand All @@ -362,6 +437,7 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
require(exchange.reserveRatio > 1, "Reserve ratio is too low");
require(exchange.reserveRatio <= MAX_WEIGHT, "Reserve ratio is too high");
require(exchange.exitContribution <= MAX_WEIGHT, "Exit contribution is too high");
require(exchange.reserveBalance > 0, "Reserve balance must be greater than 0");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#558.

Fixes issues: #57

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change related to mento-protocol/mento-core#558.

Fixes issues: #57

}

/**
Expand Down
192 changes: 192 additions & 0 deletions mento-core/contracts/goodDollar/BancorExchangeProvider.sol.rej
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
diff a/mento-core/contracts/goodDollar/BancorExchangeProvider.sol b/mento-core/contracts/goodDollar/BancorExchangeProvider.sol (rejected hunks)
@@ -122,6 +122,13 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
) external view virtual returns (uint256 amountOut) {
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledAmountIn = amountIn * tokenPrecisionMultipliers[tokenIn];
+
+ if (tokenIn == exchange.tokenAddress) {
+ require(scaledAmountIn < exchange.tokenSupply, "amountIn is greater than tokenSupply");
+ // apply exit contribution
+ scaledAmountIn = (scaledAmountIn * (MAX_WEIGHT - exchange.exitContribution)) / MAX_WEIGHT;
+ }
+
uint256 scaledAmountOut = _getScaledAmountOut(exchange, tokenIn, tokenOut, scaledAmountIn);
amountOut = scaledAmountOut / tokenPrecisionMultipliers[tokenOut];
return amountOut;
@@ -137,19 +144,27 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledAmountOut = amountOut * tokenPrecisionMultipliers[tokenOut];
uint256 scaledAmountIn = _getScaledAmountIn(exchange, tokenIn, tokenOut, scaledAmountOut);
- amountIn = scaledAmountIn / tokenPrecisionMultipliers[tokenIn];
+
+ if (tokenIn == exchange.tokenAddress) {
+ // apply exit contribution
+ scaledAmountIn = (scaledAmountIn * MAX_WEIGHT) / (MAX_WEIGHT - exchange.exitContribution);
+ require(scaledAmountIn < exchange.tokenSupply, "amountIn is greater than tokenSupply");
+ }
+
+ amountIn = divAndRoundUp(scaledAmountIn, tokenPrecisionMultipliers[tokenIn]);
return amountIn;
}

/// @inheritdoc IBancorExchangeProvider
function currentPrice(bytes32 exchangeId) public view returns (uint256 price) {
// calculates: reserveBalance / (tokenSupply * reserveRatio)
- require(exchanges[exchangeId].reserveAsset != address(0), "Exchange does not exist");
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledReserveRatio = uint256(exchange.reserveRatio) * 1e10;
+
UD60x18 denominator = wrap(exchange.tokenSupply).mul(wrap(scaledReserveRatio));
- price = unwrap(wrap(exchange.reserveBalance).div(denominator));
- return price;
+ uint256 priceScaled = unwrap(wrap(exchange.reserveBalance).div(denominator));
+
+ price = priceScaled / tokenPrecisionMultipliers[exchange.reserveAsset];
}

/* ============================================================ */
@@ -165,9 +180,9 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B

/// @inheritdoc IBancorExchangeProvider
function setReserve(address _reserve) public onlyOwner {
- require(address(_reserve) != address(0), "Reserve address must be set");
+ require(_reserve != address(0), "Reserve address must be set");
reserve = IReserve(_reserve);
- emit ReserveUpdated(address(_reserve));
+ emit ReserveUpdated(_reserve);
}

/// @inheritdoc IBancorExchangeProvider
@@ -197,8 +212,21 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
) public virtual onlyBroker returns (uint256 amountOut) {
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledAmountIn = amountIn * tokenPrecisionMultipliers[tokenIn];
+ uint256 exitContribution = 0;
+
+ if (tokenIn == exchange.tokenAddress) {
+ require(scaledAmountIn < exchange.tokenSupply, "amountIn is greater than tokenSupply");
+ // apply exit contribution
+ exitContribution = (scaledAmountIn * exchange.exitContribution) / MAX_WEIGHT;
+ scaledAmountIn -= exitContribution;
+ }
+
uint256 scaledAmountOut = _getScaledAmountOut(exchange, tokenIn, tokenOut, scaledAmountIn);
+
executeSwap(exchangeId, tokenIn, scaledAmountIn, scaledAmountOut);
+ if (exitContribution > 0) {
+ _accountExitContribution(exchangeId, exitContribution);
+ }

amountOut = scaledAmountOut / tokenPrecisionMultipliers[tokenOut];
return amountOut;
@@ -214,9 +242,26 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
PoolExchange memory exchange = getPoolExchange(exchangeId);
uint256 scaledAmountOut = amountOut * tokenPrecisionMultipliers[tokenOut];
uint256 scaledAmountIn = _getScaledAmountIn(exchange, tokenIn, tokenOut, scaledAmountOut);
+
+ uint256 exitContribution = 0;
+ uint256 scaledAmountInWithExitContribution = scaledAmountIn;
+
+ if (tokenIn == exchange.tokenAddress) {
+ // apply exit contribution
+ scaledAmountInWithExitContribution = (scaledAmountIn * MAX_WEIGHT) / (MAX_WEIGHT - exchange.exitContribution);
+ require(
+ scaledAmountInWithExitContribution < exchange.tokenSupply,
+ "amountIn required is greater than tokenSupply"
+ );
+ exitContribution = scaledAmountInWithExitContribution - scaledAmountIn;
+ }
+
executeSwap(exchangeId, tokenIn, scaledAmountIn, scaledAmountOut);
+ if (exitContribution > 0) {
+ _accountExitContribution(exchangeId, exitContribution);
+ }

- amountIn = scaledAmountIn / tokenPrecisionMultipliers[tokenIn];
+ amountIn = divAndRoundUp(scaledAmountInWithExitContribution, tokenPrecisionMultipliers[tokenIn]);
return amountIn;
}

@@ -242,6 +287,9 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
tokenPrecisionMultipliers[exchange.reserveAsset] = 10 ** (18 - uint256(reserveAssetDecimals));
tokenPrecisionMultipliers[exchange.tokenAddress] = 10 ** (18 - uint256(tokenDecimals));

+ exchange.reserveBalance = exchange.reserveBalance * tokenPrecisionMultipliers[exchange.reserveAsset];
+ exchange.tokenSupply = exchange.tokenSupply * tokenPrecisionMultipliers[exchange.tokenAddress];
+
exchanges[exchangeId] = exchange;
exchangeIds.push(exchangeId);
emit ExchangeCreated(exchangeId, exchange.reserveAsset, exchange.tokenAddress);
@@ -262,7 +310,7 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B

function _setExitContribution(bytes32 exchangeId, uint32 exitContribution) internal {
require(exchanges[exchangeId].reserveAsset != address(0), "Exchange does not exist");
- require(exitContribution <= MAX_WEIGHT, "Exit contribution is too high");
+ require(exitContribution < MAX_WEIGHT, "Exit contribution is too high");

PoolExchange storage exchange = exchanges[exchangeId];
exchange.exitContribution = exitContribution;
@@ -290,6 +338,37 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
exchanges[exchangeId].tokenSupply = exchange.tokenSupply;
}

+ /**
+ * @notice Accounting of exit contribution on a swap.
+ * @dev Accounting of exit contribution without changing the current price of an exchange.
+ * this is done by updating the reserve ratio and subtracting the exit contribution from the token supply.
+ * Formula: newRatio = (Supply * oldRatio) / (Supply - exitContribution)
+ * @param exchangeId The ID of the pool
+ * @param exitContribution The amount of the token to be removed from the pool, scaled to 18 decimals
+ */
+ function _accountExitContribution(bytes32 exchangeId, uint256 exitContribution) internal {
+ PoolExchange memory exchange = getPoolExchange(exchangeId);
+ uint256 scaledReserveRatio = uint256(exchange.reserveRatio) * 1e10;
+ UD60x18 nominator = wrap(exchange.tokenSupply).mul(wrap(scaledReserveRatio));
+ UD60x18 denominator = wrap(exchange.tokenSupply - exitContribution);
+ UD60x18 newRatioScaled = nominator.div(denominator);
+
+ uint256 newRatio = unwrap(newRatioScaled) / 1e10;
+
+ exchanges[exchangeId].reserveRatio = uint32(newRatio);
+ exchanges[exchangeId].tokenSupply -= exitContribution;
+ }
+
+ /**
+ * @notice Division and rounding up if there is a remainder
+ * @param a The dividend
+ * @param b The divisor
+ * @return The result of the division rounded up
+ */
+ function divAndRoundUp(uint256 a, uint256 b) internal pure returns (uint256) {
+ return (a / b) + (a % b > 0 ? 1 : 0);
+ }
+
/**
* @notice Calculate the scaledAmountIn of tokenIn for a given scaledAmountOut of tokenOut
* @param exchange The pool exchange to operate on
@@ -307,8 +386,6 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
if (tokenIn == exchange.reserveAsset) {
scaledAmountIn = fundCost(exchange.tokenSupply, exchange.reserveBalance, exchange.reserveRatio, scaledAmountOut);
} else {
- // apply exit contribution
- scaledAmountOut = (scaledAmountOut * MAX_WEIGHT) / (MAX_WEIGHT - exchange.exitContribution);
scaledAmountIn = saleCost(exchange.tokenSupply, exchange.reserveBalance, exchange.reserveRatio, scaledAmountOut);
}
}
@@ -341,8 +418,6 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
exchange.reserveRatio,
scaledAmountIn
);
- // apply exit contribution
- scaledAmountOut = (scaledAmountOut * (MAX_WEIGHT - exchange.exitContribution)) / MAX_WEIGHT;
}
}

@@ -362,6 +437,7 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
require(exchange.reserveRatio > 1, "Reserve ratio is too low");
require(exchange.reserveRatio <= MAX_WEIGHT, "Reserve ratio is too high");
require(exchange.exitContribution <= MAX_WEIGHT, "Exit contribution is too high");
+ require(exchange.reserveBalance > 0, "Reserve balance must be greater than 0");
}

/**
Loading