# Maker contract

### Overview

A **maker contract** is a smart contract bound to an offer on Mangrove.\
When a market order matches that offer, Mangrove calls the maker contract to execute its logic.

Maker contracts define two callbacks:

1. **Trade Execution** — via `makerExecute`
2. **Trade Posthook** — via `makerPosthook`

## Trade Execution

```solidity

function makerExecute(MgvLib.SingleOrder calldata order)
    internal 
    returns (uint gasused, bytes32 makerData);
```

The logic associated with an offer must be implemented in the `makerExecute` callback function. (See data structures for `SingleOrder` type).

### Example

```solidity
import {IERC20, IMaker, SingleOrder} from "@mgv/src/core/MgvLib.sol";


contract MyOffer is IMaker {
    // IMangrove mgv = IMangrove(payable(<address of Mangrove>));
    // Mangrove contract
    IMangrove mgv = IMangrove(payable(mgv));
    address reserve; // token reserve for inbound tokens
    
    // an example of offer execution that simply verifies that `this` contract has enough outbound tokens to satisfy the market order.
    function makerExecute(MgvLib.SingleOrder calldata order) external returns (bytes32 makerData) {
        // revert below (in case of insufficient funds) to signal mangrove we renege on trade
        // reverting as soon as early to minimize bounty
        require(
            IERC20(order.offer.gives()).balanceOf(address(this)) >= order.offer.wants(),
            "MyOffer/NotEnoughFunds");
    
        // do not perform any state changing call if caller is not Mangrove!
        require(msg.sender == mgv, "MyOffer/OnlyMangroveCanCallMe");
        // `order.gives` has been transfered by Mangrove to `this` balance
        // sending incoming tokens to reserve
        IERC20(order.offer.wants()).transfer(reserve, order.offer.gives());
        // this string will be passed to `makerPosthook`
        return "MyOffer/tradeSuccess";
    }
}
```

### Inputs

* **order** — struct containing order execution data:
  * **olKey** — identifies the offer list
    * **outbound\_tkn** — token the offer sends
    * **inbound\_tkn** — token the offer receives
    * **tickSpacing** — spacing between valid ticks
  * **offerId** — Id of the matched offer
  * **offer** — information about the matched offer
  * **takerWants** — amount of outbound tokens the taker wants to receive
  * **takerGives** — amount of inbound tokens the taker gives
  * **offerDetail** — optional detail about the offer (only populated when needed)
  * **global** — snapshot of Mangrove’s global configuration.
  * **local** — snapshot of local (market-level) configuration, cleaned of tick tree info.

> The protocol guarantees that `takerGives / takerWants` matches the offer price within precision limits.

### Outputs

* `gasused` — is the gas consumed by the execution.
* `makerData` — arbitrary data returned by the maker. Passed directly to `makerPosthook`.

### Important Notes

#### **Security**

* Always require `msg.sender == address(Mangrove)`.
* The prev/next pointers from an offer are removed before sending it to the maker. This ensures that the maker has no information about the state of the book when it gets called.

#### **Failing Early**

* To renege on a trade, revert with a string reason (castable to `bytes32`).
* Example: `revert("MyOffer/NotEnoughFunds");`
* Failing later (e.g., after partial execution) increases gas cost and bounty loss.

#### **Gas Efficiency**

* The taker’s bounty is proportional to gas consumed during failure.
* Check conditions early to minimize gas usage on revert.

#### **Reentrancy Protection**

* Mangrove prevents reentrancy during `makerExecute`.

#### **Locked Offer List**

* During `makerExecute`, the offer list is temporarily locked. Offers cannot be added, removed, or updated at this stage. Use `makerPosthook` to modify offers after execution.

## Trade Posthook

After `makerExecute` returns, Mangrove calls the maker’s **posthook** to handle updates or clean-up.

```solidity
function makerPosthook(
    MgvLib.SingleOrder calldata order,
    MgvLib.OrderResult calldata result
  ) external;
```

This function is optional but useful for reposting offers, updating states, or tracking results.

### Example

```solidity
import {IERC20, IMaker, SingleOrder, OrderResult, MgvStructs} from "@mgv/src/core/MgvLib.sol";

abstract contract MakerContract is IMaker {
    // context 
    // IMangrove mgv = IMangrove(payable(<address of Mangrove>));
    // Mangrove contract
    IMangrove mgv = IMangrove(payable(mgv));
    
    // Example of post-hook
    // if market order was a success, try to repost residual offer at the same price
    function makerPosthook(MgvLib.SingleOrder calldata order, MgvLib.OrderResult calldata result) external {
        require (msg.sender == mgv, "posthook/invalid_caller");
        if (result.mgvData == "mgv/tradeSuccess") {
            // retrieving offer data
            // the following call to updateOfferByTick will revert if:
            //    * `this` MakerContract doesn't have enough provision on Mangrove for the offer
            //    * the residual/(GASREQ+offer_gasbase) is below Mangrove's minimal density
            //    * NB : a reverting posthook does not revert the offer execution
            // update the offer with the "ByTick" version
            mgv.updateOfferByTick(
                order.olkey, // same offer list
                order.offer.tick, // same tick
                order.offer.gives() - TickLib.inboundFromOutbound(order.offer.ticktick, order.takerWants()), // what the offer was giving, minus what the taker took (wants)
                order.offerDetail.gasreq(), // keep offer's current gasreq 
                order.offerDetail.gasprice(), // keep offer's current gasprice
                order.offerId // ID of the offer to be updated 
            );
        }
    }
}
```

### Inputs

* `oder` (SingleOrder)
  * is the same as in `makerExecute`.
* `result` (OrderResult) contains:
  * **makerData** — **m**essage returned or revert reason from `makerExecute`.
  * **mgvData** —Internal Mangrove status code — indicates trade result (e.g. "mgv/tradeSuccess", "mgv/offerFail").

### Outputs

None.

### Important Notes

**Security**

* Always ensure:\
  `require(msg.sender == address(Mangrove), "posthook/invalid_caller");`

**Gas Handling**

* The posthook runs with the remaining gas from the offer’s `gasreq`, after subtracting the gas used by `makerExecute`.

**Reposting Offers**

* The offer list is unlocked during `makerPosthook`.\
  You can:
  * Repost the same offer with a new price or volume.
  * Add new offers.
  * Remove or update existing ones.

**Reverting**

* Reverting during `makerPosthook` does not cancel the trade. Settlement from `makerExecute` remains valid.


---

# Agent Instructions: 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:

```
GET https://docs.mangrove.exchange/dev/protocol/technical-references/makers/maker-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
