Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/const/gnosis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export const GNO_ADDRESS = "0x9C58BAcC331c9aa871AFD802DB6379a98e80CEdb";

// ComposableCowPoller: just-in-time funding for composable conditional orders.
// `id`-keyed deployment (schedule key is independent of the order's appData, so
// `topUp(id)` can be embedded as a pre-hook in the order's own appData).
// `pollFunds(id)` can be embedded as a pre-hook in the order's own appData).
// See https://github.com/cowprotocol/composable-cow/pull/116
export const COMPOSABLE_COW_POLLER_ADDRESS =
"0xA360eE11eD0d2025604518CF4B8F6e6CB76C7Df7";
4 changes: 2 additions & 2 deletions src/contracts/composable-cow-poller/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ethers } from "ethers";
* Minimal ABI for the `ComposableCowPoller` contract.
*
* It enables just-in-time funding for composable conditional orders: instead of
* locking the whole notional up front, `topUp` pulls exactly the current discrete
* locking the whole notional up front, `pollFunds` pulls exactly the current discrete
* order's `sellAmount` from a funder into the order owner, immediately before that
* order settles.
*
Expand All @@ -15,7 +15,7 @@ const COMPOSABLE_COW_POLLER_ABI = [
"function scheduleId(address funder, address handler, address owner, bytes32 salt) external pure returns (bytes32)",
"function register((address handler, address funder, address owner, bytes32 salt, bytes staticInput) schedule) external returns (bytes32 id)",
"function revoke(bytes32 id) external",
"function topUp(bytes32 id) external",
"function pollFunds(bytes32 id) external",
"function schedules(bytes32 id) external view returns (address handler, address funder, address owner, bytes32 salt, bytes staticInput)",
"function lastFunded(bytes32 id) external view returns (bytes32)",
] as const;
Expand Down
18 changes: 9 additions & 9 deletions src/scripts/composable-cow/postTwapForEOAWithJitFunds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ const FIRST_ORDER_SLIPPAGE_BPS = 20000000000; // 200,000,000% // TODO: This was

// The TWAP handler (ComposableCoW order type). Deterministic across chains.
const TWAP_HANDLER = "0x6cF1e9cA41f7611dEf408122793c358a3d11E5a5";
// Gas budget for the topUp pre-hook on each part (SLOADs + getTradeableOrder + transferFrom).
const TOPUP_HOOK_GAS_LIMIT = "350000";
// Gas budget for the pollFunds pre-hook on each part (SLOADs + getTradeableOrder + transferFrom).
const POLL_FUNDS_HOOK_GAS_LIMIT = "350000";

const CHAIN_ID = SupportedChainId.GNOSIS_CHAIN;

Expand Down Expand Up @@ -92,7 +92,7 @@ export async function run() {

// The poller schedule key. It is derived from appData-INDEPENDENT fields
// (funder, handler, owner, salt), which is exactly what lets us embed
// `topUp(id)` as a pre-hook inside the TWAP's own appData: the order's `ctx`
// `pollFunds(id)` as a pre-hook inside the TWAP's own appData: the order's `ctx`
// contains the appData hash, so keying on `ctx` would be circular, but `id`
// is not. We choose the salt, so we can compute `id` before the appData.
const poller = getComposableCowPollerContract(
Expand Down Expand Up @@ -125,25 +125,25 @@ The EOA keeps the 1 wei of ${twapSellToken.symbol}, which means that the EOA is
The order will have the side-effects described above.

Watch Tower will detect the TWAP and create each part, which will settle and send the proceeds back to the EOA.
Each part carries a pre-hook (baked into the TWAP appData) that calls poller.topUp(id), pulling exactly that part's
Each part carries a pre-hook (baked into the TWAP appData) that calls poller.pollFunds(id), pulling exactly that part's
sell amount from the EOA into cow-shed right before it settles. No external keeper is needed.
`,
);

// Generate app data for the TWAP, embedding a pre-hook with the polling
const metadataApi = new MetadataApi();
const topUpCalldata = poller.interface.encodeFunctionData("topUp", [id]);
const pollFundsCalldata = poller.interface.encodeFunctionData("pollFunds", [id]);
const twapAppData = await metadataApi.generateAppDataDoc({
appCode: APP_CODE,
environment: "prod",
metadata: {
hooks: {
pre: [
// Call: poll.topUp(id)
// Call: poll.pollFunds(id)
{
target: COMPOSABLE_COW_POLLER_ADDRESS,
callData: topUpCalldata,
gasLimit: TOPUP_HOOK_GAS_LIMIT,
callData: pollFundsCalldata,
gasLimit: POLL_FUNDS_HOOK_GAS_LIMIT,
},
],
},
Expand Down Expand Up @@ -208,7 +208,7 @@ TWAP buy amount total: ~${fmt(expectedTwapBuyAmount)} expected, ${fmt(twapBuyAmo
const { handler, salt, staticInput } = twap.leaf;

// Sanity: the handler/salt must be exactly what we derived `id` from, so the
// `topUp(id)` hook baked into the appData resolves to this very schedule.
// `pollFunds(id)` hook baked into the appData resolves to this very schedule.
if (
handler.toLowerCase() !== TWAP_HANDLER.toLowerCase() ||
salt.toLowerCase() !== twapSalt.toLowerCase()
Expand Down