ReferenceCurve_v1 market whose collateral token is the issuance token of another House market, the base market. The periphery routers (AtomicBuyRouter_v1, AtomicSellRouter_v1, AtomicLoopRouter_v1 and AtomicRepayRouter_v1) trade on both markets in one transaction.
The connected market’s reserve is a balance of the base market’s token, so its prices, fees and loans are all in that token. An address with the base market’s collateral token can buy, sell, loop or repay on the connected market in one router call, with no separate transaction to buy or sell the base market’s token.
Parts of a connected pair
The sell, loop and repay routers fix one base market, connected market and credit facility at deployment. The router code names in the table are the names of those fixed addresses in
AtomicRouterBase_v1.
How a connected market works
Each market is an ordinary market as described in Markets and curves. The connection is only the choice of collateral token.- The connected market’s reserve is a balance of A.
- Its reference price and every step price are in A per B.
- Its buy fee and sell fee are taken in A and go to its fee treasury.
- Its credit facility values locked B at the connected market’s reference price in A, and lends A from the connected market’s reserve (Credit and looping).
- The connected market’s curve and credit facility read prices only from the connected market’s own segments.
- A buy or sell on the connected market moves existing A between the trader and the connected market’s reserve. The base market’s supply and price do not change unless the route also trades on the base market.
- is the deposit, in C
- , with the base market’s buy fee in basis points
- is the A minted by the base market, which becomes the deposit on the connected market
- , with the connected market’s buy fee in basis points
- is the B minted by the connected market
- , are each market’s cost of supply, and , each market’s supply before the route (Cost of supply)
AtomicBuyRouter_v1 with a minimum of 890 A from the first buy and 420 B from the second.
- The base market’s buy fee is 100 bps (1%), and the buy falls within one step priced at 1.10 C per A.
- The connected market’s buy fee is 100 bps (1%). Its supply sits in a step priced at 2.00 A per B with 300 tokens left, and the next step is priced at 2.40.
After the route:
- the base market’s reserve holds 990.00 more C, and A’s supply is 900.00 higher
- the connected market’s reserve holds 891.00 more A, and B’s supply is 421.25 higher
- the base market’s fee treasury holds 10.00 C, and the connected market’s fee treasury holds 9.00 A
- the router holds nothing from the call, so there is no refund
Routers
Shared checks
Errors from these checks are prefixedModule__AtomicRouterBase__. Errors specific to the repay router are prefixed Module__AtomicRepayRouter__.
The sell, loop and repay routers inherit AtomicRouterBase_v1. At deployment it requires that:
- the base market, connected market and credit facility are contracts
- C, A and B are three different contracts
- the connected market’s collateral token is A, and the credit facility belongs to the connected market
- The receiver cannot be the zero address, the router, either market or the facility.
- The input amount must be above 0.
- The call reverts if the deadline is before the current block time. A call at the deadline runs.
- Each executed leg needs a minimum output above 0.
- The router records its own balances of C, A and B before pulling input. After each leg, a balance below that record reverts the call. At the end, every balance must equal the record, or the call reverts.
- A token pull that delivers a different amount from the one requested reverts.
- Each leg approves the market for the exact amount and clears the approval after the leg.
AtomicBuyRouter_v1 does not inherit the base. It runs its own version of these checks, described below.
AtomicBuyRouter_v1
buyExactInput(firstMarket, secondMarket, amountIn, minIntermediateOut, minFinalOut, receiver, deadline)
- Checks the inputs. Both markets must be contracts and different from each other. The receiver cannot be the zero address or the router.
- Reads the tokens. The second market’s collateral token must equal the first market’s issuance token. The first market’s collateral token must differ from its issuance token.
- Pulls
amountInof the first market’s collateral token from the caller. - Calls
buyForon the first market, with the router as receiver andminIntermediateOutas the minimum. - Calls
buyForon the second market with all the tokens the first buy minted, withreceiveras receiver andminFinalOutas the minimum. - Sends any unspent collateral token and any unspent intermediate token back to the caller. Unspent amounts come from a buy that reaches the end of a curve.
Reverts (errors prefixed
Module__AtomicBuyRouter__): InvalidMarket, InvalidAddress, InvalidAmount, InvalidMinimumOutput, ExpiredDeadline, InvalidToken, IncompatibleMarkets, UnsupportedTokenAlias, UnsupportedTokenBehavior (the pull delivered a different amount), UnexpectedBalanceChange, InsufficientIntermediateOutput, InsufficientFinalOutput, plus any revert from either market’s buy.
AtomicSellRouter_v1
sellExactInput(amountIn, minIntermediateOut, minFinalOut, receiver, deadline)
- Pulls
amountInof B from the caller. - Calls
sellToon the connected market, with the router as receiver andminIntermediateOutas the minimum. The router receives A. - Calls
sellToon the base market with all that A, withreceiveras receiver andminFinalOutas the minimum. - Requires that no A or C is left on the router, and emits
Sold.
Reverts: the shared checks,
InsufficientOutput, UnexpectedResidue (A or C left on the router), plus any revert from either market’s sell.
AtomicLoopRouter_v1
loopExactInput(params)
- Pulls
amountInof C from the caller. - Calls
buyForon the base market, with the router as receiver. - Calls
buyAndBorrowForon the credit facility with all that A. The new loans belong toreceiver. At the end of the loop, the facility returns the A it still holds to the router (Looping). - Emits
Loopedwith each new loan’s ID, loan amount and locked tokens. - Exits the A left over.
ToCollateralcallssellToon the base market and pays C toreceiver.ReinvestcallsbuyForon the connected market and mints B toreceiver; this B is not locked. - Settles. C left on the router goes to the caller. A left on the router goes to
receiverif it is at or belowmaxKnxFallback.
InvalidAmount (loops is 0), ExitClosed (the exit’s direction is closed, checked even when no A is left over), InvalidMinimumOutput, InsufficientOutput, FallbackExceeded (A left over above maxKnxFallback), UnexpectedResidue (B left on the router), plus any revert from either market or the facility.
AtomicRepayRouter_v1
repayExactInput(params)
- Pulls
amountInof C from the caller. - Calls
buyForon the base market, with the router as receiver. - Reads the loan. It must be active. With
closeAndExitset, the caller must be the loan’s borrower. - Calls
repayForon the credit facility with all that A. The facility repays at most the loan amount and sends the released B to the loan’s borrower, not to the caller. - With
closeAndExitset, requires that the loan is closed with a loan amount of 0. - Sells the A not used for the repayment on the base market and pays C to the caller.
- With
closeAndExitset, pulls the released B from the caller, sells it on the connected market for A, and sells that A on the base market for C, paid to the caller. - Settles. C left on the router goes to the caller. A left on the router goes to the caller if it is at or below
maxKnxFallback. EmitsRepaid.
InvalidLoan, CallerNotOwner, LoanNotClosed, ExitClosed (selling on the base market is closed, checked even when no A is left), InvalidMinimumOutput, InsufficientOutput, FallbackExceeded, UnexpectedResidue, plus any revert from either market or the facility, including repayFor reverting for a loan held by the early-access escrow.
Parameters
The routers have no settable parameters. The sell, loop and repay routers fix their market set in the constructor, and it cannot be changed. Each connected market’s own parameters are set as for any market (Markets and curves, Credit and looping).Permissions the routers need
The routers have no access check of their own. Any address can call them. Each market sees the router as the caller, so the router address needs the permission for every market function it calls.
The launch route leaves
buyFor, sellTo, buyAndBorrowFor and repayFor ungranted. DeployPeripheryRouters_v1 deploys the sell, loop and repay routers for one market set, grants no permissions, and reverts unless each router already holds the permissions in the table. A grant to a router opens that function to every address that calls the router. Authority lists every role.
Edge cases
- Each leg is an ordinary trade. Each market’s trading switches, fees, endowment gates and rounding apply to its leg (Markets and curves). A closed switch on either market reverts a route that trades on it.
- Buy past capacity. When a buy reaches the end of a curve, the market refunds the unspent deposit to the router.
AtomicBuyRouter_v1returns it to the caller; the other routers return refunded C to the caller at settlement. - Zero-output exit. In the loop and repay routers, an exit trade whose quote rounds to zero is skipped when the A left over is at or below
maxKnxFallback. That A goes to the receiver at settlement. - Released B on repayment. A repayment through
AtomicRepayRouter_v1sends released B to the loan’s borrower, whoever pays. - Whole-route revert. Any revert in any leg reverts the whole call, including the input pull.
Code
Source:
house-markets/contracts at 0ebbc89a (branch integration/v12-post-qa).