Setup
The setup for the flash loan example is as follows:-
A Safe wallet at address
0x35eD9A9D1122A1544e031Cc92fCC7eA599e28D9C. We use a smart contract wallet so that smart contracts can initiate the withdrawal of the collateral token. - The Safe borrows 10,000 USDT on Aave using 500,000 USDC as collateral.
- Aave is used as the flash loan lender.
-
The necessary
ERC-20approvals are set in the wallet:- The collateral token (USDC) is approved for CoW’s Vault Relayer contract to facilitate the trade.
- The borrowed token (USDT) is approved for the Aave pool contract to enable debt repayment.
- The Safe must have a non-zero balance of the order’s sell token (USDC in this case) to pass CoW Swap order validation, which serves as a spam protection measure.
- Request a flash loan to Aave of 5,000 USDT.
- Use those 5,000 to partially repay the 10,000 USDT debt on Aave.
- Withdraw 400,000 USDC from Aave.
- Perform a trade on CoW Swap, selling up to 400,000 USDC for 5,002.5 USDT (borrowed amount + 0.05% flash loan fee on Aave).
- Use the 5,002.5 USDT from the trade to fully repay the flash loan (including the fee).
Exchange ratios on the Sepolia network can be very inconsistent. To ensure successful execution of the order, a large amount of USDC is withdrawn from Aave and used in the trade.General considerations when testing flash loans on Sepolia and Aave:
- Token addresses in Aave may not correspond with tokens names in other dapps.
- Token ratios may need to be balanced, and trading amounts adjusted accordingly.
- Tokens in Aave can be obtained from the faucet.
- Check withdrawal and borrowing availability of the tokens on Aave.
Aave repay pre-hook
We need to define a pre-hook to repay the 5,000 USDT debt on Aave, ensuring the Aave pool allows us to withdraw the associated collateral. As part of the settlement, we want to call therepay function on Aave’s pool:
viem:
repay call (as well as the withdraw call later on) must be executed as a pre-hook during the order settlement process. This ensures that the user has the collateral tokens available before the settlement contract pulls in the sell tokens from all settled orders.
To enable this, the pre-hook defines a transaction that will be sent to the Safe wallet. The Safe then executes the actual repay call to the Aave pool. The transaction can be built using the Safe Protocol Kit as shown below:
For this example, the
nonce should be offset by 1 from the current Safe’s nonce. This is necessary to avoid reusing the same nonce, since a separate transaction will be sent to emit the pre-signature for our order, which is required to make it executable in the first place.Aave withdraw pre-hook
We need to define another pre-hook to withdraw 400,000 USDC from the Aave deposit. This ensures that our Safe wallet holds the necessary sell tokens for the order. Otherwise, the settlement contract would be unable to pull the funds from the Safe, causing the settlement to revert. For this, we need to call thewithdraw function on Aave’s pool:
withdraw call will be executed during the order settlement process via a Safe transaction, and can be built with:
Just like the
repay pre-hook, the nonce should be incremented to ensure it doesn’t conflict with other transactions. Here, we increase it by 2 because there are two preceding transactions: the pre-signature and the repay pre-hook.Building and publishing the order
With both therepay and withdraw pre-hooks in place, we can now build the metadata of our order:
Setting the pre-signature of the order
After placing the order, its pre-signature must be submitted by calling thesetPresignature function on the CoW Settlement contract:
Open, making it eligible for execution within the CoW Protocol.
This example uses a pre-signature, but a valid EIP-1271 contract signature could also be used. With an EIP-1271 signature, the
setPreSignature transaction would not be necessary.Order execution
Once an order is placed within the CoW Protocol, it enters an auction batch. When a solution is found, the following steps occur:-
The winning solver calls the flash loan
IFlashLoanRoutercontract. -
The 5,000 USDT gets transferred to the flash loan
IFlashLoanRoutercontract. -
In the pre-hook:
- Transfer 5,000 USDC from the flash loan
IFlashLoanRoutercontract to the user. - Execute the user’s pre-hook: Repay the outstanding debt.
- The user receives their 400,000 USDC of collateral.
- Transfer 5,000 USDC from the flash loan
- Transfer funds into the settlement contract.
-
Execute the user’s order:
- Swap USDC for USDT.
-
Transfer funds to the
receiveraddress (funds are sent to the settlement contract, which is to itself). -
Execute the post-interaction
- Depending on the flash loan provider, either pay back 5,002.5 USDT to the flash loan provider from the settlement contract, or send the funds to the flash loan
IFlashLoanRoutercontract, and then send it to the flash loan provider.
- Depending on the flash loan provider, either pay back 5,002.5 USDT to the flash loan provider from the settlement contract, or send the funds to the flash loan
- Some USDC may remain in the user’s wallet as surplus.
-
On Aave:
- The USDT debt is reduced from 10,000 to 5,000.
- The USDC collateral is reduced by 400,000.
- The flash loan provider is fully repaid (5,002.5 USDT).