> For the complete documentation index, see [llms.txt](https://openflow.gitbook.io/openflow/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://openflow.gitbook.io/openflow/smart-contract-integration/smart-contract-sdk/submit-an-order.md).

# Submit an Order

Openflow SDK provides an encapsulated easy-to-use interface for executing swaps and managing orders. Below we demonstrate SDK usage.

### Basic Swap

For convenience several aliases have been built to make swapping as seamless as possible. To execute a basic swap with default swap options use `swap(address,address)`. All swaps return a unique order UID which can be used later to invalidate/cancel orders if desired. To execute a swap you must allow your `fromToken` to be spent by your SDK instance.

```solidity
IERC20(fromToken).approve(address(sdk), type(uint256).max);
bytes memory orderUid = sdk.swap(fromToken, toToken);
```

### Conditional swap

All swaps regardless of authentication type support *user-defined conditions.* The condition configuration is as follows:

```solidity
struct Condition {
    address target;
    bytes data;
}
```

In order for a swap to succeed the [condition check](https://github.com/openflow-fi/openflow-contracts/blob/main/src/Settlement.sol#L166) must pass. The condition check is a non-state altering (staticcall) method which is called against user-defined `condition.target` and `condition.data`.

Conditional swaps unlock a wide variety of configurable/programmable swaps for all users.

The SDK comes with a basic conditional swap alias:

```solidity
Condition memory condition = IOpenflowSdk.Condition({
   target: conditionChecker,
   data: abi.encodeWithSignature("checkCondition()")
});
bytes memory orderUid = sdk.conditionalSwap(fromToken, toToken, condition);
```

### Good after time (GAT) swap

An SDK alias exists for GAT swaps. The syntax to execute a simple GAT is as follows:

```solidity
uint32 validFrom = uint32(block.timestamp + (60*5)); // Order is valid in 5 minutes
bytes memory orderUid = sdk.gatSwap(fromToken, toToken, validFrom);
```

### **Pre-swap and post-swap hooks**

One unique feature of Openflow is that all order submitters are allowed to define completely user-defined pre-swap and post-swap hooks.

User-defined hooks enable some unique/interesting use cases. For example:

* &#x20;Hooks allow users to zap in and zap out of a protocol
  * In the traditional solver landscape if a user wishes to zap, say, into a yvToken (vault token) only solvers that support this type of zap can compete
  * By allowing users to execute the zap logic themselves in hooks, this allows the entire pool of solvers to compete in the underlying swap auction rather than just the one or two solvers who support this type of zap natively. This means better and more competitive pricing for end-users. This also means higher reliability and decentralization, because in the current landscape if one of the few solvers who support esoteric zaps has downtown this affect can ripple downstream to your customers, either affecting the user's ability to zap entirely or potentially rugging users entirely (if a malicious solver offers a low bid and all the other bidders are offline). Openflow believes one of the major strengths of the protocol is that unlike other protocols it is not pay-to-play. Anyone can become a solver.
* Hooks allow EOAs and smart contracts to require custom setup/tear-down logic, essentially enabling an entire keep3r like architecture to exist by incentivizing solvers with any token of the users' choice.
  * A user could submit a swap request where `fromAmount` is any amount (sufficient to cover gas + some incentive) and `fromToken` is any token of their choice, and `toAmount` is zero. In this example the user would also need to turn on the `skipOracle` feature. The user could then define any actions they wish to be executed at all, with conditional logic, that is valid after a specific time or for a duration of a time. The user could even create more orders based on the current post-swap state in a post-swap hook essentially enabling a completely programmable cascading keep3r-like system, supported on the majority of chains.
* Hooks allow a variety of other features where, your imagination is the limit. Pre-swap hooks are actually used by the SDK itself to transfer tokens from sender to settlement before executing an order. This allows the SDK to act as an order delegator on behalf of sender (usually the SDK instance initiator).
* For more information on hooks take a look at the [hooks integration tests](https://github.com/openflow-fi/openflow-contracts/blob/main/test/Hooks.t.sol).

**Zap-in Example**

```solidity
ISettlement.Hooks memory hooks;
hooks.postHooks = new ISettlement.Interaction[](1);
hooks.postHooks[0] = ISettlement.Interaction({
    target: vaultInteractions,
    value: 0,
    data: abi.encodeWithSignature(
        "deposit(address,address)",
        toToken,
        userA
    )
});

ISettlement.Payload memory swap;
swap.fromToken = fromToken;
swaptoToken = toToken;
swap.hooks = hooks;
sdk.submitOrder(swap);
```

#### Zap-out Example

```solidity
ISettlement.Hooks memory hooks;
hooks.preHooks = new ISettlement.Interaction[](1);
preHooks[0] = ISettlement.Interaction({
    target: vaultInteractions,
    value: 0,
    data: abi.encodeWithSignature("withdraw(address)", address(vault))
});
ISettlement.Payload memory swap;
swap.fromToken = fromToken;
swaptoToken = toToken;
swap.hooks = hooks;
sdk.submitOrder(swap);
```

**Hooks Implementation Details**

Under the hood hooks are defined by the user in the swap payload. Hooks are executed during the execution cycle of a swap. Hooks are always executed from the context of the [execution proxy](https://github.com/openflow-fi/openflow-contracts/blob/main/src/Settlement.sol#L268). The reason this is done is to de-couple hook execution from Settlement to limit any potential surface area of attack. **It is not recommended to allow execution proxy to spend your tokens!** Instead, utilize the built in authentication mechanism which validates that the external call made by the execution proxy is authenticated by `sender` in the order's signed payload.

Authenticated `sender` is appended to the transaction data of each hook. To recover `sender` do as follows in your hook target if authentication is required:

```solidity
require(msg.sender == executionProxy, "Only execution proxy");
address signatory;
assembly {
    signatory := shr(96, calldataload(sub(calldatasize(), 20)))
}
require(
    signatory == address(this),
    "Transfer must be initiated from SDK"
);
```

For a real-world example of this see the [SDK Order Delegator](https://github.com/openflow-fi/openflow-contracts/blob/main/src/sdk/OrderDelegator.sol#L19) contract.

### Completely Customized Swaps

The SDK supports additional types of swaps (interval swaps, DCA swaps, stop-loss pattern, etc) which will be documented at a later date.

Finally to submit a completely custom swap do as follows:

```solidity
ISettlement.Payload memory customSwap;
customSwap.fromToken = fromToken; // Required
customSwap.toToken = toToken; // Required
customSwap.fromAmount = fromAmount; // Default is fromToken.balanceOf(sender)
customSwap.toAmount = toAmount; // Default comes from fromAmount, slippage settings and oracle
customSwap.sender = sender; // Default is options.sender
customSwap.recipient = recipient; // Default is options.recipient
customSwap.validFrom = validFrom; // Default is block.timestamp
customSwap.validTo = validTo; // Default is validFrom + options.auctionDuration
customSwap.driver = driver; // Default is options.driver
customSwap.condition = condition; // Default is no condition
customSwap.hooks = hooks; // Default is no hooks
sdk.submitOrder(customSwap);
```

### Questions

If you have any questions or comments please feel free to reach out. Join our [discord server](https://discord.gg/V8mM6qts)!


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://openflow.gitbook.io/openflow/smart-contract-integration/smart-contract-sdk/submit-an-order.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
