The first time we showed the order ticket to an outside trader, he leaned forward and said: where's the sell button. We spent ten minutes explaining why there isn't one in the way he expected, and at the end of it he said the design made sense and was also strange enough that we should write something about it. So this is that.
The short version: on GM Markets, a stop-loss is not a separate order you place after a buy. It is an attachment to the buy itself. You set the entry as a market buy, and in the same ticket you set the price at which you want the position closed. The keeper holds the closing leg until the trigger fires. There is no place in the interface to set a stop loss against a position you already hold without going through this ticket. That's not because we forgot the feature. It's because the architecture wouldn't honor it the way the trader expected.
Worth walking through why.
The default mental model
Traders coming from a centralized exchange or a traditional broker have a deep muscle memory for the way order entry works. You buy. The position lives in your account. Later, you place a separate stop-loss order against that position. The exchange's matching engine watches for the trigger price and fires the close when it hits. The two orders are independent. You can cancel either one without affecting the other.
That model assumes the exchange owns both the position and the trigger logic. It does. In a centralized exchange, your shares (or your token balance) sit in an omnibus the exchange controls, and the matching engine has full custody of the trigger. The exchange can fire the stop because it can move the asset.
That assumption breaks the moment the asset is in your wallet.
What changes when the position is wallet-native
A tokenized stock on GM Markets sits in your wallet. Not in our omnibus. Not in our database. In the wallet you control. We do not have custody of it after the buy completes. We cannot fire a sell against it without your signature.
That's the wedge. To trigger a future sell, we need either a signature from the user every time the trigger condition might be met (which is unworkable, because the user is asleep), or a pre-signed authorization that the keeper can use when the trigger fires. We chose the second.
The pre-signed authorization is the bracket. When you place a market buy with a stop-loss attached, you are signing two things at the moment of entry. One: a buy. Two: a conditional sell that fires only at the price you specified. The keeper holds the conditional sell, watches the price feed, and submits it on-chain when the condition is met. No further user interaction.
If we let you place a stop-loss after the buy, we'd need a second signature. That's a second wallet popup. That's a second confirmation. That's a second moment when the user might be away from the keyboard. The product would feel broken in exactly the situation it was designed for.
So we forced the bracket at entry time. One ticket, one signature, two legs.
Why the side is locked to buy
The other thing that confuses traders is that the only side they can enter is buy. There is no sell button on the ticket.
The reason is structural. To sell a tokenized stock, you need to already own it. You can already do that, by interacting with the burn function on the token contract, or by going through the redemption flow in the wallet. What you can't do, and what an exchange-style sell button would imply, is sell something you don't yet own. We don't run a matching engine. We don't take the other side. There's no place in the architecture for a naked short.
So the order ticket only does the thing the architecture supports: a buy, optionally with a future-sell trigger attached. The future-sell trigger is the part traders read as a stop-loss. From the trader's seat, it looks like a stop-loss on a position. From the architecture's seat, it's the second leg of a pre-signed bracket. Same effect, different shape.
The keeper is the unsung piece
The thing that makes the whole design work is the keeper. The keeper is an in-house process that watches price feeds and submits the conditional sell on-chain when the trigger fires. We picked in-house deliberately. We did not want to depend on Chainlink or Gelato for execution, because the keeper sometimes has to act in seconds and we wanted ownership of the latency budget end to end. We can talk about why somewhere else.
What matters here is that the keeper doesn't custody anything. It holds the pre-signed message. It cannot move the asset without the trigger being met. It cannot fire a sell at any price other than the one specified at entry. The user's signature constrains it. If the keeper goes offline, the worst case is that the trigger doesn't fire on time. The user's funds are not at risk, just the trigger.
What this design costs
I want to be honest about what we give up by doing this.
You cannot, in our system, set a stop-loss on a position you've held for a month. You can only set one at entry. If you want stop-loss protection on an existing position, you have to sell out and re-buy with the bracket attached, which is a real friction and one that we hear about regularly. We are working on a way to handle this without breaking the architecture. The honest answer is that the version that ships first is going to be a re-bracket flow, not a true post-hoc stop, because the post-hoc version requires a custody primitive we haven't built yet.
You also cannot have multiple brackets on the same position. Each buy is its own bracket. If you buy in three increments, you have three brackets, and they each have their own trigger price. Some traders find this useful. Some find it confusing.
These are real costs. I'm not going to pretend otherwise. The trade we made was: accept these costs to keep the asset wallet-native and the architecture trust-minimized, rather than rebuild the centralized-exchange order book on top of a tokenized asset and lose the property that made the asset interesting in the first place.
Where this lands
The design feels strange to anyone whose muscle memory is centralized-exchange order entry. It feels natural to anyone whose muscle memory is DeFi, where pre-signed permits and conditional execution are normal. We are mostly building for the second group, and gradually retraining the first.
I think the right test for whether the design is working is not whether traders find it familiar, but whether they trust it. The ones who have used it for a while don't ask for a sell button anymore. They ask for re-bracket on existing positions. That's a request I take seriously, because it means they've internalized the architecture and are pushing on the edges of what it can do.
I might be wrong about some of the second-order tradeoffs. The biggest one I keep turning over is whether a true post-hoc stop-loss is buildable without giving up the wallet-native property. There's probably a path through using delegated permits, but we haven't shipped it yet, and I don't want to commit to a timeline I'm not sure I can hold. The shape of the design is going to keep moving. The thing I'm confident about is that the asset stays in the user's wallet, and the bracket is the price we pay for that.
