MagpieRouterV3

The MagpieRouterV3 contract is designed to facilitate token swaps. It inherits from Ownable2Step and Pausable contracts, ensuring controlled access and the ability to pause operations. The contract utilizes various libraries like Address, LibAsset, and LibRouter to handle different asset types and provide utility functions. It includes custom errors and an enums for different command actions, such as calls, approvals, transfers, and balance checks. Key features include functions for updating internal callers and bridge addresses, executing multiple delegate calls in a single transaction, and handling UniswapV3 swap callbacks. The contract also supports various swap operations, including those requiring signatures from Magpie and user, and provides functions for estimating gas, handling permits, and transferring affiliate fees. Additionally, it includes comprehensive command execution functions for calls, approvals, transfers, wrapping and unwrapping tokens, balance checks, mathematical operations, and comparisons, ensuring efficient and secure swap processes. The contract can also accept Ether payments directly.

Function Name
Description (Business Logic)

updateInternalCaller

The updateInternalCaller function allows the contract owner to update the list of authorized internal callers, emitting an UpdateInternalCaller event upon execution. Similarly, the updateBridge function updates the list of authorized bridge addresses and emits an UpdateBridge event.

multicall

The multicall function enables the contract owner to execute multiple delegate calls in a single transaction. It iterates over an array of calldata, performing each delegate call and storing the results in an array, which is then returned. This function enhances the contract’s efficiency by allowing batch processing of multiple operations.

fallback

It includes a fallback function designed to handle uniswapV3SwapCallback requests from any protocol based on UniswapV3. This function does not check for the factory since the contract is not intended to store tokens. Instead, it protects the user by ensuring the amountOutMin check is performed at the end of execution by comparing the starting and final balances at the destination address. The function uses inline assembly to extract parameters from the calldata, such as amount0Delta, amount1Delta, and assetIn. If the calldata size is not 164 bytes or if both amount0Delta and amount1Delta are non-positive, the function reverts with appropriate errors. The function then transfers the calculated amount of assetIn to the caller.

getFromAddress

The getFromAddress function retrieves the address to be used for a swap operation. It takes swapData, a boolean useCaller, and a boolean checkSignature as parameters. If checkSignature is true, the function constructs a message based on whether the swap data includes an affiliate and verifies the signature using the LibRouter.verifySignature function. If the signature is valid, it returns the address from the swap data. If checkSignature is false and useCaller is true, it returns the caller’s address. Otherwise, it reverts with an InvalidCall error. This function ensures that the correct address is used for the swap operation, providing flexibility and security in handling swap requests.

swap

The swap function facilitates token swaps based on the provided swapData. It takes the address initiating the swap (fromAddress) and the full amount used for the operation (fullAmountIn). The function calculates the initial balance of the destination address (toAddress) for the output asset (toAssetAddress). It then executes the swap by calling the execute function, which returns the amount transferred and the gas used. The function calculates the final balance of the destination address and determines the amount of tokens received (amountOut). If the received amount is less than the minimum required (amountOutMin), it reverts with an InsufficientAmountOut error. Additionally, it checks if the input amount matches the transferred amount for non-native assets, reverting with an InvalidAmountIn error if they do not match. If fullAmountIn is greater than zero, it emits a Swap event with the relevant details.

estimateSwapGas

The estimateSwapGas function estimates the gas required for a swap operation. It retrieves the swap data using LibRouter.getData() and determines the address initiating the swap. If the swap data includes a permit, it calls LibRouter.permit to handle the permit. It then transfers any applicable fees using LibRouter.transferFees. Finally, it calls the swap function and returns the amount of tokens received and the gas used.

swapWithMagpieSignature

The swapWithMagpieSignature function performs a swap operation using Magpie signature. It retrieves the swap data and the address initiating the swap, handles any permits, transfers fees, and calls the swap function. It returns the amount of tokens received.

swapWithUserSignature

The swapWithUserSignature function allows internal callers to perform a swap operation using a user-provided signature. It retrieves the swap data and the address initiating the swap, ensuring no native tokens are sent with the transaction. It handles any permits, transfers fees, and calls the swap function, returning the amount of tokens received.

swapWithoutSignature

The swapWithoutSignature function enables bridge addresses to perform a swap operation without requiring a signature. It retrieves the swap data and the address initiating the swap, then calls the swap function, returning the amount of tokens received. This function is restricted to authorized bridge addresses using the onlyBridge modifier.

getCommandData

The getCommandData function prepares the necessary command data for iterating through a sequence of commands. It uses inline assembly to calculate the offsets and lengths required for processing the commands. Specifically, it calculates the commandsOffset by adding 70 to the shifted value of the calldata at position 68, the commandsOffsetEnd by adding 68 to the calldata at position 36, and the outputsLength by shifting the calldata at position 70. These values are essential for correctly iterating through the commands during the swap operation.

execute

The execute function handles the execution of a sequence of commands for the swap operation. It takes the address from which the assets will be swapped (fromAddress) and the address of the asset to be swapped (fromAssetAddress). The function retrieves the command data using getCommandData and initializes a pointer for the output data. It then iterates through the commands using a loop, calling the executeCommand function for each command. The executeCommand function returns the amount transferred, the gas used, and updates the output pointer. If the final output pointer exceeds the allocated output length, the function reverts with an InvalidOutput error. This function ensures that the swap operation is executed correctly and efficiently, handling multiple commands in a single transaction.

getInput

The getInput function constructs the input data for a specific command based on its position (i) and the memory pointer of the currently available output (outputPtr). Using inline assembly, the function calculates the end position of the sequences and initializes the input data and native token amount. It iterates through the sequences, processing each one based on its type, such as NativeAmount, Selector, Address, Amount, Data, CommandOutput, RouterAddress, and SenderAddress. For each sequence type, the function performs specific operations:

β€’ For NativeAmount, it determines the native token amount either from the output pointer or directly from the calldata.

β€’ For Selector, it loads the function selector from the calldata.

β€’ For Address, it extracts the address from the calldata.

β€’ For Amount, it calculates the amount from the calldata.

β€’ For Data, it copies the data from the calldata to the input.

β€’ For CommandOutput, it loads the output data from the output pointer.

β€’ For RouterAddress, it stores the contract’s address.

β€’ For SenderAddress, it stores the caller’s address.

If an invalid sequence type is encountered, the function reverts with an InvalidSequenceType error. After processing all sequences, it updates the input data length and the free memory pointer. This function ensures that the input data for each command is correctly constructed, enabling the execution of complex operations within the contract.

executeCommandCall

The executeCommandCall function executes a command call with the given parameters. It retrieves the input data and native token amount using the getInput function. The function then calculates the output length from the calldata and uses a switch statement to handle different selectors. If the selector is invalid or corresponds to a blacklisted transferFrom call, the function reverts with appropriate errors. For valid selectors, it retrieves the target address from the calldata and ensures it is not the contract’s address. It then performs a call to the target address with the provided input data and native amount. If the call fails, it reverts with the returned data. The function updates the output offset pointer and returns the new position.

executeCommandApproval

The executeCommandApproval function handles the execution of a command approval. It retrieves the input data using the getInput function and extracts the self address, spender address, and the amount to be approved from the input data. The function then calls the approve method on the self address, allowing the spender to spend the specified amount. This function ensures that the approval operation is executed correctly, enabling subsequent transactions to utilize the approved amount.

executeCommandTransferFrom

The executeCommandTransferFrom function facilitates the execution of a transfer command from a specific address and asset. It retrieves the input data using the getInput function and extracts the amount to be transferred from the input data. If the amount is greater than zero, it also extracts the recipient address and performs the transfer from the specified fromAddress to the recipient using the transferFrom method of the fromAssetAddress. The function then updates the accumulated transfer amount and returns it. This ensures that the specified amount of the asset is correctly transferred from the source address to the destination address.

executeCommandTransfer

The executeCommandTransfer function handles the execution of a direct transfer command. It retrieves the input data using the getInput function and extracts the amount to be transferred. If the amount is greater than zero, it also extracts the sender (self) and recipient addresses from the input data. The function then performs the transfer from the sender to the recipient using the transfer method. This function ensures that the specified amount is correctly transferred from the sender to the recipient, facilitating the movement of assets within the contract.

executeCommandWrap

The executeCommandWrap function handles the execution of a wrap command, which is used to wrap native tokens. It retrieves the input data using the getInput function and extracts the self address and the amount to be wrapped from the input data. The function then calls the wrap method on the self address with the specified amount, ensuring that the native tokens are correctly wrapped.

executeCommandUnwrap

The executeCommandUnwrap function is responsible for executing an unwrap command, which is used to unwrap native tokens. Similar to the wrap function, it retrieves the input data and extracts the self address and the amount to be unwrapped. The function then calls the unwrap method on the self address with the specified amount, ensuring that the native tokens are correctly unwrapped.

executeCommandBalance

The executeCommandBalance function executes a balance command and returns the resulting balance. It retrieves the input data using the getInput function and extracts the self address. The function then calls the getBalance method on the self address to retrieve the balance. The balance is stored at the output offset pointer in memory, and the function updates the output offset pointer before returning it. This function ensures that the balance of the specified address is correctly retrieved and stored for further use in the contract.

executeCommandMath

The executeCommandMath function executes a mathematical command based on the provided parameters. It retrieves the input data using the getInput function and defines a nested assembly function, math, to perform various mathematical operations. The function iterates through a set of commands, processing each one based on its operator type, such as addition, subtraction, multiplication, division, power, absolute value (both 128-bit and 256-bit), bitwise shift right, and bitwise shift left. For each operator, the function retrieves the operands from either the current output pointer or the input data, performs the specified operation, and stores the result in the current output pointer. If an invalid operator is encountered, the function reverts with an InvalidSequenceType error. After processing all commands, the function updates the output offset pointer and returns it. This function ensures that complex mathematical operations can be executed efficiently within the contract, supporting a wide range of arithmetic and bitwise operations.

executeCommandComparison

The executeCommandComparison function executes a comparison command based on the provided parameters. It retrieves the input data using the getInput function and defines a nested assembly function, comparison, to perform various comparison operations. The function iterates through a set of commands, processing each one based on its operator type, such as less than (Lt), less than or equal to (Lte), greater than (Gt), greater than or equal to (Gte), equal to (Eq), and not equal to (Ne). For each operator, the function retrieves the operands from either the current output pointer or the input data, performs the specified comparison, and stores the result in the current output pointer. If an invalid operator is encountered, the function reverts with an InvalidSequenceType error. After processing all commands, the function updates the output offset pointer and returns it. This function ensures that complex comparison operations can be executed efficiently within the contract, supporting a wide range of relational operations to facilitate decision-making processes in the contract’s logic.

executeCommand

The executeCommand function is a comprehensive handler for executing various commands within the swap operation. It takes several parameters, including the command data position (i), the address from which assets will be transferred (fromAddress), the asset address (fromAssetAddress), and pointers for output memory (outputPtr and outputOffsetPtr). It also tracks the accumulated transferred amount (transferFromAmount) and the gas used (gasUsed). The function begins by determining the type of command to execute using the CommandAction enumeration. Depending on the command type, it calls the appropriate function to handle the command: β€’ Call: Executes a generic function call using executeCommandCall.

β€’ Approval: Handles token approval operations with executeCommandApproval.

β€’ TransferFrom: Executes a transfer from a specific address using executeCommandTransferFrom.

β€’ Transfer: Executes a direct transfer with executeCommandTransfer.

β€’ Wrap: Wraps native tokens using executeCommandWrap.

β€’ Unwrap: Unwraps native tokens with executeCommandUnwrap.

β€’ Balance: Retrieves the balance of an address using executeCommandBalance.

β€’ Math: Performs mathematical operations with executeCommandMath.

β€’ Comparison: Executes comparison operations using executeCommandComparison.

β€’ EstimateGasStart: Records the starting gas for estimation.

β€’ EstimateGasEnd: Calculates the gas used by subtracting the remaining gas from the starting gas.

If an invalid command is encountered, the function reverts with an InvalidCommand error. The function returns the updated values for transferFromAmount, gasUsed, and outputOffsetPtr, ensuring that the swap operation is executed correctly and efficiently.

receive

receive function handles incoming Ether transfers.

Last updated