-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MD-14 #14
Open
0xPrimata
wants to merge
3
commits into
main
Choose a base branch
from
primata/bridge-timelock-as-state
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
MD-14 #14
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# MD-14: Bridge Should Use A More Secure Timelock | ||
- **Description**: Provide formal structure for proposing non-trivial improvements to Movement. | ||
- **Authors**: [Primata](mailto:[email protected]) | ||
|
||
## Overview | ||
|
||
The Bridge is arguably the most important feature of an L2 and lately we have had a confusing approach to it. We might want to solidify our understanding of how it is to be used and the assumptions we rely on. Off-loading the Bridge Relayer from securing timestamps might be important here in terms of security and preventing it from being an attack vector. | ||
|
||
## Definitions | ||
|
||
* Timelock - Time delta between the current block time and the end-of-lock time. | ||
* Bridge Relayer - formerly referred as the bridge service, it's the infrastructure utilized to have some form of synchronicity of the bridge request state. Single point of failure. | ||
* Initiator Contract - Contract the user utilizes to initialze the bridge and the bridge relayer completes or refunds the user. Exists both on Ethereum and Movement. | ||
* Counterparty Contract - Contract the user completes the bridge and the bridge relayer locks or cancels the bridge. Exists both on Ethereum and Movement. | ||
|
||
|
||
## Desiderata | ||
|
||
1. | ||
2. Because it has to be lower than the Initiator Contract Timelock, whenever Timelock is consumed, it is consumed as `timelock`. | ||
3. Definitely use timestamps for the sake of synchronicity between Ethereum and Movement. | ||
4. Remove dependency of the Bridge Relayer on processing the desired timelock. | ||
|
||
### D1: Initiator Contract Timelock is a constant or a modifiable state with a minimum time | ||
**User Journey**: Whenever Timelock is consumed, it is consumed as `timelock * 2`. If a modifiable state, it should be at least 12 hours. | ||
|
||
**Justification**: Because it has to be higher than the Counterparty Contract Timelock, `timelock * 2` is reasonable. A modifiable state should have some form to prevent malicious attacks. If lowering becomes a necessity, an upgrade to the contract will solve the issue. `timelock * 2` consumption also introduces a requirement from the design which stipulates that the initiator timelock has to be significantly higher than the counterparty to assure that a bridge transfer cannot be completed on the target chain and cancelled on the origin chain. | ||
|
||
### D2: Counterparty Contract Timelock is a constant or a modifiable variable with a minimum time | ||
**User Journey**: Bridge Relayer locks the bridge transfer on the Counterparty side. It does not specify the timelock. The timelock is specified by the timelock state or constant in the Ethereum Initiator Contract or Movement Initiator Contract. | ||
|
||
**Justification**: Because it has to be higher than the Counterparty Contract Timelock, `timelock` is reasonable. A modifiable state should have some form to prevent malicious attacks. If lowering becomes a necessity, an upgrade to the contract will solve the issue. | ||
|
||
### D3: Use timestamps instead of block number | ||
0xPrimata marked this conversation as resolved.
Show resolved
Hide resolved
|
||
**User Journey**: This has already been agreed, but by using timestamp, there is no necessity to handle block.number parity between chains. | ||
|
||
**Justification**: For cross bridge synchronocity between Ethereum and Movement which have very distinct block numbers and block settlement speed. | ||
0xPrimata marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### D4: Remove dependency of the Bridge Relayer on processing the desired timelock. | ||
**User Journey**: Bridge Relayer stops having any decision how the timelock timestamp. It is fully provided by the contracts and modules variables. | ||
|
||
**Justification**: We are heavily relying on the Bridge Relayer's capabilities to not fail and this should make the Bridge Relayer less error prone. | ||
|
||
|
||
**Guidance and suggestions**: | ||
|
||
Ethereum contracts: | ||
``` | ||
uint256 public timelock = 1 days; | ||
... | ||
function setTimelock (uint256 newTimelock) external onlyOwner { | ||
if (newTimelock < 12 hours) revert MinimumTimelockError(); | ||
timelock = newTimelock; | ||
} | ||
``` | ||
Movement Modules: | ||
``` | ||
struct BridgeConfig has key { | ||
moveth_minter: address, | ||
bridge_module_deployer: address, | ||
signer_cap: account::SignerCapability, | ||
timelock: u64 | ||
} | ||
... | ||
move_to(resource,BridgeConfig { | ||
moveth_minter: signer::address_of(resource), | ||
bridge_module_deployer: signer::address_of(resource), | ||
signer_cap: resource_signer_cap, | ||
timelock: 12 hours | ||
}); | ||
``` | ||
|
||
handle consumption depending on the condition on if it's an initiator or a counterparty | ||
|
||
## Errata |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the idea here is to not relay any timestamp information in, right?
Instead we simply assume the bridge relay has sent the time-lock information over as quickly as it can and use the timestamp from the destination chain when the relay transaction is received.
This removes the trust on any clock in the bridge service, thus making it harder to manipulate.
The tradeoff is perhaps that the attacker can now attack by forcing delays on the bridge. But, these could be easier to detect than lock manipulations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one reason why we need a minimum time bound. Maybe an upper bound might be necessary just so that a user couldn't have funds stuck in the bridge for type(uint).max time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in the difference between the reported timestamp and the timestamp at the time the relay transaction is received?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
timelock = 20
initiator receiving a bridge at time 0
counterparty lock is called at 5
initiator completes at 10
counterparty completes at 15
It would be an issue if:
iinitiator receiving a bridge at time 0
counterparty lock is called at 21
counterparty completes at 40
initiator cancels at 41
This is already an issue with the current implementation if the Bridge Relayer fails at some certain levels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only makes sense when you have quite short timelocks and the actual act of calling over the network could cause them to expire incorrectly.