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

Test/new exit contribution #557

Merged
merged 10 commits into from
Nov 29, 2024
71 changes: 66 additions & 5 deletions 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;
}

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

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 = scaledAmountIn / tokenPrecisionMultipliers[tokenIn];
return amountIn;
}
Expand Down Expand Up @@ -196,8 +210,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;
Expand All @@ -213,9 +240,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 = scaledAmountInWithExitContribution / tokenPrecisionMultipliers[tokenIn];
return amountIn;
}

Expand Down Expand Up @@ -289,6 +333,27 @@ 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 Calculate the scaledAmountIn of tokenIn for a given scaledAmountOut of tokenOut
* @param exchange The pool exchange to operate on
Expand All @@ -306,8 +371,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 @@ -340,8 +403,6 @@ contract BancorExchangeProvider is IExchangeProvider, IBancorExchangeProvider, B
exchange.reserveRatio,
scaledAmountIn
);
// apply exit contribution
scaledAmountOut = (scaledAmountOut * (MAX_WEIGHT - exchange.exitContribution)) / MAX_WEIGHT;
}
}

Expand Down
Loading
Loading