Now that we have the setup out of the way, lets make use of CoW Hooks to set up an order that, when executed will:
Set the required token approval to CoW Protocol - this allows the user to trade regardless of whether or not they have Ether to execute the approval transaction themselves and so that the approval is only set if the order were to execute (no reason to pay for an approval that doesn’t get used amirite?). Note that this requires a token that has EIP-2612 permit support (such as COW, USDC, and DAI; many modern tokens support this).
Bridges the resulting trade proceeds to Gnosis Chain
EIP-2612 Permit
The next order of business is to compute the pre-hook for setting the required approval of the CoW Protocol Vault Relayer contract.
For this, we make use of EIP-2612 permit. This EIP defines an extension for ERC-20 tokens that allows any account to set ERC-20 approvals on behalf of another with an off-chain signature. In other words, we can sign with an off-chain signature permission for anyone to set a single approval to CoW Protocol for us. This signature can be used in a pre-hook so that a solver can execute the approval on your behalf only if your order were to trade.
Let's compute the permit parameters and sign them:
⚠️ This example makes use of an unaudited contract, use at your own risk!.
On-chain
Now, we want to add a post-hook to bridge the funds that we receive from trading over to Gnosis Chain.
Unfortunately, bridging contracts aren't designed with this use-case in mind. In particular, the hooks are called from an unprivileged context (specifically, the settlement will "trampoline" the user-specified hooks over an intermediary contract as a security measure):
The existing Gnosis Chain Omnibridge contract takes tokens for bridging from msg.sender, so we need to design an on-chain contract to temporarily hold the funds for the bridging process. Fortunately, this is very easy to do:
This contract works by deploying a per-user "bridging account", where funds deposited can only be bridged to the user, or withdrawn back to the user, keeping the funds safe!
Note that there are no on-chain guarantees that order hooks will get executed as part of a settlement. These are guaranteed by off-chain protocol rules where damages will be taken from solver bonding pools (which sets an upper bound for how much in funds is protected). Keep this in mind as you design your hooks.
In addition to this contract, we also create a Bridger factory contract that deploys accounts per user and makes bridging with hooks easier. For the full source code, see [contracts/Bridger.sol].
This can be extended to allow for bridging to different receivers, this is left as an exercise to the reader
Off-chain
Now that we have our bridging intermediary contract, we can generate the hook for bridging the funds received from trading.
This is a walk in the park, just compute the receiver address and generate data for the hook:
orderConfig.receiver =awaitBRIDGER.getAccountAddress(wallet.address);constbridgeHook= { target:BRIDGER.address, callData:BRIDGER.interface.encodeFunctionData("bridgeAll", [wallet.address,COW.address, ]),// Approximate gas limit determined with Tenderly. gasLimit:"228533",};
Order Creation
Now that we have our hooks set up, it is time to create our order!
First, we need to include our hooks in the order's appData. Hooks are specified as part of appData documentsin order to ensure that hook preferences are signed by the order:
Note that the API will compute a feeAmount that takes the hook gas amounts into account. This means that gas for the permit and bridging transactions are paid in the sell token only if (and when) the order executes! Account abstraction at its finest 😄.
Here is the demo executed order on Mainnet. As you can see from the transaction, the USDC approval to CoW Protocol was set just-in-time for the swap to happen, and the trade proceeds were sent to the Omnibridge so that the bridging of the COW tokens that were received was initiated.
Here are the relayed COW tokens to the same address on Gnosis Chain.
Here is the complete code listing for the script that was used for creating the order.