Skip to content

feat: register a polling schedule#123

Open
anxolin wants to merge 3 commits into
feat/poller-basefrom
feat/poller-register
Open

feat: register a polling schedule#123
anxolin wants to merge 3 commits into
feat/poller-basefrom
feat/poller-register

Conversation

@anxolin

@anxolin anxolin commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Part of #121. Follow uo #116

The polling requires a pre-authorization from the funding account (the registration).

This pre-authorization is done by registering a polling schedule

What

Adds the struct of the register.

The registrations are done using a scheduleId (bytes32). The PR provides a pure function that generates this id deterministically based on the funder, handler, owner and salt.

This pre-register is what will allow in a follow up PR to implement the constraints in the function that does the actual poll.

Test plan

forge test --match-contract ComposableCowPollerTest -vv

Test pass

@anxolin
anxolin marked this pull request as draft July 10, 2026 22:36
@anxolin anxolin changed the title feat: register a polling schedule (1/3) feat: register a polling schedule Jul 10, 2026
@anxolin
anxolin force-pushed the feat/poller-base branch from f47098d to f62db1a Compare July 10, 2026 23:12
@anxolin
anxolin force-pushed the feat/poller-register branch from 8fdcbe1 to 4e308b0 Compare July 10, 2026 23:12
@anxolin
anxolin marked this pull request as ready for review July 10, 2026 23:16
@anxolin
anxolin force-pushed the feat/poller-base branch from f62db1a to 6b6c223 Compare July 11, 2026 00:42
@anxolin
anxolin force-pushed the feat/poller-register branch from 4e308b0 to 6966303 Compare July 11, 2026 00:42
@anxolin
anxolin force-pushed the feat/poller-base branch from 6b6c223 to 6e29a31 Compare July 11, 2026 01:44
@anxolin
anxolin force-pushed the feat/poller-register branch 2 times, most recently from 04c1bde to bf350d1 Compare July 13, 2026 09:17
Comment thread src/types/ComposableCowPoller.sol Outdated
Comment thread src/types/ComposableCowPoller.sol
Comment thread src/types/ComposableCowPoller.sol
Comment thread test/ComposableCowPoller.t.sol Outdated
Comment thread test/ComposableCowPoller.t.sol Outdated

@kaze-cow kaze-cow left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is probably some shady security issue with simply not including the staticInput in the schedule ID, but I need to see the rest of the code put together before I will comment further.

appears there are currently merge conflicts that need fixing

Comment thread src/types/ComposableCowPoller.sol Outdated
/// @dev A schedule is uniquely identified by its funder, handler, owner, and salt.
struct Schedule {
IConditionalOrderGenerator handler; // the conditional-order handler to poll (e.g. the TWAP type)
address funder; // source of funds; the only registrant

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based solely on this comment, its unclear: in the case of polling for a TWAP order using CoW Shed and an EOA, is the funder the EOA, or the CoWShed?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, funder can be anyone that approves the Poller contract

Comment thread src/types/ComposableCowPoller.sol Outdated
struct Schedule {
IConditionalOrderGenerator handler; // the conditional-order handler to poll (e.g. the TWAP type)
address funder; // source of funds; the only registrant
address owner; // order owner; the pull destination

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from this comment I assume it is the CoWShed. I would rename this field to orderOwner and clarify in the comment that this is the CoW Settlement order, as opposed to any other kind of order that may become relevant.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this brings any value. owner can be anyone that will receive funds in the end

Comment thread src/types/ComposableCowPoller.sol Outdated
Comment on lines +14 to +15
bytes32 salt; // the conditional order's salt
bytes staticInput; // the order's staticInput

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments are kind of redundant. maybe

Suggested change
bytes32 salt; // the conditional order's salt
bytes staticInput; // the order's staticInput
/// Used to set a new poller schedule instance with the same parameters
bytes32 salt;
/// The `staticInput` parameter used for `getTradableOrder` when calling `handler`
bytes staticInput;

contract ComposableCowPoller {
/// @notice Parameters for a JIT funding schedule.
/// @dev A schedule is uniquely identified by its funder, handler, owner, and salt.
struct Schedule {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of the fields in this struct comments could be docstrings (/// before the field)

Comment on lines +31 to +45
/// @notice Computes the deterministic, appData-independent schedule key.
/// @dev `staticInput` is excluded because its appData can depend on this key.
/// Use a different salt for concurrent schedules with the same funder, handler, and owner.
/// @param funder The token source.
/// @param handler The conditional-order generator.
/// @param owner The conditional-order owner.
/// @param salt The conditional-order salt.
/// @return The schedule key.
function scheduleId(address funder, IConditionalOrderGenerator handler, address owner, bytes32 salt)
public
pure
returns (bytes32)
{
return keccak256(abi.encode(funder, handler, owner, salt));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though staticInput isnt used in the schedule ID, it still would make the most sense here to simply take in the Schedule struct to make it simpler for the front end. Also, its wierd that the order of address funder and IConditionalOrderGenerator handler have been flipped from the original structure, and this could be problematic on the frontend because the type is ultimately address in both cases.

/// @param schedule The schedule to store.
/// @return id The deterministic key of the stored schedule.
function register(Schedule calldata schedule) external returns (bytes32 id) {
if (msg.sender != schedule.funder) revert OnlyFunder();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its now possible to do

Suggested change
if (msg.sender != schedule.funder) revert OnlyFunder();
require(msg.sender == schedule.funder, OnlyFunder());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I prefer this style of reverts, this is not a standard adopted in any CoW repo IIRC.

/// @param id The deterministic key of the schedule.
/// @param owner The conditional-order owner and pull destination.
/// @param funder The token source that registered the schedule.
event ScheduleRegistered(bytes32 indexed id, address indexed owner, address indexed funder);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for completeness it would be good to include all fields of Schedule in the log

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current fields are the most important ones, and adding more could just spike up gas costs at not much additional benefits (e.g. staticInput, handler etc)

Comment thread test/ComposableCowPoller.t.sol Outdated
/// added in follow-up PRs.
/// @notice Exercises registering a schedule for a composable TWAP created via `createWithContext`.
contract ComposableCowPollerTest is BaseComposableCoWTest {
uint256 constant PART = 100e18;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the amount to trade on each TWAP trade, right? The constant (or at least the naming) actually makes it harder to understand what is going on, so it seems like it would be best to rename this to something like TWAP_PART_AMOUNT, or perhaps remove it entirely.

/// @notice Exercises registering a schedule for a composable TWAP created via `createWithContext`.
contract ComposableCowPollerTest is BaseComposableCoWTest {
uint256 constant PART = 100e18;
uint256 constant LIMIT = 1e18;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this value is only used in the _bundle function so low value in having it as a constant here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded magic values are really hard to understand, so I'd keep it as-is

anxolin and others added 3 commits July 17, 2026 19:08
Clarify schedule roles, accept Schedule in scheduleId, and improve TWAP test naming.
@igorroncevic
igorroncevic force-pushed the feat/poller-register branch from 21fe323 to 45755b8 Compare July 17, 2026 17:17
@igorroncevic
igorroncevic requested a review from kaze-cow July 17, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants