Calldata passed to the 0x Settler calls will be incorrect as the action signatures (action to take on 0x Settler) are incorrect and not the same as the ones 0x Settler is familiar with.
Vulnerability Details
In the library above, the different actions have function signatures that specify which action should be taken in 0x Settler but these function signatures are wrong and when encoded along with the call to 0x Settler will result in no action being taken thus failing swaps for example.
These function signatures for the external call to the 0x Settler are wrong and will lead to failing swaps in the 99% case and wrong function calls in 0x Settler in the 1% case.
For example, the UNISWAPV3_VIP action type on 0x Settler has the function selector: 0x22ce6ede not 0x9ebf8e8d as the Alchemix team expects it to be. This will force uniswap v3 swap calldata transactions to fail.
This is also the case for all the function selectors in this library as they are wrong.
For reference please see the 0x Settler functions and the selectors they correspond to onchain from the 0x Settler address here: https://etherscan.io/address/0x70bf6634ee8cb27d04478f184b9b8bb13e5f4710#code
For a detailed code view of the 0x Settler contract, look here: https://vscode.blockscan.com/ethereum/0x70bf6634ee8cb27d04478f184b9b8bb13e5f4710
When you get the function selector for the UNISWAPV3_VIP function from the 0x Settler address it is computed as:
Thus, the function signature of the action is 0x22ce6ede and not 0x9ebf8e8d
The same issue affects all other action signatures below:
Impact Details
Swap calls to the 0x Settler contract will not work as the function signatures of the actions will not be found in the contract and the low level calls to the 0x Settler will be successful but the function will not execute.
Also, on another note the EXECUTE_SELECTOR and EXECUTE_META_TXN_SELECTOR are also incorrect but I have decided to highlight it in this single submission too so I don't mistakenly duplicate myself.
struct TokenPermissions {
// ERC20 token address
address token;
// the maximum amount that can be spent
uint256 amount;
}
/// @notice The signed permit message for a single token transfer
struct PermitTransferFrom {
TokenPermissions permitted;
// a unique value for every token owner's signature to prevent signature replays
uint256 nonce;
// deadline on the permit signature
uint256 deadline;
}
function UNISWAPV3_VIP(
address recipient,
bytes memory path,
ISignatureTransfer.PermitTransferFrom memory permit,
bytes memory sig,
uint256 amountOutMin
) external;