Conversation
src/FinalAutoRouting.sol
Outdated
| // ============================================================================ | ||
|
|
||
| modifier onlyAuthorizedCaller() { | ||
| if (!authorizedCallers[msg.sender] && msg.sender != owner()) { |
There was a problem hiding this comment.
Can we restrict this to admin and LTM? So our role permissions setup is similar to other LAT contracts. Do you foresee that that we would have other authorized callers?
There was a problem hiding this comment.
We can introudcue kinda role management style
There was a problem hiding this comment.
it's really depends on how we gonna use that far contract.
Do you see any other use case beside that ltm usage?
There was a problem hiding this comment.
I guess the original comment is stale -- I do think it would be good to keep the option open for other contracts to call. WM may use it when settling user withdrawals (undecided as of now)
The role management style makes sense, as its in-line with the pattern of other contracts
But if we do the lib + storage method, we wouldn't need any auth on the swap functions (in lib) right? Only the management functions that control the FAR state (in storage contract) would need something like DEFAULT_ADMIN_ROLE?
|
Hey, looks great overall!! The one consideration that I have structurally is that future contracts like WM and potentially others would have to maintain separate (but synced) state of FAR. So I wonder if it's a good idea to split the FAR into:
The implications of this change would then be --
Overall, looking to reduce complexity + improve deployment/dev experience. Lemme know your thoughts! |
- Improve ETH transfer safety in emergencyWithdraw with proper error handling - Clean up comments and imports in FinalAutoRouting - Update LiquidTokenManager with latest implementation - Remove deprecated TokenSwap test directory and related test files
…payable address type for LiquidTokenManager
src/FinalAutoRouting.sol
Outdated
| if (poolAddresses.length != curveInterfaces.length) | ||
| revert InvalidParameter("interfaceArrays"); | ||
|
|
||
| // Configure supported tokens |
There was a problem hiding this comment.
Can we use the same supported tokens from LTM? Since there can only be swaps between those tokens (we remain agnostic to intermediate tokens).
Because maintaining another registry here can create a new point of human error
src/FinalAutoRouting.sol
Outdated
| require(msg.sender == address(this), "Internal only"); | ||
|
|
||
| // Check quote freshness | ||
| if (block.timestamp - quote.timestamp > QUOTE_MAX_AGE) |
There was a problem hiding this comment.
Does the manager need to specifically watch out for this revert and adjust its calls accordingly (like splitting a heavy call into multiple smaller attempts, etc.)?
src/FinalAutoRouting.sol
Outdated
| uint256 minAmountOut | ||
| ) private returns (uint256 amountOut) { | ||
| if (params.tokenIn == address(WETH) && params.tokenOut == OSETH) { | ||
| return _performWETHToOsETHSwap(params, minAmountOut); |
There was a problem hiding this comment.
Is there a reason to specifically handle WETH -> osETH here instead of having the user do a multi-step swap? In case we don’t handle WETH -> osETH here, then can we remove the entire category of Protocol.MultiHop right? Since any other multi-hop is handled with (Protocol.Uniswap && route.isMultiHop)
Perhaps we can instead recommend WETH -> rETH -> osETH to the manager in its config for when it sets up RouteConfigs for AutoSwaps and put responsibility on the caller if they choose to use swapAssets for WETH <> osETH
src/FinalAutoRouting.sol
Outdated
| * @param params Swap parameters | ||
| * @return amountOut Amount of output tokens received by caller | ||
| */ | ||
| function swapAssets( |
There was a problem hiding this comment.
I think the params.minAmountOut provided by the user is not actually used right?
- Quoter: checks quote -> adds buffer and calculates new minAmountOut from quote -> attempts swap -> success if outputAmount >= new minAmountOut
- Fallback: Directly calculates minAmountOut from SlippageConfig
If so, then I feel that we can give the caller the autonomy to choose their slippage without configs/fallbacks:
- Quoter: checks quote -> if quote >= params.minAmountOut -> adds buffer and calculates new minAmountOut from quote -> attempts swap -> success if outputAmount >= new minAmountOut
- Fallback: None, revert because caller has been too strict with their slippage expectations
Note 1: If this suggestion is taken, we can consider removing SlippageConfig altogether and instead add slippage uint256 slippageBps to RouteConfig.
Note 2: If both suggestions from L530 and Note 1 are taken, we can consider removing AssetType altogether. The bridgeAsset can be taken in the initialization params directly OR we can add unitOfAccount as an immutable constant on the LiquidToken contract and use that (this actually helps in a few ways for the backend/manager too)
src/FinalAutoRouting.sol
Outdated
| ); | ||
| } | ||
|
|
||
| if (amountOut < params.minAmountOut) revert InsufficientOutput(); |
There was a problem hiding this comment.
What are your thoughts on not using params.minAmountOut at all and relying on the pre-existing config. So this function can v simple for the manager to call and is truly “auto”
src/FinalAutoRouting.sol
Outdated
| return amountOut; | ||
| } | ||
|
|
||
| // 3) Bridge route |
There was a problem hiding this comment.
Nice, this is smart!
src/FinalAutoRouting.sol
Outdated
| * @param password password for safety | ||
| * @return amountOut Amount of tokens received | ||
| */ | ||
| function executeBackendSwap( |
There was a problem hiding this comment.
Can we add minAmountOut here and check amountOut >= minAmountOut?
src/FinalAutoRouting.sol
Outdated
| IERC20(tokenIn).safeApprove(dex, 0); | ||
| } | ||
|
|
||
| emit BackendSwapExecuted( |
There was a problem hiding this comment.
Can we include gasUsed like we did in AssetSwapped? Would be nice for backend to evaluate a given DEX over time and judge when to use it
src/FinalAutoRouting.sol
Outdated
| // ============================================================================ | ||
|
|
||
| modifier onlyAuthorizedCaller() { | ||
| if (!authorizedCallers[msg.sender] && msg.sender != owner()) { |
There was a problem hiding this comment.
I guess the original comment is stale -- I do think it would be good to keep the option open for other contracts to call. WM may use it when settling user withdrawals (undecided as of now)
The role management style makes sense, as its in-line with the pattern of other contracts
But if we do the lib + storage method, we wouldn't need any auth on the swap functions (in lib) right? Only the management functions that control the FAR state (in storage contract) would need something like DEFAULT_ADMIN_ROLE?
|
|
||
| // Swap using FAR - for every tokenIn swap to corresponding tokenOut | ||
| for (uint256 i = 0; i < assetsLength; i++) { | ||
| address tokenIn = address(assetsToSwap[i]); |
There was a problem hiding this comment.
Note that tokenIn must be a supported token and have a corresponding supported strategy
|
Hey putting this PR into draft as we are splitting it up into LTM integration and a new repo. Will keep it open for reference and close it entirely after merge of v2-core to dev |
No description provided.