-
Notifications
You must be signed in to change notification settings - Fork 126
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
add delayed upgrade #2735
base: release_loopring_3.6.3
Are you sure you want to change the base?
add delayed upgrade #2735
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,11 +14,14 @@ abstract contract ILoopringV3 is Claimable | |
event ExchangeStakeDeposited(address exchangeAddr, uint amount); | ||
event ExchangeStakeWithdrawn(address exchangeAddr, uint amount); | ||
event ExchangeStakeBurned(address exchangeAddr, uint amount); | ||
event SettingsUpdated(uint time); | ||
event SettingsUpdated(uint time, uint effectTime); | ||
event SettingsApplied(uint time); | ||
|
||
// == Public Variables == | ||
uint256 internal constant SETTING_UPDATE_DELAY = 7 days; | ||
mapping (address => uint) internal exchangeStake; | ||
|
||
uint public nextEffectiveTime; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will change the data storage layout table and break upgradeability!!!!! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. loopringv3 is not deployed using proxy mode There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because it has no |
||
uint public totalStake; | ||
address public blockVerifierAddress; | ||
uint public forcedWithdrawalFee; | ||
|
@@ -29,6 +32,14 @@ abstract contract ILoopringV3 is Claimable | |
|
||
address payable public protocolFeeVault; | ||
|
||
struct CachedSettings { | ||
address protocolFeeVault; | ||
address blockVerifierAddress; | ||
uint forcedWithdrawalFee; | ||
} | ||
|
||
CachedSettings internal cachedSettings; | ||
|
||
// == Public Functions == | ||
|
||
/// @dev Returns the LRC token address | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,11 +17,13 @@ contract BlockVerifier is ReentrancyGuard, IBlockVerifier | |
struct Circuit | ||
{ | ||
bool registered; | ||
uint registeredTime; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will you deploy a new BlockVerifier or upgrade an existing deployment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blockverifier is the same case There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But you are modifying the code, so what did you mean "is the same"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry for my confused statement. I mean that block verifier also cannot be deployed by using proxy mode like in loopringv3 so that only way to upgrade smart contract is to deploy a new one. so the disorder of storage of it doesn't matter. |
||
bool enabled; | ||
uint[18] verificationKey; | ||
} | ||
|
||
mapping (uint8 => mapping (uint16 => mapping (uint8 => Circuit))) public circuits; | ||
uint internal constant CIRCUIT_DELAYED_EFFECT = 7 days; | ||
|
||
constructor() Claimable() {} | ||
|
||
|
@@ -44,7 +46,8 @@ contract BlockVerifier is ReentrancyGuard, IBlockVerifier | |
circuit.verificationKey[i] = vk[i]; | ||
} | ||
circuit.registered = true; | ||
circuit.enabled = true; | ||
circuit.registeredTime = block.timestamp; | ||
// NOTE: circuit is disabled by default | ||
|
||
emit CircuitRegistered( | ||
blockType, | ||
|
@@ -77,6 +80,25 @@ contract BlockVerifier is ReentrancyGuard, IBlockVerifier | |
); | ||
} | ||
|
||
function enableCircuit( | ||
uint8 blockType, | ||
uint16 blockSize, | ||
uint8 blockVersion | ||
) external override nonReentrant onlyOwner { | ||
Circuit storage circuit = circuits[blockType][blockSize][blockVersion]; | ||
require(circuit.registered == true, "NOT_REGISTERED"); | ||
require(circuit.enabled == false, "ALREADY_ENABLED"); | ||
require( | ||
block.timestamp >= circuit.registeredTime + CIRCUIT_DELAYED_EFFECT, | ||
"NOT_EFFECT_YET" | ||
); | ||
|
||
// Enable the circuit | ||
circuit.enabled = true; | ||
|
||
emit CircuitDisabled(blockType, blockSize, blockVersion); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is enabled ,can add an event |
||
} | ||
|
||
function verifyProofs( | ||
uint8 blockType, | ||
uint16 blockSize, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,7 +34,7 @@ contract LoopringV3 is ILoopringV3, ReentrancyGuard | |
|
||
lrcAddress = _lrcAddress; | ||
|
||
updateSettingsInternal(_protocolFeeVault, _blockVerifierAddress, 0); | ||
updateSettingsInternal(_protocolFeeVault, _blockVerifierAddress, 0, 0); | ||
} | ||
|
||
// == Public Functions == | ||
|
@@ -51,7 +51,8 @@ contract LoopringV3 is ILoopringV3, ReentrancyGuard | |
updateSettingsInternal( | ||
_protocolFeeVault, | ||
_blockVerifierAddress, | ||
_forcedWithdrawalFee | ||
_forcedWithdrawalFee, | ||
SETTING_UPDATE_DELAY + block.timestamp | ||
); | ||
} | ||
|
||
|
@@ -67,7 +68,7 @@ contract LoopringV3 is ILoopringV3, ReentrancyGuard | |
protocolTakerFeeBips = _protocolTakerFeeBips; | ||
protocolMakerFeeBips = _protocolMakerFeeBips; | ||
|
||
emit SettingsUpdated(block.timestamp); | ||
emit SettingsUpdated(block.timestamp, 0); | ||
} | ||
|
||
function getExchangeStake( | ||
|
@@ -159,17 +160,50 @@ contract LoopringV3 is ILoopringV3, ReentrancyGuard | |
function updateSettingsInternal( | ||
address payable _protocolFeeVault, | ||
address _blockVerifierAddress, | ||
uint _forcedWithdrawalFee | ||
uint _forcedWithdrawalFee, | ||
uint _nextEffectiveTime | ||
) | ||
private | ||
{ | ||
require(address(0) != _protocolFeeVault, "ZERO_ADDRESS"); | ||
require(address(0) != _blockVerifierAddress, "ZERO_ADDRESS"); | ||
require( | ||
_forcedWithdrawalFee <= 0.5 ether, | ||
"FORCED_WITHDRAWAL_FEE_TOO_HIGH" | ||
); | ||
|
||
if (_nextEffectiveTime == 0) { | ||
// effect immediately | ||
protocolFeeVault = _protocolFeeVault; | ||
blockVerifierAddress = _blockVerifierAddress; | ||
forcedWithdrawalFee = _forcedWithdrawalFee; | ||
} else { | ||
// delayed effect | ||
cachedSettings = CachedSettings({ | ||
protocolFeeVault: _protocolFeeVault, | ||
blockVerifierAddress: _blockVerifierAddress, | ||
forcedWithdrawalFee: _forcedWithdrawalFee | ||
}); | ||
nextEffectiveTime = _nextEffectiveTime; | ||
} | ||
|
||
emit SettingsUpdated(block.timestamp, _nextEffectiveTime); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should not modify current event, can add another event which only update but not effect |
||
} | ||
|
||
function applyUpdate() external onlyOwner { | ||
// TODO(add ownership check) | ||
require(nextEffectiveTime > 0, "NO_ANY_UPDATES"); | ||
require(nextEffectiveTime <= block.timestamp, "NOT_ENABLED_YET"); | ||
|
||
protocolFeeVault = payable(cachedSettings.protocolFeeVault); | ||
blockVerifierAddress = cachedSettings.blockVerifierAddress; | ||
forcedWithdrawalFee = cachedSettings.forcedWithdrawalFee; | ||
|
||
// clear updates | ||
nextEffectiveTime = 0; | ||
|
||
protocolFeeVault = _protocolFeeVault; | ||
blockVerifierAddress = _blockVerifierAddress; | ||
forcedWithdrawalFee = _forcedWithdrawalFee; | ||
delete cachedSettings; | ||
|
||
emit SettingsUpdated(block.timestamp); | ||
emit SettingsApplied(block.timestamp); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
// Copyright 2017 Loopring Technology Limited. | ||
pragma solidity ^0.8.2; | ||
|
||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
|
||
/** | ||
* @title DelayedImplementationManager | ||
* @author Kongliang Zhong - <[email protected]> | ||
*/ | ||
contract DelayedImplementationManagerV2 is Ownable { | ||
address public currImpl; | ||
address public nextImpl; | ||
uint public nextEffectiveTime; | ||
|
||
event UpgradeScheduled(address nextImpl, uint effectiveTime); | ||
event UpgradeCancelled(address nextImpl); | ||
event ImplementationChanged(address newImpl); | ||
|
||
constructor(address initImpl) { | ||
require(initImpl != address(0), "ZERO_ADDRESS"); | ||
currImpl = initImpl; | ||
} | ||
|
||
/** | ||
* @dev Allows the proxy owner to upgrade the current version of the proxy. | ||
* @param _nextImpl representing the address of the next implementation to be set. | ||
* @param _daysToDelay representing the amount of days after the next implementation take effect. | ||
*/ | ||
function delayedUpgradeTo( | ||
address _nextImpl, | ||
uint _daysToDelay | ||
) public onlyOwner { | ||
if (_nextImpl == address(0)) { | ||
require( | ||
nextImpl != address(0) && _daysToDelay == 0, | ||
"INVALID_ARGS" | ||
); | ||
emit UpgradeCancelled(nextImpl); | ||
nextImpl = address(0); | ||
} else { | ||
// remove it only for test | ||
// require(_daysToDelay >= 1, "INVALID_DAYS"); | ||
// solhint-disable-next-line not-rely-on-time | ||
uint _nextEffectiveTime = block.timestamp + _daysToDelay * 1 days; | ||
nextImpl = _nextImpl; | ||
nextEffectiveTime = _nextEffectiveTime; | ||
emit UpgradeScheduled(_nextImpl, _nextEffectiveTime); | ||
} | ||
} | ||
|
||
/** | ||
* @dev Allows everyone to replace implementation after effective time. | ||
*/ | ||
function executeUpgrade() public { | ||
require( | ||
// solhint-disable-next-line not-rely-on-time | ||
nextImpl != address(0) && block.timestamp >= nextEffectiveTime, | ||
"NOT_IN_EFFECT" | ||
); | ||
currImpl = nextImpl; | ||
nextImpl = address(0); | ||
emit ImplementationChanged(currImpl); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
// Copyright 2017 Loopring Technology Limited. | ||
pragma solidity ^0.8.2; | ||
|
||
import "@openzeppelin/contracts/proxy/Proxy.sol"; | ||
import "./DelayedImplementationManager.sol"; | ||
|
||
/** | ||
* @title ForwardProxy | ||
* @author Kongliang Zhong - <[email protected]> | ||
*/ | ||
contract ForwardProxyV2 is Proxy { | ||
DelayedImplementationManagerV2 public immutable implManager; | ||
|
||
constructor(address _implManager) { | ||
require(_implManager != address(0), "ZERO_ADDRESS"); | ||
implManager = DelayedImplementationManagerV2(_implManager); | ||
} | ||
|
||
function _implementation() internal view override returns (address) { | ||
return implManager.currImpl(); | ||
} | ||
} |
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.