-
Notifications
You must be signed in to change notification settings - Fork 317
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
30a1467
commit 96b4acd
Showing
4 changed files
with
308 additions
and
0 deletions.
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,66 @@ | ||
// SPDX-License-Identifier: AGPL-3.0 | ||
pragma solidity 0.8.17; | ||
|
||
import "../PolygonZkEVM.sol"; | ||
|
||
/** | ||
* Contract responsible for managing the state and the updates of the L2 network | ||
* This contract will NOT BE USED IN PRODUCTION, will be used only in testnet enviroment | ||
*/ | ||
contract PolygonZkEVMUpgraded is PolygonZkEVM { | ||
// Indicates the current version | ||
uint256 public version; | ||
|
||
// Last batch before the last upgrade, should check it inside the _proofDifferentState function | ||
uint256 public lastBatchBeforeUpgrade; | ||
|
||
// Indicates the last version before upgrade | ||
uint256 public immutable VERSION_BEFORE_UPGRADE; | ||
|
||
/** | ||
* @param _globalExitRootManager Global exit root manager address | ||
* @param _matic MATIC token address | ||
* @param _rollupVerifier Rollup verifier address | ||
* @param _bridgeAddress Bridge address | ||
* @param _chainID L2 chainID | ||
*/ | ||
constructor( | ||
IPolygonZkEVMGlobalExitRoot _globalExitRootManager, | ||
IERC20Upgradeable _matic, | ||
IVerifierRollup _rollupVerifier, | ||
IPolygonZkEVMBridge _bridgeAddress, | ||
uint64 _chainID, | ||
uint64 _forkID, | ||
uint256 versionBeforeUpgrade | ||
) | ||
PolygonZkEVM( | ||
_globalExitRootManager, | ||
_matic, | ||
_rollupVerifier, | ||
_bridgeAddress, | ||
_chainID, | ||
_forkID | ||
) | ||
{ | ||
VERSION_BEFORE_UPGRADE = versionBeforeUpgrade; | ||
} | ||
|
||
/** | ||
* @dev Thrown when try to update version when it's already updated | ||
*/ | ||
error VersionAlreadyUpdated(); | ||
|
||
/** | ||
* @notice Update version of the zkEVM | ||
* @param _versionString New version string | ||
*/ | ||
function updateVersion(string memory _versionString) public { | ||
if (version != VERSION_BEFORE_UPGRADE) { | ||
revert VersionAlreadyUpdated(); | ||
} | ||
version++; | ||
|
||
lastBatchBeforeUpgrade = lastVerifiedBatch; | ||
emit UpdateZkEVMVersion(lastVerifiedBatch, forkID, _versionString); | ||
} | ||
} |
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
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,40 @@ | ||
Contract responsible for managing the state and the updates of the L2 network | ||
This contract will NOT BE USED IN PRODUCTION, will be used only in testnet enviroment | ||
|
||
|
||
## Functions | ||
### constructor | ||
```solidity | ||
function constructor( | ||
contract IPolygonZkEVMGlobalExitRoot _globalExitRootManager, | ||
contract IERC20Upgradeable _matic, | ||
contract IVerifierRollup _rollupVerifier, | ||
contract IPolygonZkEVMBridge _bridgeAddress, | ||
uint64 _chainID | ||
) public | ||
``` | ||
|
||
|
||
#### Parameters: | ||
| Name | Type | Description | | ||
| :--- | :--- | :------------------------------------------------------------------- | | ||
|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRoot | Global exit root manager address | ||
|`_matic` | contract IERC20Upgradeable | MATIC token address | ||
|`_rollupVerifier` | contract IVerifierRollup | Rollup verifier address | ||
|`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address | ||
|`_chainID` | uint64 | L2 chainID | ||
|
||
### updateVersion | ||
```solidity | ||
function updateVersion( | ||
string _versionString | ||
) public | ||
``` | ||
Update version of the zkEVM | ||
|
||
|
||
#### Parameters: | ||
| Name | Type | Description | | ||
| :--- | :--- | :------------------------------------------------------------------- | | ||
|`_versionString` | string | New version string | ||
|
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,201 @@ | ||
/* eslint-disable no-plusplus, no-await-in-loop */ | ||
const { expect } = require('chai'); | ||
const { ethers, upgrades } = require('hardhat'); | ||
|
||
describe('PolygonZkEVMUpgraded', () => { | ||
let deployer; | ||
let trustedAggregator; | ||
let trustedSequencer; | ||
let admin; | ||
|
||
let verifierContract; | ||
let polygonZkEVMBridgeContract; | ||
let polygonZkEVMContract; | ||
let maticTokenContract; | ||
let polygonZkEVMGlobalExitRoot; | ||
|
||
const maticTokenName = 'Matic Token'; | ||
const maticTokenSymbol = 'MATIC'; | ||
const maticTokenInitialBalance = ethers.utils.parseEther('20000000'); | ||
|
||
const genesisRoot = '0x0000000000000000000000000000000000000000000000000000000000000001'; | ||
|
||
const networkIDMainnet = 0; | ||
const urlSequencer = 'http://zkevm-json-rpc:8123'; | ||
const chainID = 1000; | ||
const networkName = 'zkevm'; | ||
const version = '0.0.1'; | ||
const forkID = 0; | ||
const pendingStateTimeoutDefault = 100; | ||
const trustedAggregatorTimeoutDefault = 10; | ||
let firstDeployment = true; | ||
const currentVersion = 0; | ||
|
||
beforeEach('Deploy contract', async () => { | ||
upgrades.silenceWarnings(); | ||
|
||
// load signers | ||
[deployer, trustedAggregator, trustedSequencer, admin] = await ethers.getSigners(); | ||
|
||
// deploy mock verifier | ||
const VerifierRollupHelperFactory = await ethers.getContractFactory( | ||
'VerifierRollupHelperMock', | ||
); | ||
verifierContract = await VerifierRollupHelperFactory.deploy(); | ||
|
||
// deploy MATIC | ||
const maticTokenFactory = await ethers.getContractFactory('ERC20PermitMock'); | ||
maticTokenContract = await maticTokenFactory.deploy( | ||
maticTokenName, | ||
maticTokenSymbol, | ||
deployer.address, | ||
maticTokenInitialBalance, | ||
); | ||
await maticTokenContract.deployed(); | ||
|
||
/* | ||
* deploy global exit root manager | ||
* In order to not have trouble with nonce deploy first proxy admin | ||
*/ | ||
await upgrades.deployProxyAdmin(); | ||
if ((await upgrades.admin.getInstance()).address !== '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0') { | ||
firstDeployment = false; | ||
} | ||
const nonceProxyBridge = Number((await ethers.provider.getTransactionCount(deployer.address))) + (firstDeployment ? 3 : 2); | ||
const nonceProxyZkevm = nonceProxyBridge + 2; // Always have to redeploy impl since the polygonZkEVMGlobalExitRoot address changes | ||
|
||
const precalculateBridgeAddress = ethers.utils.getContractAddress({ from: deployer.address, nonce: nonceProxyBridge }); | ||
const precalculateZkevmAddress = ethers.utils.getContractAddress({ from: deployer.address, nonce: nonceProxyZkevm }); | ||
firstDeployment = false; | ||
|
||
const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory('PolygonZkEVMGlobalExitRoot'); | ||
polygonZkEVMGlobalExitRoot = await upgrades.deployProxy(PolygonZkEVMGlobalExitRootFactory, [], { | ||
initializer: false, | ||
constructorArgs: [precalculateZkevmAddress, precalculateBridgeAddress], | ||
unsafeAllow: ['constructor', 'state-variable-immutable'], | ||
}); | ||
|
||
// deploy PolygonZkEVMBridge | ||
const polygonZkEVMBridgeFactory = await ethers.getContractFactory('PolygonZkEVMBridge'); | ||
polygonZkEVMBridgeContract = await upgrades.deployProxy(polygonZkEVMBridgeFactory, [], { initializer: false }); | ||
|
||
// deploy PolygonZkEVMTestnet | ||
const PolygonZkEVMFactory = await ethers.getContractFactory('PolygonZkEVMUpgraded'); | ||
polygonZkEVMContract = await upgrades.deployProxy(PolygonZkEVMFactory, [], { | ||
initializer: false, | ||
constructorArgs: [ | ||
polygonZkEVMGlobalExitRoot.address, | ||
maticTokenContract.address, | ||
verifierContract.address, | ||
polygonZkEVMBridgeContract.address, | ||
chainID, | ||
forkID, | ||
currentVersion, | ||
], | ||
unsafeAllow: ['constructor', 'state-variable-immutable'], | ||
}); | ||
|
||
expect(precalculateBridgeAddress).to.be.equal(polygonZkEVMBridgeContract.address); | ||
expect(precalculateZkevmAddress).to.be.equal(polygonZkEVMContract.address); | ||
|
||
await polygonZkEVMBridgeContract.initialize(networkIDMainnet, polygonZkEVMGlobalExitRoot.address, polygonZkEVMContract.address); | ||
await polygonZkEVMContract.initialize( | ||
{ | ||
admin: admin.address, | ||
trustedSequencer: trustedSequencer.address, | ||
pendingStateTimeout: pendingStateTimeoutDefault, | ||
trustedAggregator: trustedAggregator.address, | ||
trustedAggregatorTimeout: trustedAggregatorTimeoutDefault, | ||
}, | ||
genesisRoot, | ||
urlSequencer, | ||
networkName, | ||
version, | ||
); | ||
|
||
// fund sequencer address with Matic tokens | ||
await maticTokenContract.transfer(trustedSequencer.address, ethers.utils.parseEther('1000')); | ||
}); | ||
|
||
it('should check the constructor parameters', async () => { | ||
expect(await polygonZkEVMContract.version()).to.be.equal(0); | ||
}); | ||
|
||
it('should check updateVersion', async () => { | ||
const newVersionString = '0.0.2'; | ||
|
||
const lastVerifiedBatch = 0; | ||
await expect(polygonZkEVMContract.updateVersion(newVersionString)) | ||
.to.emit(polygonZkEVMContract, 'UpdateZkEVMVersion').withArgs(lastVerifiedBatch, forkID, newVersionString); | ||
|
||
expect(await polygonZkEVMContract.version()).to.be.equal(1); | ||
|
||
await expect(polygonZkEVMContract.updateVersion(newVersionString)) | ||
.to.be.revertedWith('VersionAlreadyUpdated'); | ||
}); | ||
|
||
it('should upgrade polygonKEVM', async () => { | ||
// deploy PolygonZkEVMTestnet | ||
const PolygonZkEVMFactory = await ethers.getContractFactory('PolygonZkEVM'); | ||
const oldPolygonZkEVMContract = await upgrades.deployProxy(PolygonZkEVMFactory, [], { | ||
initializer: false, | ||
constructorArgs: [ | ||
polygonZkEVMGlobalExitRoot.address, | ||
maticTokenContract.address, | ||
verifierContract.address, | ||
polygonZkEVMBridgeContract.address, | ||
chainID, | ||
forkID, | ||
], | ||
unsafeAllow: ['constructor', 'state-variable-immutable'], | ||
}); | ||
|
||
// initialize | ||
await oldPolygonZkEVMContract.initialize( | ||
{ | ||
admin: admin.address, | ||
trustedSequencer: trustedSequencer.address, | ||
pendingStateTimeout: pendingStateTimeoutDefault, | ||
trustedAggregator: trustedAggregator.address, | ||
trustedAggregatorTimeout: trustedAggregatorTimeoutDefault, | ||
}, | ||
genesisRoot, | ||
urlSequencer, | ||
networkName, | ||
version, | ||
); | ||
|
||
/* | ||
* Upgrade the contract | ||
*/ | ||
const PolygonZkEVMUpgradedFactory = await ethers.getContractFactory('PolygonZkEVMUpgraded'); | ||
const polygonZkEVMUpgradedContract = PolygonZkEVMUpgradedFactory.attach(oldPolygonZkEVMContract.address); | ||
|
||
// Check that is the v0 contract | ||
await expect(polygonZkEVMUpgradedContract.version()).to.be.reverted; | ||
|
||
// Upgrade the contract | ||
const newVersionString = '0.0.2'; | ||
|
||
await upgrades.upgradeProxy( | ||
polygonZkEVMContract.address, | ||
PolygonZkEVMUpgradedFactory, | ||
{ | ||
constructorArgs: [ | ||
polygonZkEVMGlobalExitRoot.address, | ||
maticTokenContract.address, | ||
verifierContract.address, | ||
polygonZkEVMBridgeContract.address, | ||
chainID, | ||
forkID, | ||
currentVersion], | ||
unsafeAllow: ['constructor', 'state-variable-immutable'], | ||
call: { fn: 'updateVersion', args: [newVersionString] }, | ||
}, | ||
); | ||
|
||
expect(await polygonZkEVMContract.version()).to.be.equal(1); | ||
await expect(polygonZkEVMContract.updateVersion(newVersionString)) | ||
.to.be.revertedWith('VersionAlreadyUpdated'); | ||
}); | ||
}); |