buyAmount via off-chain input.
How It Works
A GAT order remains dormant until itsstartTime is reached. After that, it becomes valid until endTime, provided:
- The owner’s balance meets the
minSellBalancerequirement - The off-chain provided
buyAmountpasses optional price checker validation
buyAmount can vary between calls, each variation creates a unique orderUid, allowing multiple fills.
Data Structure
Price Checker Payload
Optional nested structure for price validation:Parameters
The token to sell
The token to receive in exchange
The address that will receive the bought tokens
The exact amount of
sellToken to sell in the orderMinimum balance of
sellToken the owner must have for the order to be valid. Provides replay protection by ensuring sufficient funds.Example: If you want to sell 1000 tokens but only allow execution if you have at least 1000 tokens, set minSellBalance = 1000e18UNIX timestamp when the order becomes valid. The order will not execute before this time.Example:
block.timestamp + 1 days for orders valid starting tomorrowUNIX timestamp when the order expires. Used as the
validTo field in the GPv2 order.Whether solvers can partially fill the order
ABI-encoded
PriceCheckerPayload struct for price validation, or empty bytes to skip price checking.When provided, the order validates that the off-chain supplied buyAmount meets minimum price requirements.The IPFS hash of the appData associated with the order
Price Checker Parameters
A Milkman-compatible price checker contract that calculates expected output amounts
Arbitrary data passed to the price checker (checker-specific format)
Maximum allowed slippage in basis points (1 bp = 0.01%)Examples:
- 100 = 1% slippage
- 50 = 0.5% slippage
- 500 = 5% slippage
buyAmount is calculated as:Off-Chain Input
GAT orders require off-chain input to specify thebuyAmount:
buyAmount when querying the order. Different buyAmount values create different orderUids, allowing multiple fills of the same order.
Behavior
Time-Based Activation
- Before
startTime: Order reverts withPollTryAtEpoch(startTime)- watchers should poll again at that time - Between
startTimeandendTime: Order is potentially valid (subject to balance and price checks) - After
endTime: Order expires and cannot be filled
Balance Check
The order validates that:Price Validation
IfpriceCheckerPayload is non-empty:
- Decode the
PriceCheckerPayload - Query the price checker for expected output:
expectedOut = checker.getExpectedOut(sellAmount, sellToken, buyToken, payload) - Calculate minimum acceptable amount:
minAcceptable = expectedOut * (10000 - allowedSlippage) / 10000 - Validate:
buyAmount >= minAcceptable
PollTryNextBlock(PRICE_CHECKER_FAILED).
Error Messages
The current time is before
startTime. The order will poll again at startTime.The owner’s balance of
sellToken is below minSellBalance. The order is invalid.The provided
buyAmount is below the minimum acceptable price. The order will poll again in the next block.Example Usage
Example 1: Basic Scheduled Order
Sell 1000 USDC for DAI starting in 24 hours:Example 2: Order with Price Validation
Sell ETH for USDC with Milkman price checker:Example 3: Repeatable Order with Partial Fills
Sell DAI multiple times after token unlock:Implementation Details
Contract Address
The Good After Time conditional order type is deployed at/src/types/GoodAfterTime.sol.
Key Function
The
buyAmount is provided via off-chain input, allowing the same order to be filled multiple times with different prices. The minSellBalance check prevents over-execution.