Address Contract Verified
Address
0x94da8A995D0D82Ef0fE7E509C6D76c22603B6f67
Balance
0 ETH
Nonce
1
Code Size
4116 bytes
Creator
0x8ab6D03b...4F4b at tx 0x22849619...bb34b9
Indexed Transactions
0
Contract Bytecode
4116 bytes
0x608060409080825260049081361015610016575f80fd5b5f3560e01c9081631e52192714610d53575080632539162414610d36578063253b153b146108c457806331a94da314610695578063389b8b3a1461054557806355f29166146104645780635a99719e1461041e5780636b131e06146103f9578063999f0be2146102eb578063a836f4c9146102a8578063ac0d925c1461028a578063c3d1770614610259578063c3f59687146101bd578063c727927f1461017a578063c8a446671461015d578063d4d543c51461011e5763f1ce598e146100db575f80fd5b3461011a57602036600319011261011a57359060025482101561011a576001600160a01b0361010b602093610dfd565b92905490519260031b1c168152f35b5f80fd5b50903461011a575f36600319011261011a5760ff60035416905190600381101561014a57602092508152f35b602183634e487b7160e01b5f525260245ffd5b823461011a575f36600319011261011a576020905f549051908152f35b823461011a575f36600319011261011a57602090516001600160a01b037f00000000000000000000000092b12c9d85bf7bd2ef5d2f53f4cd4ce0be432045168152f35b503461011a57602036600319011261011a576101d7610d9e565b916101e133610f65565b6001600160a01b03831615610216577fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103839055005b906020606492519162461bcd60e51b8352820152600260248201527f31640000000000000000000000000000000000000000000000000000000000006044820152fd5b503461011a57602036600319011261011a57359060055482101561011a576001600160a01b0361010b602093610db4565b823461011a575f36600319011261011a576020906006549051908152f35b823461011a575f36600319011261011a57602090516001600160a01b037f0000000000000000000000003b4d794a66304f130a4db8f2551b0070dfcf5ca7168152f35b50903461011a57602036600319011261011a57610306610d9e565b9061031033610f65565b60ff6003541660038110156103e6576103a457506002546001600160a01b03918216926801000000000000000082101561039157508060016103559201600255610dfd565b819291549060031b9184831b921b19161790556006547fecfd8b4d8bfc0590001d923f6db32faaad4c3d96097734fe5950f43980dabfc45f80a3005b604190634e487b7160e01b5f525260245ffd5b5162461bcd60e51b8152602081840152600560248201527f61706331310000000000000000000000000000000000000000000000000000006044820152606490fd5b602184634e487b7160e01b5f525260245ffd5b823461011a575f36600319011261011a57602090610415610e81565b90519015158152f35b823461011a575f36600319011261011a576020906001600160a01b037fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610354915191168152f35b503461011a575f36600319011261011a5761047e33610f65565b60035460ff8116600381101561014a5715610502577ff2b18f8abbd8a0d0c1fb8245146eedf5304887b12f6395b548ca238e054a148360205f94621baf809081875551908152a18260015560ff1916600355556104d9610e32565b6006547f55cd34119fd31f1a8cc60aad1098023b450274eef2294e3e1b6dd452d58ce6fd5f80a2005b506020606492519162461bcd60e51b8352820152600560248201527f63707531310000000000000000000000000000000000000000000000000000006044820152fd5b503461011a57602036600319011261011a57600154801561065257813503610610576001600160a01b037f00000000000000000000000092b12c9d85bf7bd2ef5d2f53f4cd4ce0be4320451633036105ce57505f546105a057005b60207ff2b18f8abbd8a0d0c1fb8245146eedf5304887b12f6395b548ca238e054a1483915f8055515f8152a1005b6020606492519162461bcd60e51b8352820152600260248201527f70330000000000000000000000000000000000000000000000000000000000006044820152fd5b6020606492519162461bcd60e51b8352820152600260248201527f70320000000000000000000000000000000000000000000000000000000000006044820152fd5b506020606492519162461bcd60e51b8352820152600260248201527f70310000000000000000000000000000000000000000000000000000000000006044820152fd5b50903461011a576020908160031936011261011a5767ffffffffffffffff91833583811161011a576106ca9036908601610d6d565b9390946106d633610f65565b6003549160ff8316600381101561014a57610882576002548603610840576001809342825560ff1916176003554282558511610391576801000000000000000085116103915750600554846005558085106107fe575b50928460055f525f905b8282106107b55750506006549381845194808601908652526060840195915f5b81811061078b575f85870152867fabce748366d7d01473824f1bee75dc176759f56b88f00253e4a10d7528ca806f878a0388a2005b909192968735906001600160a01b03821680920361011a5790815284019684019291908201610756565b8095929535916001600160a01b038316830361011a578484920192817f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001550190949194610736565b81857f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db092830192015b82811061083557505061072c565b5f8155018290610827565b6064828587519162461bcd60e51b8352820152600560248201527f73707531320000000000000000000000000000000000000000000000000000006044820152fd5b6064828587519162461bcd60e51b8352820152600560248201527f73707531310000000000000000000000000000000000000000000000000000006044820152fd5b503461011a576020918260031936011261011a5767ffffffffffffffff90823582811161011a576108f89036908501610d6d565b909461090333610f65565b60039360ff85541685811015610d23576002809103610ce1576002548403610c9f576001600160a01b039385517f02cfb56300000000000000000000000000000000000000000000000000000000815284818a81897f0000000000000000000000003b4d794a66304f130a4db8f2551b0070dfcf5ca7165afa908115610c95575f91610c3d575b50610bfb5790977ff2b18f8abbd8a0d0c1fb8245146eedf5304887b12f6395b548ca238e054a148384621baf80805f558851908152a16001985f8a55895f905b610a99575b50505050506006545f198114610a86579580919392960192836006558251928184019082855260055480925284019760055f527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0925f915b838310610a6f57505050505050807f48bc8be43b04d57da4f0d65c05db98278a94d9e90b7348d5d2705cc78c9a9d2e915f960390a2805460ff1916905555610a6d610e32565b005b845481168b52998101999385019391850191610a27565b601186634e487b7160e01b5f525260245ffd5b81549085811691821015610bf557859188610ab383610db4565b9054908d1b1c169081610ae6575b505016848114610ad3578a018a6109ca565b60118a634e487b7160e01b5f525260245ffd5b9091925085898c610af686610dfd565b9054911b1c16911015610be257681fffffffffffffffe08360051b16850135601e198636030181121561011a5785019182359288841161011a57890190833603821361011a57823b1561011a578b928e5f809486518098819682957f6fc491400000000000000000000000000000000000000000000000000000000084528301526024988983015280604483015280606493848401378181018301849052601f01601f191681010301925af18015610bd857908793929115610ac1579091928211610bc75750885284905f80610ac1565b60418c634e487b7160e01b5f52525ffd5b8a513d5f823e3d90fd5b60328c634e487b7160e01b5f525260245ffd5b506109cf565b6064888588519162461bcd60e51b8352820152600560248201527f66707531330000000000000000000000000000000000000000000000000000006044820152fd5b9050843d8611610c8e575b601f8101601f1916820185811183821017610c7b57869183918a528101031261011a5751801515810361011a575f61098a565b60418b634e487b7160e01b5f525260245ffd5b503d610c48565b87513d5f823e3d90fd5b6064878487519162461bcd60e51b8352820152600560248201527f66707531320000000000000000000000000000000000000000000000000000006044820152fd5b6064878487519162461bcd60e51b8352820152600560248201527f66707531310000000000000000000000000000000000000000000000000000006044820152fd5b602187634e487b7160e01b5f525260245ffd5b50903461011a575f36600319011261011a57602091549051908152f35b3461011a575f36600319011261011a576020906001548152f35b9181601f8401121561011a5782359167ffffffffffffffff831161011a576020808501948460051b01011161011a57565b600435906001600160a01b038216820361011a57565b600554811015610de95760055f527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001905f90565b634e487b7160e01b5f52603260045260245ffd5b600254811015610de95760025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace01905f90565b6005545f60055580610e415750565b60055f527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0908101905b818110610e76575050565b5f8155600101610e6b565b610e8a33610f65565b60035460ff81166003811015610f5157600103610f0d576004544210610f085760ff19166002176003556001545f548101908110610ef457421061011a576006547fd2b7d4a4a2b38481e36a9b8198af8b427261011fd199b7a1b7cb8f437aa25acd5f80a2600190565b634e487b7160e01b5f52601160045260245ffd5b505f90565b606460405162461bcd60e51b815260206004820152600560248201527f75677031310000000000000000000000000000000000000000000000000000006044820152fd5b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035416911603610f9a57565b606460405162461bcd60e51b815260206004820152600260248201527f31630000000000000000000000000000000000000000000000000000000000006044820152fdfea264697066735822122012eb6af821620109335e391b200016e975f60124760da25948f2682767ef332f64736f6c63430008190033
Verified Source Code Full Match
Compiler: v0.8.25+commit.b61c2a91
EVM: cancun
Optimization: Yes (1000 runs)
IZkLighterDesertMode.sol 12 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.25;
/// @title zkLighter DesertMode Interface
/// @author zkLighter Team
interface IZkLighterDesertMode {
/// @notice thrown when DesertMode is active
error ZkLighter_DesertModeActive();
function desertMode() external view returns (bool);
}
IUpgradeable.sol 12 lines
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.25;
/// @title Interface of the upgradeable contract
/// @author Matter Labs (https://github.com/matter-labs/zksync/blob/master/contracts/contracts/Upgradeable.sol)
interface IUpgradeable {
/// @notice Upgrades target of upgradeable contract
/// @param newTarget New target
/// @param newTargetInitializationParameters New target initialization parameters
function upgradeTarget(address newTarget, bytes calldata newTargetInitializationParameters) external;
}
IUpgradeEvents.sol 26 lines
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.25;
/// @title Upgrade events
/// @author Matter Labs (https://github.com/matter-labs/zksync/blob/master/contracts/contracts/Events.sol)
interface IUpgradeEvents {
/// @notice Event emitted when new upgradeable contract is added to upgrade gatekeeper's list of managed contracts
event NewUpgradable(uint256 indexed versionId, address indexed upgradeable);
/// @notice Upgrade mode enter event
event NoticePeriodStart(
uint256 indexed versionId,
address[] newTargets,
uint256 noticePeriod // notice period (in seconds)
);
/// @notice Upgrade mode cancel event
event UpgradeCancel(uint256 indexed versionId);
/// @notice Upgrade mode preparation status event
event PreparationStart(uint256 indexed versionId);
/// @notice Upgrade mode complete event
event UpgradeComplete(uint256 indexed versionId, address[] newTargets);
}
Ownable.sol 50 lines
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.25;
/// @title Ownable Contract
/// @author Matter Labs (https://github.com/matter-labs/zksync/blob/master/contracts/contracts/Ownable.sol)
contract Ownable {
/// @dev Storage position of the masters address (keccak256('eip1967.proxy.admin') - 1)
bytes32 private constant MASTER_POSITION = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/// @notice Contract constructor
/// @dev Sets msg sender address as masters address
/// @param masterAddress Master address
constructor(address masterAddress) {
require(masterAddress != address(0), "1b"); // oro11 - master address can't be zero address
setMaster(masterAddress);
}
/// @notice Check if specified address is master
/// @param _address Address to check
function requireMaster(address _address) internal view {
require(_address == getMaster(), "1c"); // oro11 - only by master
}
/// @notice Returns contract masters address
/// @return master Master's address
function getMaster() public view returns (address master) {
bytes32 position = MASTER_POSITION;
assembly {
master := sload(position)
}
}
/// @dev Sets new masters address
/// @param _newMaster New master's address
function setMaster(address _newMaster) internal {
bytes32 position = MASTER_POSITION;
assembly {
sstore(position, _newMaster)
}
}
/// @notice Transfer mastership of the contract to new master
/// @param _newMaster New masters address
function transferMastership(address _newMaster) external {
requireMaster(msg.sender);
require(_newMaster != address(0), "1d"); // otp11 - new masters address can't be zero address
setMaster(_newMaster);
}
}
UpgradeGatekeeper.sol 123 lines
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.25;
import "./IUpgradeEvents.sol";
import "./Ownable.sol";
import "./IUpgradeable.sol";
import "../UpgradeableMaster.sol";
/// @title Upgrade Gatekeeper Contract
/// @author Matter Labs (https://github.com/matter-labs/zksync/blob/master/contracts/contracts/UpgradeGatekeeper.sol)
/// Modified to implement UpgradeableMaster, since Proxy no longer implements the interface
contract UpgradeGatekeeper is UpgradeableMaster, IUpgradeEvents, Ownable {
/// @notice Array of addresses of upgradeable contracts managed by the gatekeeper
IUpgradeable[] public managedContracts;
/// @notice Upgrade mode statuses
enum UpgradeStatus {
Idle,
NoticePeriod,
Preparation
}
UpgradeStatus public upgradeStatus;
/// @notice Notice period finish timestamp (as seconds since unix epoch)
/// @dev Will be equal to zero in case of not active upgrade mode
uint256 public noticePeriodFinishTimestamp;
/// @notice Addresses of the next versions of the contracts to be upgraded (if element of this array is equal to zero address it means that appropriate upgradeable contract wouldn't be upgraded this time)
/// @dev Will be empty in case of not active upgrade mode
address[] public nextTargets;
/// @notice Version id of contracts
uint256 public versionId;
/// @notice Contract constructor
/// @param _securityCouncilAddress Security council address
/// @param _zkLighterProxy ZkLighter proxy address for desert mode checks to disable upgrades
/// @dev Calls Ownable contract constructor
constructor(
address _securityCouncilAddress,
address _zkLighterProxy
) UpgradeableMaster(_securityCouncilAddress, _zkLighterProxy) Ownable(msg.sender) {
versionId = 0;
}
/// @notice Adds a new upgradeable contract to the list of contracts managed by the gatekeeper
/// @param addr Address of upgradeable contract to add
function addUpgradeable(address addr) external {
requireMaster(msg.sender);
require(upgradeStatus == UpgradeStatus.Idle, "apc11"); /// apc11 - upgradeable contract can't be added during upgrade
managedContracts.push(IUpgradeable(addr));
emit NewUpgradable(versionId, addr);
}
/// @notice Starts upgrade (activates notice period)
/// @param newTargets New managed contracts targets (if element of this array is equal to zero address it means that appropriate upgradeable contract wouldn't be upgraded this time)
function startUpgrade(address[] calldata newTargets) external {
requireMaster(msg.sender);
require(upgradeStatus == UpgradeStatus.Idle, "spu11"); // spu11 - unable to activate active upgrade mode
require(newTargets.length == managedContracts.length, "spu12"); // spu12 - number of new targets must be equal to the number of managed contracts
uint256 noticePeriod = getNoticePeriod();
upgradeNoticePeriodStarted();
upgradeStatus = UpgradeStatus.NoticePeriod;
noticePeriodFinishTimestamp = block.timestamp + noticePeriod;
nextTargets = newTargets;
emit NoticePeriodStart(versionId, newTargets, noticePeriod);
}
/// @notice Cancels upgrade
function cancelUpgrade() external {
requireMaster(msg.sender);
require(upgradeStatus != UpgradeStatus.Idle, "cpu11"); // cpu11 - unable to cancel not active upgrade mode
upgradeCanceled();
upgradeStatus = UpgradeStatus.Idle;
noticePeriodFinishTimestamp = 0;
delete nextTargets;
emit UpgradeCancel(versionId);
}
/// @notice Activates preparation status
/// @return Bool flag indicating that preparation status has been successfully activated
function startPreparation() external returns (bool) {
requireMaster(msg.sender);
require(upgradeStatus == UpgradeStatus.NoticePeriod, "ugp11"); // ugp11 - unable to activate preparation status in case of not active notice period status
if (block.timestamp >= noticePeriodFinishTimestamp) {
upgradeStatus = UpgradeStatus.Preparation;
upgradePreparationStarted();
emit PreparationStart(versionId);
return true;
} else {
return false;
}
}
/// @notice Finishes upgrade
/// @param targetsUpgradeParameters New targets upgrade parameters per each upgradeable contract
function finishUpgrade(bytes[] calldata targetsUpgradeParameters) external {
requireMaster(msg.sender);
require(upgradeStatus == UpgradeStatus.Preparation, "fpu11"); // fpu11 - unable to finish upgrade without preparation status active
require(targetsUpgradeParameters.length == managedContracts.length, "fpu12"); // fpu12 - number of new targets upgrade parameters must be equal to the number of managed contracts
require(isReadyForUpgrade(), "fpu13"); // fpu13 - main contract is not ready for upgrade
upgradeFinishes();
for (uint64 i = 0; i < managedContracts.length; i++) {
address newTarget = nextTargets[i];
if (newTarget != address(0)) {
managedContracts[i].upgradeTarget(newTarget, targetsUpgradeParameters[i]);
}
}
versionId++;
emit UpgradeComplete(versionId, nextTargets);
upgradeStatus = UpgradeStatus.Idle;
noticePeriodFinishTimestamp = 0;
delete nextTargets;
}
}
UpgradeableMaster.sol 98 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.25;
import "./interfaces/IZkLighterDesertMode.sol";
/// @title Upgradeable Master Contract
/// @author zkLighter Team
/// @dev UpgradeableMaster is used by the UpgradeGatekeeper when upgrading contracts.
/// It is controlled by the security council. The whole state of the contract is read only.
/// It's indented to be inherited by the UpgradeGatekeeper. Due to this, all methods which are used in the flow of
/// deploying updates are internal.
/// It has 2 main roles:
/// - It delays the deployment of upgrades by at most 3 weeks, in case the upgrade is malicious.
/// This gives users enough time to withdraw the funds using full exit operation from the system.
/// - It stops any upgrade if the system has entered desert mode.
contract UpgradeableMaster {
/// @notice Notice period changed
event NoticePeriodChange(uint256 newNoticePeriod);
/// @dev Notice period before activation of the upgrade (in seconds)
/// @dev NOTE: Gives users enough time to send full exit requests if the upgrade is malicious
uint256 internal constant UPGRADE_NOTICE_PERIOD = 3 weeks;
/// @dev Upgrade notice period, possibly shorten by the security council
uint256 public approvedUpgradeNoticePeriod;
/// @dev Upgrade start timestamp
/// @dev Will be equal to zero if there is no active upgrade
uint256 public upgradeStartTimestamp;
/// @dev Instead of keeping a list of council members and requiring approval from all of them,
/// keep just one council member to simplify the workflow. The council member itself could be a multi signature wallet
address public immutable securityCouncilAddress;
/// @dev zkLighter contract used to detect if system is in desert mode. If desert mode is detected, upgrades are not allowed
IZkLighterDesertMode public immutable zkLighterProxy;
constructor(address _securityCouncilAddress, address _zkLighterProxy) {
require(_zkLighterProxy != address(0), "c1");
securityCouncilAddress = _securityCouncilAddress;
zkLighterProxy = IZkLighterDesertMode(_zkLighterProxy);
approvedUpgradeNoticePeriod = UPGRADE_NOTICE_PERIOD;
emit NoticePeriodChange(approvedUpgradeNoticePeriod);
}
/// @notice Minimum notice period before setting the activation preparation for the upgrade
function getNoticePeriod() internal pure returns (uint256) {
return 0;
}
/// @notice Sets the upgradeStartTimestamp when an upgrade starts
function upgradeNoticePeriodStarted() internal {
upgradeStartTimestamp = block.timestamp;
}
/// @notice Checks if the upgrade preparation has started for the current upgrade
function upgradePreparationStarted() internal view {
require(block.timestamp >= upgradeStartTimestamp + approvedUpgradeNoticePeriod);
}
/// @dev Clears the current upgrade when upgrade is finished or canceled
function clearUpgradeStatus() internal {
approvedUpgradeNoticePeriod = UPGRADE_NOTICE_PERIOD;
emit NoticePeriodChange(approvedUpgradeNoticePeriod);
upgradeStartTimestamp = 0;
}
/// @notice Clears the upgrade status when the upgrade is canceled
function upgradeCanceled() internal {
clearUpgradeStatus();
}
/// @notice Clears the upgrade status when the upgrade is finished
function upgradeFinishes() internal {
clearUpgradeStatus();
}
/// @notice Checks if the contract can be upgraded (does not allow upgrades in desert mode)
/// @return bool flag indicating that contract is ready for upgrade
function isReadyForUpgrade() internal view returns (bool) {
return !zkLighterProxy.desertMode();
}
/// @notice Allows security council to decrease upgrade notice period time to 0
/// @dev Can only be called after the start of the upgrade (getNoticePeriod)
function cutUpgradeNoticePeriod(uint256 _upgradeStartTimestamp) external {
require(upgradeStartTimestamp != 0, "p1");
require(upgradeStartTimestamp == _upgradeStartTimestamp, "p2"); // given target is not the active upgrade
require(msg.sender == securityCouncilAddress, "p3"); // only security council can call this
// decrease upgrade notice period time to zero
if (approvedUpgradeNoticePeriod > 0) {
approvedUpgradeNoticePeriod = 0;
emit NoticePeriodChange(approvedUpgradeNoticePeriod);
}
}
}
Read Contract
approvedUpgradeNoticePeriod 0xc8a44667 → uint256
getMaster 0x5a99719e → address
managedContracts 0xf1ce598e → address
nextTargets 0xc3d17706 → address
noticePeriodFinishTimestamp 0x25391624 → uint256
securityCouncilAddress 0xc727927f → address
upgradeStartTimestamp 0x1e521927 → uint256
upgradeStatus 0xd4d543c5 → uint8
versionId 0xac0d925c → uint256
zkLighterProxy 0xa836f4c9 → address
Write Contract 7 functions
These functions modify contract state and require a wallet transaction to execute.
addUpgradeable 0x999f0be2
address addr
cancelUpgrade 0x55f29166
No parameters
cutUpgradeNoticePeriod 0x389b8b3a
uint256 _upgradeStartTimestamp
finishUpgrade 0x253b153b
bytes[] targetsUpgradeParameters
startPreparation 0x6b131e06
No parameters
returns: bool
startUpgrade 0x31a94da3
address[] newTargets
transferMastership 0xc3f59687
address _newMaster
Recent Transactions
No transactions found for this address