Module contract code is located here. The test for it is located here.
The driver script is located at index.ts. All other code is in the ts
directory. It can use either Ethplorer, Blockscout APIs or it can directly get the information on-chain using Settlement Trade events to determine the different tokens held by the Settlement contract. It then filters them on the basis of:
- Swap output value, see module setup.
The program after filtering and determining which tokens to swap, posts the swap orders on the CoW OrderBook API.
For all the orders that got successfully posted, it determines which of those orders require approval
and sends a tx to call COWFeeModule::drip with tokens that need to be approved, and
tokens that need to be swapped specifiying both the sell and buy amounts.
There are additional methods:
COWFeeModule::approve-- will max approve all the specified tokens to be spent by the vault relayer.COWFeeModule::revoke-- will revoke the given tokens for given spenders.
Copy the .env.example to .env and set the applicable configuration variables for the testing / deployment environment.
Run the script to deploy the module:
# Dry run the deployment
forge script ./script/DeployCOWFeeModule.s.sol \
--rpc-url <rpc>
# Deploy and verify the contract
# Make sure to set the ETHERSCAN_API_KEY environment variable
forge script ./script/DeployCOWFeeModule.s.sol \
--rpc-url <rpc> \
--broadcast --verify --private-key <private-key>To verify the contract code of the module on the chain's block explorer if the contract is already deployed:
source .env
forge verify-contract <fee-module-address> COWFeeModule --chain-id <chain-id> --etherscan-api-key $ETHERSCAN_API_KEY --constructor-args $(cast abi-encode "constructor(address,address,address,address,bytes32,address,uint256)" $SETTLEMENT $TARGET_SAFE $WRAPPED_NATIVE_TOKEN $KEEPER $APP_DATA $RECEIVER $MIN_OUT)The module may be redeployed often to update its parameters. If there's already a past deployment, it's helpful to compare the parameters of a new deployment with the current one. This can be done with the following script:
yarn ts-node compare-deployments.ts --network <network name> <address of the newly deployed module>The deployment creates the module, but this module needs to be enabled on the target safe.
One way to do this is to use the Transaction Builder UI on the target safe.
- Select the target safe.
- Click on
Use Implementation ABIto load the ABI automatically. - Select
enableModulefrom the dropdown of available functions. - Enter the module address and click on
Add new transaction - Send batch
Private key for keeper needs to set with PRIVATE_KEY environment
variable.
Usage: cow-fee [options]
Options:
--network <network> (choices: "mainnet", "gnosis", "arbitrum", "base", "sepolia")
--rpc-url <rpc-url>
--max-orders <max-orders> Maximum number of orders to place in single drip call (default: 250)
--buy-amount-slippage-bps <buy-amount-slippage-bps> Tolerance to add to the quoted buyAmount (default: 100)
--module <module> COWFeeModule address
--token-list-strategy <strategy> Strategy to use to get the list of tokens to swap on (choices: "explorer", "chain", default: "explorer")
--lookback-range <n> Last <n> number of blocks to check the `Trade` events for (default: 1000)
-h, --help display help for command
source .env
yarn ts-node index.ts \
--network mainnet \
--max-orders 250 \
--rpc-url $RPC_URL \
--buy-amount-slippage-bps 100 \
--module <module-address> \
--token-list-strategy chain \
--lookback-range 1000source .env
# build the docker file
docker build -t cow-fee .
# run the container
docker run --rm \
-e PRIVATE_KEY=$PRIVATE_KEY \
cow-fee \
--network mainnet \
--max-orders 250 \
--rpc-url $RPC_URL \
--buy-amount-slippage-bps 100 \
--module <module-address> \
--token-list-strategy chain \
--lookback-range 1000cast calldata "enableModule(address)" <module-address>
use this calldata to send a transaction from a safe to itself to enable the module on that safe.
Use the safe UI settings page to disable the module.
forge test -vvv --rpc-url wss://mainnet.gateway.tenderly.co