CREATE2 callback validation; init code storage contracts
This commit is contained in:
@@ -17,6 +17,7 @@ import {OwnableInternal} from "./OwnableInternal.sol";
|
||||
import {PartyPoolBase} from "./PartyPoolBase.sol";
|
||||
import {PartyPoolMintImpl} from "./PartyPoolMintImpl.sol";
|
||||
import {PartyPoolSwapImpl} from "./PartyPoolSwapImpl.sol";
|
||||
import {IPartyPoolDeployer} from "./IPartyPoolDeployer.sol";
|
||||
|
||||
/// @title PartyPool - LMSR-backed multi-asset pool with LP ERC20 token
|
||||
/// @notice A multi-asset liquidity pool backed by the LMSRStabilized pricing model.
|
||||
@@ -43,7 +44,7 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
|
||||
/// @notice If true, the vault has been disabled by the owner and only burns (withdrawals) are allowed.
|
||||
function killed() external view returns (bool) { return _killed; }
|
||||
|
||||
function wrapperToken() external view returns (NativeWrapper) { return WRAPPER_TOKEN; }
|
||||
function wrapperToken() external view returns (NativeWrapper) { return WRAPPER; }
|
||||
|
||||
/// @notice Liquidity parameter κ (Q64.64) used by the LMSR kernel: b = κ * S(q)
|
||||
/// @dev Pool is constructed with a fixed κ. Clients that previously passed tradeFrac/targetSlippage
|
||||
@@ -80,7 +81,7 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
|
||||
function swapMintImpl() external view returns (PartyPoolSwapImpl) { return SWAP_IMPL; }
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function getToken(uint256 i) external view returns (IERC20) { return _tokens[i]; }
|
||||
function token(uint256 i) external view returns (IERC20) { return _tokens[i]; }
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function numTokens() external view returns (uint256) { return _tokens.length; }
|
||||
@@ -94,61 +95,42 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
|
||||
/// @inheritdoc IPartyPool
|
||||
function LMSR() external view returns (LMSRStabilized.State memory) { return _lmsr; }
|
||||
|
||||
|
||||
/// @param owner_ Admin account that can disable the vault using kill()
|
||||
/// @param name_ LP token name
|
||||
/// @param symbol_ LP token symbol
|
||||
/// @param tokens_ token addresses (n)
|
||||
/// @param kappa_ liquidity parameter κ (Q64.64) used to derive b = κ * S(q)
|
||||
/// @param fees_ per-asset swap fees in ppm (length must equal tokens_.length)
|
||||
/// @param flashFeePpm_ fee in parts-per-million, taken for flash loans
|
||||
/// @param swapImpl_ address of the SwapMint implementation contract
|
||||
/// @param mintImpl_ address of the Mint implementation contract
|
||||
constructor(
|
||||
address owner_,
|
||||
string memory name_,
|
||||
string memory symbol_,
|
||||
IERC20[] memory tokens_,
|
||||
int128 kappa_,
|
||||
uint256[] memory fees_,
|
||||
uint256 flashFeePpm_,
|
||||
uint256 protocolFeePpm_,
|
||||
address protocolFeeAddress_,
|
||||
NativeWrapper wrapperToken_,
|
||||
PartyPoolSwapImpl swapImpl_,
|
||||
PartyPoolMintImpl mintImpl_
|
||||
)
|
||||
PartyPoolBase(wrapperToken_)
|
||||
OwnableExternal(owner_)
|
||||
ERC20External(name_, symbol_)
|
||||
constructor()
|
||||
{
|
||||
require(owner_ != address(0));
|
||||
require(tokens_.length > 1, "Pool: need >1 asset");
|
||||
_tokens = tokens_;
|
||||
KAPPA = kappa_;
|
||||
require(fees_.length == tokens_.length, "Pool: fees length");
|
||||
// validate ppm bounds and assign
|
||||
_fees = new uint256[](fees_.length);
|
||||
for (uint256 i = 0; i < fees_.length; i++) {
|
||||
// Cap all fees at 1%
|
||||
require(fees_[i] < 10_000, "Pool: fee >= 1%");
|
||||
_fees[i] = fees_[i];
|
||||
}
|
||||
require(flashFeePpm_ < 10_000, "Pool: flash fee >= 1%");
|
||||
FLASH_FEE_PPM = flashFeePpm_;
|
||||
require(protocolFeePpm_ < 400_000, "Pool: protocol fee >= 40%");
|
||||
// If the protocolFeePpm_ is set, then also require the fee address to be nonzero
|
||||
require(protocolFeePpm_ == 0 || protocolFeeAddress_ != address(0));
|
||||
PROTOCOL_FEE_PPM = protocolFeePpm_;
|
||||
protocolFeeAddress = protocolFeeAddress_;
|
||||
SWAP_IMPL = swapImpl_;
|
||||
MINT_IMPL = mintImpl_;
|
||||
IPartyPoolDeployer.DeployParams memory p = IPartyPoolDeployer(msg.sender).params();
|
||||
uint256 n = p.tokens.length;
|
||||
require(n > 1, "Pool: need >1 asset");
|
||||
|
||||
uint256 n = tokens_.length;
|
||||
_nonce = p.nonce;
|
||||
WRAPPER = p.wrapper;
|
||||
_name = p.name;
|
||||
_symbol = p.symbol;
|
||||
|
||||
ownableConstructor(p.owner);
|
||||
|
||||
_tokens = p.tokens;
|
||||
KAPPA = p.kappa;
|
||||
require(p.fees.length == p.tokens.length, "Pool: fees length");
|
||||
// validate ppm bounds and assign
|
||||
_fees = new uint256[](p.fees.length);
|
||||
for (uint256 i = 0; i < p.fees.length; i++) {
|
||||
// Cap all fees at 1%
|
||||
require(p.fees[i] < 10_000, "Pool: fee >= 1%");
|
||||
_fees[i] = p.fees[i];
|
||||
}
|
||||
require(p.flashFeePpm < 10_000, "Pool: flash fee >= 1%");
|
||||
FLASH_FEE_PPM = p.flashFeePpm;
|
||||
require(p.protocolFeePpm < 400_000, "Pool: protocol fee >= 40%");
|
||||
// If the p.protocolFeePpm is set, then also require the fee address to be nonzero
|
||||
require(p.protocolFeePpm == 0 || p.protocolFeeAddress != address(0));
|
||||
PROTOCOL_FEE_PPM = p.protocolFeePpm;
|
||||
protocolFeeAddress = p.protocolFeeAddress;
|
||||
SWAP_IMPL = p.swapImpl;
|
||||
MINT_IMPL = p.mintImpl;
|
||||
|
||||
// Initialize token address to index mapping
|
||||
for (uint i = 0; i < n;) {
|
||||
_tokenAddressToIndexPlusOne[tokens_[i]] = i + 1;
|
||||
_tokenAddressToIndexPlusOne[p.tokens[i]] = i + 1;
|
||||
unchecked {i++;}
|
||||
}
|
||||
|
||||
@@ -252,7 +234,8 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
|
||||
uint256 maxAmountIn,
|
||||
int128 limitPrice,
|
||||
uint256 deadline,
|
||||
bool unwrap
|
||||
bool unwrap,
|
||||
bytes memory cbData
|
||||
) external payable native nonReentrant killable returns (uint256 amountIn, uint256 amountOut, uint256 inFee) {
|
||||
require(deadline == 0 || block.timestamp <= deadline, "swap: deadline exceeded");
|
||||
|
||||
@@ -264,24 +247,7 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
|
||||
IERC20 tokenIn = _tokens[inputTokenIndex];
|
||||
IERC20 tokenOut = _tokens[outputTokenIndex];
|
||||
|
||||
if (fundingSelector == Funding.APPROVALS)
|
||||
// Regular ERC20 permit of the pool to move the tokens
|
||||
_receiveTokenFrom(payer, tokenIn, totalTransferAmount);
|
||||
else if (fundingSelector == Funding.PREFUNDING) {
|
||||
require(limitPrice==0, 'Prefunding cannot be used with a limit price');
|
||||
uint256 balance = tokenIn.balanceOf(address(this));
|
||||
uint256 prevBalance = _cachedUintBalances[inputTokenIndex] + _protocolFeesOwed[inputTokenIndex];
|
||||
require( balance - prevBalance == totalTransferAmount, 'Incorrect prefunding amount');
|
||||
}
|
||||
else {
|
||||
// Callback-style funding mechanism
|
||||
uint256 startingBalance = tokenIn.balanceOf(address(this));
|
||||
bytes memory data = abi.encodeWithSelector(fundingSelector, tokenIn, totalTransferAmount);
|
||||
// Invoke the payer callback; no return value expected (reverts on failure)
|
||||
Address.functionCall(payer, data);
|
||||
uint256 endingBalance = tokenIn.balanceOf(address(this));
|
||||
require(endingBalance-startingBalance == totalTransferAmount, 'Insufficient funds');
|
||||
}
|
||||
_receiveTokenFrom(payer, fundingSelector, inputTokenIndex, tokenIn, totalTransferAmount, limitPrice, cbData);
|
||||
|
||||
// Compute on-chain balances as: onchain = cached + owed (+/- transfer)
|
||||
uint256 balIAfter = _cachedUintBalances[inputTokenIndex] + _protocolFeesOwed[inputTokenIndex] + totalTransferAmount;
|
||||
@@ -369,22 +335,26 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
|
||||
/// @inheritdoc IPartyPool
|
||||
function swapToLimit(
|
||||
address payer,
|
||||
bytes4 fundingSelector,
|
||||
address receiver,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
int128 limitPrice,
|
||||
uint256 deadline,
|
||||
bool unwrap
|
||||
bool unwrap,
|
||||
bytes memory cbData
|
||||
) external payable returns (uint256 amountInUsed, uint256 amountOut, uint256 inFee) {
|
||||
bytes memory data = abi.encodeWithSelector(
|
||||
PartyPoolSwapImpl.swapToLimit.selector,
|
||||
payer,
|
||||
fundingSelector,
|
||||
receiver,
|
||||
inputTokenIndex,
|
||||
outputTokenIndex,
|
||||
limitPrice,
|
||||
deadline,
|
||||
unwrap,
|
||||
cbData,
|
||||
_pairFeePpm(inputTokenIndex, outputTokenIndex),
|
||||
PROTOCOL_FEE_PPM
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user