- Because takehomes are not paid for hours worked, this task is designed to help us gauge the participants’ skills and understanding, rather than to produce work that will be used by the team.
- To respect the participant’s work, we will not be taking this work or modifying it for the team’s interest in any way.
Here's the scenario:
- I want to purchase 1 WBTC by paying the necessary amount of WETH.
- But I do not yet have any WETH that I can use to pay for this swap.
- Fortunately, I have a friend who will transfer me the necessary WETH amount, if I give them just 0.5 of WBTC.
- This is a great deal, since I'm not paying for anything and I get half of WBTC.
- One issue is that I don't have access to that 0.5 WBTC, before I make the swap itself.
- So we need a way to access the token that I'm buying first, send a part of that token to the friend, receive the WETH amount necessary to purchase the WBTC amount, then pay the Uniswap pool.
- Callbacks in Uniswap's
swap
function helps us achieve this.- Concretely,
- I can receive the 1 WBTC amount that I'm buying before this callback function is called.
- In the callback, I can transfer 0.5 WBTC to my friend, then receive some amount of WETH from my friend.
- Then at the end of the callback, I can use this WETH that I received from my friend to pay for the cost of the swap. (If I don't pay the pool, then Uniswap will revert the swap);
- We call this a
flashswap
since we gain access to the output asset first, take control flow, and have the pool guarantee that the call succeeds if and only if the input asset is paid for.
- Concretely,
- Now here's the real problem: How can I implement a multi-hop flashswap?
- A single-hop flashswap between WETH (sell) <> WBTC (buy) means I get access to WBTC, insert a callback in the middle, then pays the WETH back to the pool.
- A multi-hop flashswap between WETH (sell) <> DAI <> USDC <> WBTC (buy) means I get access to WBTC, do a callback, then pay WETH.
- In both cases, I am buying WBTC and paying WETH and taking control flow in between. But importantly, the second bullet point conducts the swap across multiple pools.
- Your job is to implement this second bullet point, a multi-hop flashswap that allows you to access to the output token (WBTC) before paying the input token (WETH), while routing the swap across multiple pools
- There are three pools.
- WBTC <> USDC
- USDC <> DAI
- DAI <> WETH
- TODO
- See all the
TODO
items inFlashswap.sol
andFlashswap.t.sol
- Implement the
exactOutput
and theuniswapV3SwapCallback
functions for the multi-hop flashswap. - Implement the
Caller.flashSwapCallback
function. - Implement the
_path
intest_ExactOutput_ThreePools
. - Run the
test_ExactOutput_ThreePools
test and make it pass!
- See all the
test_ExactOutput_ThreePool
- This test is meant to validate the following process:
- Flashswap WETH (sell) <> WBTC (buy) using the three pools in the path.
- After you receive WBTC, trade with the
Friend
contract in the callback. (TheFriend
will take0.5
WBTC and give you any requested amount ofWETH
). - Use the
WETH
from the friend to pay the swap. - Congratulations! You just finished a multi-hop flashswap.
- NOTE You must set up the
.env
file for the fork test. See.env.example
.
- This test is meant to validate the following process:
- It is strongly recommended that you review the
FlashSwap.t.sol
andFlashswap.sol
for theTODO
items as you begin.
- Multi-hop Swap
- SwapRouter.sol contract implements a multi-hop swap that takes in the path that encodes a list of pools that the swap should go through.
- Your solution is also a multi-hop swap and may look very similar to this contract.
- Path
- Uniswap swap paths can be encoded in bytes and decoded using the
Path.sol
library. - Example of using the
path
is also inSwapRouter.sol
.
- You may need to review other resources related to UniV3 if not yet familiar.
- Recommendations
- Start by diagramming out the flow for callback control flow to ensure understanding of the requirements.
- NOTE
- If the task is challenging, please do not hestitate to reach out with any questions if there are blockers.
- We would much rather have open discussions around the problem to work it out together as part of the takehome process than to have the participant be discouraged and not complete the task. We are looking for a glimpse into your thought process as you tacke non-trivial problems.
- You are also encouraged to reference any resources or tools online if it helps your process.
$ forge build
$ forge test
$ forge fmt
$ forge snapshot
$ anvil
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
$ cast <subcommand>
$ forge --help
$ anvil --help
$ cast --help