Post a Smart Offer
Last updated
Last updated
In this tutorial, you will learn how to post a managed by your own that simply stores and tokens on its balance.
The tutorial assumes knowledge of solidity development.
Follow to create a new tutorial
folder.
Open your favorite solidity editor inside that folder.
It is assumed that the ADMIN_ADDRESS
has enough native tokens to complete the steps. (If you're using the foundry setup in then the ADMIN_ADDRESS
is set to one of the Foundry test addresses with some native tokens.)
We want to create a new contract OfferMakerTutorial
to implement an and utilize the Direct
contract in our strat-library for this purpose. Direct
provides a safety harness to make it easier to correctly interact with Mangrove, you can read more about it .
Start by creating a new OfferMakerTutorial.sol
file in the src
folder, and add the following pieces:
Add the imports we are going to need, along with a standard solidity preamble.
Next, add the contract and the code for the constructor.
OfferMakerTutorial.sol - Contract and constructor
Add the below code to your contract.
OfferMakerTutorial.sol - Offer management functions
OfferMakerTutorial.sol - Emit in Posthook
The contract is now complete - you can see the full example by following the links to github.
But before deploying it on-chain, we should test it!
First, compile the contract:
Before proceeding, import the environment variables made as part of the preparation
Start Foundry's local node anvil
to test things locally before broadcasting to the real chain, with $RPC_URL
coming from .env
and pointing, for instance, to the Polygon network.
Start another terminal and import environment variables again
Now, create the OfferMakerTutorial
contract on the anvil
node with your private key by pointing to its local rpc-url
, and supplying the parameters for Mangrove core contract (get it from Addresses for the network you have forked).
You can also add it to your .env
file.
Note: you might need to add the
--legacy
argument.
The output should look like:
Take a note of the Deployed to
address and save it in a variable:
In this tutorial, we will use the WBTC/DAI market.
Make sure to set variables with the tokens address into your .env
file.
Note: the example token addresses are for the Polygon Mumbai testnet.
We have to let Mangrove pull the outbound token from our new contract - we can use the activate
function for that.
Instead of trying to parse the logs, we can make a note of the transactionHash
at the end of the output and use local execution to see the offerId
returned by newOffer
.
Which would output the following tail:
0x0000000000000000000000000000000000000000000000000000000000000002
is the offer id.
If the offer was now taken, it will fail to deliver the promised liquidity. It promises up to 1 WBTC, but the contract has no WBTC to deliver. We can fix this by sending some WBTC to the contract:
If you do not have the liquidity in your wallet, check Getting tokens below, and come back to this step afterwards.
Note : One of the big benefits of Mangrove is that liquidity does not have to be locked in - we will have a look at that in the Unlocking Liquidity guide.
If the admin (acting as a maker) does not have required WBTC tokens then the smart offer will fail when taken.
Note: this true in this particular case where we need to lock liquidity in our contract - that's how we designed it. Using a %%router|router%%, you can unlock your funds, and your offer could still be posted - your smart offer can source liquidity elsewhere on-chain.
In a similar fashion, we can make use of the updateOffer
function inside our contract. We will need the offer ID from earlier - let's add it in a variable:
Now, we can update our offer, for example by changing the amount of WBTC we give to 0.1:
Note : To update an offer, here's something to keep in mind:
To change the volume offered => change gives
(example above)
To change the price of the offer => change tick
To change both volume and price => change gives
and tick
We can also remove our offer from the book, using retractOffer
. Note that we don't need to provide a provision in this case, since we are pulling the offer off the market. We will actually get back our provision with that configuration.
You could publish the contract on mainnet by stopping Anvil and replacing the --rpc-url $LOCAL_URL
in the above create
, activate
, and approve
commands with --rpc-url $RPC_URL
- and finally, the newOffer
with sensible prices.
To get a view of the order book, the Mangrove UI can be used, or you can use the SDK.
To get a better understanding of how tokens flow between taker, maker, Mangrove, and maker contracts like OfferMakerTutorial
, see Mangrove Offer.
You can also add more features (such as reneging trades or unlocking/reactive liquidity) to your smart offer by looking at the next sections of this doc!
At some point, you will need to measure the gas requirements of your smart offers - this page will give you pointers on how to do this.
We will skip some details here, which you can read more about later; , , and .
Note: we also implement the ILiquidityProvider
interface which makes the contract compatible with what the expects.
The abstract contract Direct
has internal functions that allows one to manage offers: _newOffer
for posting offers, _updateOffer
for updating existing offers and _retractOffer
for unpublishing offers from Mangrove. We need to expose these functions in a restricted manner, so that only the administrator of the contract can manage offers. We expose them through functions matching the interface.
See for an explanation of the parameters for posting an offer.
Also see , , and .
When using our new contract, we can inspect traces and addresses but illustrative purposes, let's insert the following to emit an event in the when the offer is successfully taken.
There are more hooks to enable the Mangrovian abilities of and more advanced .
Now that the contract is ready, we can use it to post an offer - note that we have to the offer, and we do that by sending some native tokens to newOffer
.
In our example, we are offering 1 WBTC (gives) at tick 50 (tick 50 means the price ratio is 1.0001^50
).
Note :
Later, if you'd like to take your own offer with a market order for testing purpose, it would be handy to have your offer at the very top of the book (i.e. with the best price possible). To do this, you could post your offer with the smallest tick (-887272
), or use the constant in your test contract.
If you don't have any WBTC, you can get some by using the following commands (taken from ), or the corresponding faucet. Just look for a token holder with large amounts of WBTC - you can check the list on Polygonscan. Also, remember to add the chosen address under $LUCKY_USER
in your .env
file.