1 · Seller: make a link
On the home page, fill in:
- Your address: where the payout goes. Type it or press Use wallet.
- Amount in ETH: exactly what the buyer locks.
- Terms: a short text (up to 280 characters) of what the buyer pays for.
- Deadline (UTC) and what happens if nobody acts by then: refund buyer or pay seller.
- Arbiter (optional): someone both sides trust, who can release or refund.
You get a link like /d/#seller=0x…&amount=…&terms=…&deadline=…&arbiter=&x=0. Nothing is on-chain yet and nothing is stored on our server: the link itself carries the deal. Send it to the buyer.
2 · Buyer: lock the ETH
Opening the link shows the amount, the terms, the deadline rule and the arbiter. Connect a wallet and press Lock. That calls open(seller, arbiter, deadline, expiryPaysSeller, keccak256(terms)) with the exact amount (at least 0.0001 ETH), and the deal gets an id. You land on /deal/?id=N. Send that page to the seller.
3 · Seller: accept
The seller opens the deal page, checks the on-chain terms (amount, arbiter, deadline, deadline rule, and that the terms text matches the stored hash) and presses Accept before the deadline. That calls accept(id).
Sellers: accept on-chain first, deliver after. Before you accept, the buyer can cancel at any time and take the ETH back.
Acceptance protects the seller. The buyer is the one who sends the funding transaction, so the buyer could fund the deal with an arbiter or deadline the seller never agreed to. Until the seller accepts: the arbiter has no power, the buyer can cancel (cancel(id), full refund, no fee), and a passed deadline always refunds the buyer.
4 · Release, refund, settle
- Release (buyer any time while open; arbiter only after acceptance): the seller is paid, minus the fee.
- Refund (seller any time while open; arbiter only after acceptance): the buyer gets everything back, no fee.
- Settle (anyone, after the deadline): if the seller accepted, the deal ends the way the link said (pay the seller or refund the buyer); if not, the buyer is refunded.
A deal ends once. After a release or a refund nothing else can happen to it.
5 · Withdraw
Payouts are pull-based. A release, refund or cancel credits the receiver inside the contract; they press Withdraw on any deal page to receive the ETH (withdraw(), or withdrawTo(address) to send it elsewhere). This keeps one failing wallet from blocking anyone else.
Limits
- Deadline: at least 1 hour and at most 180 days from the moment the buyer funds. A link whose deadline is under an hour away can no longer be funded.
- Buyer, seller and arbiter must be different addresses. No arbiter = the zero address.
- Amount: at least 0.0001 ETH (
MIN_AMOUNT). - The seller must accept before the deadline, or the deal can only end in a refund.
- ETH only. No tokens in escrow.
- Only the hash of the terms text is stored. Keep the link: it is the readable copy, and the deal page checks it against the hash.
- The contract does not know if work was done. The buyer, the seller and the arbiter decide that.
Fees and staking
The fee is 0.5% of payouts to the seller (release, or a deadline that pays the seller). Refunds are free. The fee is fixed when the contract is deployed; it cannot be changed.
Fees go into a 7-day stream to $HASPS stakers, paid in ETH. The stream is topped up automatically on each release (and sync() still exists for anyone to call). Claim with claim() or claimTo(address). Stake, unstake and claim on the stake page. The $HASPS address is set once after launch; before that staking is closed.
No admin
The contract has no admin; only a one-time setToken. There is no owner, no pause, no upgrade and no function that moves escrowed ETH except release, refund, cancel and settle. setToken can be called once, by the deployer 0xBC8A51f38BD60C50089560E0BaAC4daA9182C6f5, and only accepts a token whose symbol() is HASPS. It only switches staking on. The token's own rules (supply, tax, transfers) are outside this contract.
Not audited
The contract has not been audited by a third party; it had an internal review only. It is short and public, and it was tested, but bugs are possible. Start with amounts you can afford to lose. Haspline cannot reverse a transaction, recover a deal or settle a dispute for you.
Contract
- Network
- Robinhood Chain
- Chain id
- 4663
- Address
- Contract deploys before launch
Functions
open(address seller, address arbiter, uint64 deadline, bool expiryPaysSeller, bytes32 terms) payable → idaccept(id)·cancel(id)·release(id)·refund(id)·settleExpired(id)·withdraw()·withdrawTo(address)deals(id) → (buyer, seller, arbiter, amount, deadline, expiryPaysSeller, state, terms, accepted), state 1 open, 2 released, 3 refundedMIN_AMOUNT()·dealCount()·credits(address)·feeBps()·totalEscrowed()·totalCredits()- Staking:
token()·stake(amount)·unstake(amount)·claim()·claimTo(address)·sync()·earned(address)·staked(address)·totalStaked()·rewardRate()·periodFinish()·pendingFees()
Events: Opened, Accepted, Released, Refunded, Withdrawn, TokenSet, Staked, Unstaked, Claimed, Synced.
Times
All times on this site are UTC. Deadlines are unix timestamps on-chain.