HandleEscrow
HandleEscrow sends ETH or ERC-20 tokens to a handle. It pays the handle’s
owner at once, or holds the funds until the owner proves the handle and
claims them. It reads owners from IdentityNames. See
Send funds to a handle for a walkthrough.
The full source is HandleEscrow.sol.
Tokens
Section titled “Tokens”NATIVE() returns 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, the address
the escrow uses for ETH (EIP-7528).
Any other token address is treated as an ERC-20.
Each token is held as one pool. These tokens do not work:
- Tokens that charge a fee to the sender on
transfer. Deposits work, but every claim and refund revertsOverDebited. - Tokens whose balances change on their own (rebasing tokens).
- Tokens that can block the escrow’s address. A block freezes the funds.
Functions
Section titled “Functions”deposit
Section titled “deposit”function deposit(bytes32 platformId, bytes32 handleHash, address token, uint256 amount, address refundTo) payablePays amount of token to a handle. handleHash is keccak256 of the
normalized handle (IdentityNames.handleHashOf, or handleHash in the
TypeScript package).
- If someone owns the handle, they are paid now and
Forwardedis emitted. - Otherwise the funds are held and
Depositedis emitted.refundTocan take them back until the owner claims.
For ETH, msg.value must equal amount. For a token, approve the escrow
first and send no ETH.
The escrow cannot check the hash. A wrong hash holds the funds where nobody
can claim them; only refundTo can get them back.
function claim(bytes32 handleNode, address[] tokens, address recipient)Sends everything held for the handle, in each of tokens, to recipient.
The caller must be the handle’s owner (IdentityNames.byHandle). Tokens with
nothing held are skipped. Reverts NothingHeld if nothing was paid.
After a claim, earlier deposits can no longer be refunded.
refund
Section titled “refund”function refund(bytes32 handleNode, address token, address recipient)Sends the caller’s own deposits for the handle, in one token, to recipient.
Only deposits made since the last claim can be refunded. Works whether or not
the handle has an owner.
escrowed
Section titled “escrowed”function escrowed(bytes32 handleNode, address token) view returns (uint256)How much is held for the handle in one token right now.
refundable
Section titled “refundable”function refundable(bytes32 handleNode, address token, address refundTo) view returns (uint256)How much refund would pay refundTo right now.
function names() view returns (address)The IdentityNames contract this escrow reads. It is set once and cannot be
changed.
Events
Section titled “Events”event Deposited( bytes32 indexed handleNode, address indexed token, address indexed refundTo, address depositor, bytes32 platformId, uint256 round, uint256 amount);event Forwarded( bytes32 indexed handleNode, address indexed token, address indexed depositor, address holder, bytes32 platformId, uint256 amount, uint256 received);event Claimed( bytes32 indexed handleNode, address indexed token, address indexed claimer, address recipient, uint256 round, uint256 released, uint256 received);event Refunded( bytes32 indexed handleNode, address indexed token, address indexed refundTo, address recipient, uint256 round, uint256 released, uint256 received);round groups deposits between claims. A claim ends a round, and the next
deposit starts the next one. A Refunded belongs to the deposits of its
round.
amount in Deposited is what arrived. released is what left the escrow’s
books, and received is what the recipient gained. They differ only for
tokens that take a fee.
Claimed and Refunded do not include the platform. Join them with
Deposited on handleNode.
Errors
Section titled “Errors”| Error | When |
|---|---|
ZeroAmount() | amount is zero, or nothing arrived. |
ValueMismatch(uint256 expected, uint256 provided) | msg.value does not match. |
BadRefundTo(address refundTo) | refundTo is zero or the escrow. |
PayingYourself(address holder) | You own the handle you are paying. |
PlatformAcceptsNoBindings(bytes32 platformId) | Nobody owns the handle and the platform accepts no new proofs, so the funds could never be claimed. |
NotTheHolder(address holder, address caller) | claim was called by someone other than the owner. |
NothingHeld(bytes32 handleNode) | claim found nothing in any listed token. |
NothingToRefund(bytes32 handleNode, address token, address refundTo) | The caller has nothing to refund in this round. |
BadRecipient(address recipient) | recipient is zero or the escrow. |
OverDebited(address token, uint256 booked, uint256 debited) | The token took more than the escrow booked. |
NativeTransferFailed(address recipient, uint256 amount) | The recipient rejected ETH. |
Admin functions
Section titled “Admin functions”The owner can upgrade the escrow with upgradeToAndCall. The owner cannot
change which IdentityNames it reads.