Delayed withdrawals
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
We need to make sure that senders cannot front-run recipients that detect double spends (i.e. receiving a winning ticket resulting in a macropayment except the sender's `deposit` is insufficient to cover the macropayment) by withdrawing their `penaltyEscrow` right before a recipient's transaction which indicates a double spend (resulting in the slashing of the `penaltyEscrow`) is confirmed on-chain.
We can prevent this front-run attack with delayed withdrawals. The contract defines a parameter `unlockPeriod` (an example value could be 1 week worth of blocks) which is set when the contract is deployed. When senders want to withdraw its `deposit` and `penaltyEscrow` they can call `unlock()` which
- Transitions the sender from the `Locked` state to `Unlocking` state until `withdrawBlock = block.number + unlockPeriod`. The sender must wait until `withdrawBlock` in order to withdraw its `deposit` and `penaltyEscrow`.
- Emits a `Unlock` event. Recipients that are currently accepting tickets from the sender can watch for this event. When this event is emitted, recipients can cash all their winning tickets on-chain and slash the sender for any detected double spends knowing that the sender cannot move its funds until `withdrawBlock`. Furthermore, recipients can stop working with the sender once they see this event.
At `withdrawBlock`, the sender transitions from the `Unlocking` state to the `Unlocked` state and the sender can then call `withdraw` which
- Transfers the sender's remaining `deposit` and `penaltyEscrow` to the sender's account
- Zeros out the contract storage used for the sender
If the sender wants to cancel a withdrawal, it can call `cancelUnlock()` which will transition the sender from the `Unlocking` state to the `Locked` state preventing a future withdrawal. Alternatively, if the sender calls `deposit()` in order to add more funds, the sender will also transition from the `Unlocking` state to the `Locked` state.
Note: While this delayed withdrawal scheme can prevent a sender from prematurely withdrawing its `penaltyEscrow` to front-run recipients that detect double spends, it cannot stop a sender from generating a winning ticket for another account (remember that the randomness generation for a ticket is collaborative so if the sender is also the recipient the sender can always generate winning tickets) that it owns which then cashes the winning ticket to transfer funds from `deposit` to the new account. The primary scenario where this could happen is if a sender wants to front-run a recipient to double spend by giving the recipient a valid winning ticket, but then emptying out the sender's `deposit` before the recipient can cash the winning ticket. In this case, the recipient would detect a double spend and slash the sender's `penaltyEscrow`. Thus, preventing this type of attack is a matter of ensuring sender's have `penaltyEscrow` values that can actually deter double spends which we can address separately.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No files or tests are named. Start by locating the contract's sender state machine and the existing deposit and withdrawal entry points, then trace how balances and events are handled. Done means the specified delayed-withdrawal states, timing, cancellation, event emission, and balance transfers are implemented and covered by tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- blockchain, payments, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100