per-asset fees
This commit is contained in:
@@ -8,6 +8,7 @@ import {IPartyPool} from "./IPartyPool.sol";
|
||||
import {NativeWrapper} from "./NativeWrapper.sol";
|
||||
import {LMSRStabilized} from "./LMSRStabilized.sol";
|
||||
import {PartyPoolBase} from "./PartyPoolBase.sol";
|
||||
import {IERC3156FlashBorrower} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC3156FlashBorrower.sol";
|
||||
|
||||
/// @title PartyPoolSwapMintImpl - Implementation contract for swapMint and burnSwap functions
|
||||
/// @notice This contract contains the swapMint and burnSwap implementation that will be called via delegatecall
|
||||
@@ -19,6 +20,48 @@ contract PartyPoolSwapImpl is PartyPoolBase {
|
||||
|
||||
constructor(NativeWrapper wrapper_) PartyPoolBase(wrapper_) {}
|
||||
|
||||
bytes32 internal constant FLASH_CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
|
||||
|
||||
function flashLoan(
|
||||
IERC3156FlashBorrower receiver,
|
||||
address tokenAddr,
|
||||
uint256 amount,
|
||||
bytes calldata data,
|
||||
uint256 flashFeePpm,
|
||||
uint256 protocolFeePpm
|
||||
) external nonReentrant killable returns (bool) {
|
||||
IERC20 token = IERC20(tokenAddr);
|
||||
require(amount <= token.balanceOf(address(this)), "flash: amount > balance");
|
||||
uint256 tokenIndex = _tokenAddressToIndexPlusOne[token];
|
||||
require(tokenIndex != 0, 'flash: token not in pool');
|
||||
tokenIndex -= 1;
|
||||
(uint256 flashFee, ) = _computeFee(amount, flashFeePpm);
|
||||
|
||||
// Compute protocol share of flash fee
|
||||
uint256 protoShare = 0;
|
||||
if (protocolFeePpm > 0 && flashFee > 0) {
|
||||
protoShare = (flashFee * protocolFeePpm) / 1_000_000; // floor
|
||||
if (protoShare > 0) {
|
||||
_protocolFeesOwed[tokenIndex] += protoShare;
|
||||
}
|
||||
}
|
||||
|
||||
_sendTokenTo(token, address(receiver), amount, false);
|
||||
require(
|
||||
receiver.onFlashLoan(msg.sender, address(token), amount, flashFee, data) == FLASH_CALLBACK_SUCCESS,
|
||||
'flash: callback'
|
||||
);
|
||||
_receiveTokenFrom(address(receiver), token, amount + flashFee);
|
||||
|
||||
// Update cached balance for the borrowed token
|
||||
uint256 balAfter = token.balanceOf(address(this));
|
||||
require(balAfter >= _protocolFeesOwed[tokenIndex], "balance < protocol owed");
|
||||
_cachedUintBalances[tokenIndex] = balAfter - _protocolFeesOwed[tokenIndex];
|
||||
|
||||
emit IPartyPool.Flash(msg.sender, receiver, token, amount, flashFee - protoShare, protoShare);
|
||||
return true;
|
||||
}
|
||||
|
||||
function swapToLimitAmounts(
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
@@ -27,7 +70,7 @@ contract PartyPoolSwapImpl is PartyPoolBase {
|
||||
int128 kappa,
|
||||
int128[] memory qInternal,
|
||||
uint256 swapFeePpm
|
||||
) external pure returns (uint256 amountIn, uint256 amountOut, uint256 fee) {
|
||||
) external pure returns (uint256 amountIn, uint256 amountOut, uint256 inFee) {
|
||||
// Compute internal maxima at the price limit
|
||||
(int128 amountInInternal, int128 amountOutInternal) = LMSRStabilized.swapAmountsForPriceLimit(
|
||||
bases.length, kappa, qInternal,
|
||||
@@ -37,11 +80,11 @@ contract PartyPoolSwapImpl is PartyPoolBase {
|
||||
uint256 amountInUintNoFee = _internalToUintCeil(amountInInternal, bases[inputTokenIndex]);
|
||||
require(amountInUintNoFee > 0, "swapToLimit: input zero");
|
||||
|
||||
fee = 0;
|
||||
inFee = 0;
|
||||
amountIn = amountInUintNoFee;
|
||||
if (swapFeePpm > 0) {
|
||||
fee = _ceilFee(amountInUintNoFee, swapFeePpm);
|
||||
amountIn += fee;
|
||||
inFee = _ceilFee(amountInUintNoFee, swapFeePpm);
|
||||
amountIn += inFee;
|
||||
}
|
||||
|
||||
amountOut = _internalToUintFloor(amountOutInternal, bases[outputTokenIndex]);
|
||||
@@ -59,7 +102,7 @@ contract PartyPoolSwapImpl is PartyPoolBase {
|
||||
bool unwrap,
|
||||
uint256 swapFeePpm,
|
||||
uint256 protocolFeePpm
|
||||
) external payable native killable nonReentrant returns (uint256 amountInUsed, uint256 amountOut, uint256 fee) {
|
||||
) external payable native killable nonReentrant returns (uint256 amountInUsed, uint256 amountOut, uint256 inFee) {
|
||||
uint256 n = _tokens.length;
|
||||
require(inputTokenIndex < n && outputTokenIndex < n, "swapToLimit: idx");
|
||||
require(limitPrice > int128(0), "swapToLimit: limit <= 0");
|
||||
|
||||
Reference in New Issue
Block a user