https://github.com/cowprotocol/hooks-trampoline
A dedicated trampoline contract for executing user-specified hooks.
https://github.com/cowprotocol/hooks-trampoline
Last synced: 8 months ago
JSON representation
A dedicated trampoline contract for executing user-specified hooks.
- Host: GitHub
- URL: https://github.com/cowprotocol/hooks-trampoline
- Owner: cowprotocol
- Created: 2023-07-08T07:14:37.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2025-07-29T10:48:04.000Z (10 months ago)
- Last Synced: 2025-07-29T12:53:20.726Z (10 months ago)
- Language: Solidity
- Size: 42 KB
- Stars: 6
- Watchers: 4
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Hooks Trampoline
Hooks are a CoW Protocol feature that allow traders to specify custom Ethereum
calls as part of their order to get executed atomically in the same transaction
as they trade.
The `HooksTrampoline` contract protects the protocol from two things:
- Executing calls from the privileged context of the settlement contract. Fees
are accrued in the contract, and users could simply specify hooks that
`ERC20.transfer(user, amount)` if the calling context for user hooks were the
settlement contract.
- Reverting unnecessary hooks during a settlement. This can cause a two issues:
- `Interaction`s from the settlement contract are called with all remaining
`gasleft()`. This means, that a revert from an `INVALID` opcode for example,
would consume 63/64ths of the total transaction gas. This means that hooks
can make settlements extremely expensive for nothing.
- Other orders being executed as part of the settlement would also not be
included.
As such, the `HooksTrampoline` contract is designed to execute user-specified
hooks:
1. From an unprivileged context (the `HooksTrampoline` contract instead of the
CoW Protocol settlement contract).
2. Specify a gas limit, to cap `INVALID` opcodes from consuming too much gas.
3. Allow the calls to revert.
In addition, the `HooksTrampoline` also only allows calls from the settlement
contract. This means that hook implementations can add checks that ensure that
they are only called from within a settlement:
```solidity
require(msg.sender == HOOKS_TRAMPOLINE_ADDRESS, "not a settlement");
```
## Settlement Diagram
```mermaid
sequenceDiagram
participant Solver
participant Settlement
participant HooksTrampoline
participant Hook
Solver->>Settlement: settle
activate Settlement
Settlement->>HooksTrampoline: execute
activate HooksTrampoline
loop pre-hooks
HooksTrampoline->>Hook: call
activate Hook
Hook->>HooksTrampoline: return/revert
deactivate Hook
end
HooksTrampoline->>Settlement: return
deactivate HooksTrampoline
Settlement->>Settlement: swap
Settlement->>HooksTrampoline: execute
activate HooksTrampoline
loop post-hooks
HooksTrampoline->>Hook: call
activate Hook
Hook->>HooksTrampoline: return/revert
deactivate Hook
end
HooksTrampoline->>Settlement: return
deactivate HooksTrampoline
Settlement->>Solver: return
deactivate Settlement
```
## Development
### Installation
This project uses [Foundry](https://book.getfoundry.sh/).
Additional dependencies can be installed with:
```sh
forge install
```
### Test
```sh
forge test
```
### Deployment
Copy `.env.sample` to `.env` and fill each variable with the necessary
information.
You can do a test run of the transaction with the following command:
```sh
source .env
forge script script/DeployHooksTrampoline.s.sol -vvvv --rpc-url "$ETH_RPC_URL"
```
The following command executes the deployment transaction onchain and verifies
the contract code on the block explorer.
```sh
source .env
forge script script/DeployHooksTrampoline.s.sol -vvvv --rpc-url "$ETH_RPC_URL" --verify --verifier-url "$VERIFIER_URL" --broadcast
```
#### Deployment addresses
The file [`networks.json`](./networks.json) lists all official deployments of the contracts in this repository by chain id.
Update the file with:
```sh
bash dev/generate-networks-file.sh > networks.json
```
## Verification
If you deployed the contract passing `--verify`, the contract will be verified so you can skip this step. However, if you didn't, or the verification failed, you can verify the contract manually with the following command:
```sh
source .env
forge verify-contract 0x60Bf78233f48eC42eE3F101b9a05eC7878728006 src/HooksTrampoline.sol:HooksTrampoline --guess-constructor-args --etherscan-api-key $ETHERSCAN_API_KEY --verifier-url $VERIFIER_URL --verifier $VERIFIER --watch
```