SIP-116: Optimism bridge update
Author | |
---|---|
Discussions-To | https://research.synthetix.io/t/optimism-standard-deposit-withdrawa-interface/322 |
Status | Implemented |
Created | 2021-02-25 |
Simple Summary
We propose to make use of the upcoming and last Optimism regenesis, to upgrade the bridge contracts in a way that has no withdrawal downtime. The upgrade would allow future bridge upgrades to also not have any withdrawal downtime, and would make the bridge conform to the new standard bridge interface being adopted by the community.
Abstract
The Ethereum and Optimism bridge contracts, SynthetixBridgeToOptimism
and SynthetixBridgeToBase
, would be replaced with new versions that conform to the new bridge standard. This involves renaming some functions, but keeping the existing functionality mostly intact. The SNX currently deposited in SynthetixBridgeToOptimism
would be transferred to a new SynthetixBridgeEscrow
contract, solely in charge of holding SNX for deposits. This would allow future bridge upgrades to occur without moving any funds, since any bridges in the future would all share the same deposit pool. Additionally, the new contracts would allow to suspend the initiation of deposits or withdrawals, while continuing to allow finalization, which is a feature that currently does not exist in the bridges and necessary for bridge upgrades.
Motivation
The Spartan Council has previously considered upgrading the bridges, but the idea was shelved due to the complication of inter-chain asynchronicity. The problem is that withdrawals that had already been initiated but not yet finalized before the bridge migration, would eventually finalize against the old SynthetixBridgeToOptimism
contract, which would no longer hold the corresponding SNX deposit, and thus fail. As a consequence, the upgrade appeared to be forced to involve suspending withdrawals for a week, and then doing the migration. Alternatives that involved no withdrawal downtime were discussed, but they were all very delicate given the capabilities of the existing bridge contract code. With the upcoming Optimism regenesis, there is an opportunity to perform the upgrade without any withdrawal downtime whatsoever, since Optimism will finalize all ongoing withdrawals just before the upgrade.
Even though the existing bridges don't contain any critical issues that require an immediate upgrade, the proposed upgrade would make future upgrades easier, which should come in handy if there ever any urgency to upgrade.
Specification
Overview
A few changes would need to be made to the bridge contracts, SynthetixBridgeToOptimism
and SynthetixBridgeToBase
, and a new contract SynthetixBridgeEscrow
would need to be created.
The new bridge contracts should be deployed, and the deposit SNX migrated to the new deposit contract.
Rationale
To conform to the new standard bridge interface, the bridge contracts, SynthetixBridgeToOptimism
and SynthetixBridgeToBase
, will have a few functions renamed, and some new functions added. The new functions don't introduce any major functionality, but merely extend the existing functionality with added flexibility.
A new deposit/withdrawal initiation mechanism will be added to the SynthetixBridgeToOptimism
and SynthetixBridgeToBase
. This mechanism will allow a bridge to stop accepting deposit or withdrawal initiation, while still allowing finalization. The idea is that future bridge updates will involve deploying new bridges, while partially disabling the old bridges to allow them to finalize their deposits and withdrawals. Once this happens, they can be disconnected from the SynthetixBridgeEscrow
contract, and thus completely disabled.
The SynthetixBrideToOptimism
contract will be modified so that it no longer holds any SNX, and will instead forward the deposit to the new contract SynthetixBridgeEscrow
. When finalizing a deposit, SynthetixBridgeToOptimism
will have allowance to pull funds from SynthetixBridgeEscrow
.
In terms of the next bridge upgrade, the idea would be that after the new contracts are deployed, the system is suspended, and Optimism finalizes all withdrawals, the old SynthetixBridgeToOptimism
's migrate function will be called, effectively disabling it, and transferring all funds to SynthetixBridgeEscrow
.
Technical Specification - Standard Bridge Interface
SynthetixBridgeToOptimism
should adopt iOVM_L1ERC20Gateway
:
interface iOVM_L1ERC20Gateway {
function deposit(uint _amount) external;
function depositTo(address _to, uint _amount) external;
function finalizeWithdrawal(address _to, uint _amount) external;
event DepositInitiated(address indexed _from, address _to, uint256 _amount);
event WithdrawalFinalized(address indexed _to, uint256 _amount);
}
SynthetixBridgeToBase
should adopt iOVM_L2DepositedERC20
:
interface iOVM_L2DepositedERC20 is IUniswapV2ERC20 {
function withdraw(uint _amount) external;
function withdrawTo(address _to, uint _amount) external;
function finalizeDeposit(address _to, uint _amount) external;
event WithdrawalInitiated(address indexed _from, address _to, uint256 _amount);
event DepositFinalized(address indexed _to, uint256 _amount);
}
The bridges should implement these interfaces, as well as the previously existing ISynthetixBridgeToOptimism
and ISynthetixBridgeToBase
interfaces.
The new interface for SynthetixBridgeToOptimism
should be:
interface ISynthetixBridgeToOptimism {
function migrateEscrow(uint256[][] calldata entryIDs) external;
function depositReward(uint amount) external;
function depositAndMigrateEscrow(uint256 depositAmount, uint256[][] calldata entryIDs) external;
}
The new interface for SynthetixBridgeToBase
should be:
interface ISynthetixBridgeToBase {
function finalizeEscrowMigration(
address account,
uint256 escrowedAmount,
VestingEntries.VestingEntry[] calldata vestingEntries
) external;
function finalizeRewardDeposit(uint amount) external;
}
Technical Specification - New Suspension Mechanism
The same code should be used for both SynthetixBridgeToOptimism
and SynthetixBridgeToBase
.
initiationActive = true // set during contracy deployment
modifier requireInitiationActive() {
depositingActive();
_;
}
function depositingActive() internal view {
require(depositsActive, "Initiation deactivated");
}
function suspendInitiation() external onlyOwner {
initiationActive = false;
emit InitiationSuspended();
}
function resumeInitiation() external onlyOwner {
initiationActive = true;
emit InitiationResumed();
}
Technical Specification - New Bridge Escrow Contract
The bridge would need to access the address of SynthetixBridgeEscrow
, which is going to hold all the deposited SNX on the bridge's behalf. We propose to use the address resolver for this.
bytes32 private constant CONTRACT_SYNTHETIXBRIDGEESCROW = "SynthetixBridgeEscrow";
function synthetixBridgeEscrow() internal view returns (address) {
return requireAndGetAddress(CONTRACT_SYNTHETIXBRIDGEESCROW);
}
When SNX are deposited to the bridge, they should be transferred to SynthetixBridgeEscrow
instead of the bridge itsef:
// move the SNX into SynthetixBridgeEscrow
synthetixERC20().transferFrom(msg.sender, synthetixBridgeEscrow(), amount);
Technical Specification - First SNX Migration
-
First, the new bridges would have to be deployed and connected to the system as part of an official release. This involves both the Ethereum and the Optimism instances to be suspended of course. Ownership of all new contracts is transferred to the Protocol DAO.
-
At this point, Optimism would continue with the regenesis process, and inform Synthetix when all withdrawals have been finalized.
-
Synthetix then calls the old
SynthetixBridgeToOptimism
contract'smigrateBridge(address newBridge)
function, targeting theSynthetixBridgeEscrow
contract. Which transfers all the deposited SNX to the new escrow contract. -
The Protocol DAO, as the owner provides infinite allowance to the new
SynthetixBridgeToOptimism
. -
Systems are resumed.
Test Cases
New test cases:
-
depositTo(address to, uint256 amount)
- Same as
deposit(uint256 amount)
amount, with msg.sender
is account1to
is account2amount
is deduced from account1's balance in L1amount
is minted for account2 on L2
- Same as
-
withdrawTo(address to, uint256 amount)
- Same as
withdraw(uint256 amount)
amount, with msg.sender
is account1to
is account2amount
is deduced from account1's balance in L2amount
is released for account2 on L1
- Same as
-
suspendInitiation()
msg.sender
is should be the contract owner (otherwise the tx should revert)initiationActive
should be set to false- an
InitiationSuspended
event is emitted
-
resumeInitiation()
- Same as
suspendInitiation()
msg.sender
should be the contract owner (otherwise the tx should revert)initiationActive
should be set to false- an
InitiationResumed
event is emitted
- Same as
Configurable Values (Via SCCP)
No new configurable values are involved with the proposed changes.
Copyright
Copyright and related rights waived via CC0.