Docs

How it works.

Three steps: the buyer funds, the seller accepts, the buyer releases. Everything Haspline does, in the order you meet it. The contract is small; this page describes all of it.

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 → id
  • accept(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 refunded
  • MIN_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.