-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(contracts): Add the WithdrawalFinalizer Contract (#314)
# What ❔ This PR adds the WithdrawalFinalizer contract. ## Why ❔ To open source the already deployed contract. ## Checklist <!-- Check your PR fulfills the following items. --> <!-- For draft PRs check the boxes as you complete them. --> - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `cargo fmt`. --------- Co-authored-by: Fedor Sakharov <[email protected]>
- Loading branch information
Showing
6 changed files
with
223 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 |
---|---|---|
@@ -1 +1,7 @@ | ||
/target | ||
node_modules | ||
cache | ||
artifacts | ||
typechain-types | ||
*.log | ||
dev.env |
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,92 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "@matterlabs/zksync-contracts/l1/contracts/bridge/interfaces/IL1Bridge.sol"; | ||
import "@matterlabs/zksync-contracts/l1/contracts/zksync/interfaces/IMailbox.sol"; | ||
import "@matterlabs/zksync-contracts/l1/contracts/common/libraries/UncheckedMath.sol"; | ||
|
||
|
||
contract WithdrawalFinalizer { | ||
using UncheckedMath for uint256; | ||
IMailbox constant ZKSYNC_MAILBOX = IMailbox($(ZKSYNC_ADDRESS)); | ||
IL1Bridge constant ERC20_BRIDGE = IL1Bridge($(ERC20_BRIDGE_ADDRESS)); | ||
|
||
struct RequestFinalizeWithdrawal { | ||
uint256 _l2BlockNumber; | ||
uint256 _l2MessageIndex; | ||
uint16 _l2TxNumberInBlock; | ||
bytes _message; | ||
bytes32[] _merkleProof; | ||
bool _isEth; | ||
uint256 _gas; | ||
} | ||
|
||
struct Result { | ||
uint256 _l2BlockNumber; | ||
uint256 _l2MessageIndex; | ||
uint256 _gas; | ||
bool success; | ||
} | ||
|
||
function finalizeWithdrawals( | ||
RequestFinalizeWithdrawal[] calldata requests | ||
) external returns (Result[] memory) { | ||
uint256 requestsLength = requests.length; | ||
Result[] memory results = new Result[](requestsLength); | ||
for (uint256 i = 0; i < requestsLength; i = i.uncheckedInc()) { | ||
require(gasleft() >= ((requests[i]._gas * 64) / 63) + 500, "i"); | ||
uint256 gasBefore = gasleft(); | ||
if (requests[i]._isEth) { | ||
try | ||
ZKSYNC_MAILBOX.finalizeEthWithdrawal{gas: requests[i]._gas}( | ||
requests[i]._l2BlockNumber, | ||
requests[i]._l2MessageIndex, | ||
requests[i]._l2TxNumberInBlock, | ||
requests[i]._message, | ||
requests[i]._merkleProof | ||
) | ||
{ | ||
results[i] = Result({ | ||
_l2BlockNumber: requests[i]._l2BlockNumber, | ||
_l2MessageIndex: requests[i]._l2MessageIndex, | ||
_gas: gasBefore - gasleft(), | ||
success: true | ||
}); | ||
} catch { | ||
results[i] = Result({ | ||
_l2BlockNumber: requests[i]._l2BlockNumber, | ||
_l2MessageIndex: requests[i]._l2MessageIndex, | ||
_gas: 0, | ||
success: false | ||
}); | ||
} | ||
} else { | ||
try | ||
ERC20_BRIDGE.finalizeWithdrawal{gas: requests[i]._gas}( | ||
requests[i]._l2BlockNumber, | ||
requests[i]._l2MessageIndex, | ||
requests[i]._l2TxNumberInBlock, | ||
requests[i]._message, | ||
requests[i]._merkleProof | ||
) | ||
{ | ||
results[i] = Result({ | ||
_l2BlockNumber: requests[i]._l2BlockNumber, | ||
_l2MessageIndex: requests[i]._l2MessageIndex, | ||
_gas: gasBefore - gasleft(), | ||
success: true | ||
}); | ||
} catch { | ||
results[i] = Result({ | ||
_l2BlockNumber: requests[i]._l2BlockNumber, | ||
_l2MessageIndex: requests[i]._l2MessageIndex, | ||
_gas: 0, | ||
success: false | ||
}); | ||
} | ||
} | ||
} | ||
return results; | ||
} | ||
} |
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,38 @@ | ||
import '@nomiclabs/hardhat-solpp'; | ||
import '@nomiclabs/hardhat-ethers'; | ||
import '@nomiclabs/hardhat-etherscan'; | ||
import '@typechain/hardhat'; | ||
|
||
const config = { | ||
ZKSYNC_ADDRESS: process.env.CONTRACTS_DIAMOND_PROXY_ADDR, | ||
ERC20_BRIDGE_ADDRESS: process.env.CONTRACTS_L1_ERC20_BRIDGE_PROXY_ADDR | ||
}; | ||
|
||
export default { | ||
solidity: { | ||
version: '0.8.18', | ||
settings: { | ||
optimizer: { | ||
enabled: true, | ||
runs: 200 | ||
}, | ||
outputSelection: { | ||
'*': { | ||
'*': ['storageLayout'] | ||
} | ||
} | ||
} | ||
}, | ||
contractSizer: { | ||
runOnCompile: false | ||
}, | ||
paths: { | ||
sources: './contracts' | ||
}, | ||
solpp: { | ||
defs: config | ||
}, | ||
etherscan: { | ||
apiKey: process.env.MISC_ETHERSCAN_API_KEY | ||
} | ||
}; |
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,38 @@ | ||
{ | ||
"name": "withdrawal-finalizer", | ||
"version": "0.1.0", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@matterlabs/zksync-contracts": "^0.5.2", | ||
"@openzeppelin/contracts": "^4.8.1", | ||
"@sentry/node": "^7.2.0", | ||
"@sentry/tracing": "^7.2.0", | ||
"ethers": "^5.6.0", | ||
"node-fetch": "^2.6.1", | ||
"prom-client": "^14.2.0", | ||
"zksync-web3": "^0.13.3" | ||
}, | ||
"devDependencies": { | ||
"@nomiclabs/hardhat-ethers": "^2.0.5", | ||
"@nomiclabs/hardhat-etherscan": "^3.0.3", | ||
"@nomiclabs/hardhat-solpp": "^2.0.1", | ||
"@typechain/ethers-v5": "^9.0.0", | ||
"@typechain/hardhat": "^5.0.0", | ||
"@types/chai": "^4.2.0", | ||
"@types/mocha": "^9.1.0", | ||
"@types/node": "^14.14.5", | ||
"chai": "^4.3.6", | ||
"hardhat": "^2.12.7", | ||
"mocha": "^9.2.1", | ||
"prettier": "^2.5.1", | ||
"prettier-plugin-solidity": "^1.1.2", | ||
"ts-generator": "^0.1.1", | ||
"ts-node": "^10.8.1", | ||
"typechain": "^7.0.0", | ||
"typescript": "^4.0.5" | ||
}, | ||
"scripts": { | ||
"deploy": "ts-node scripts/deploy.ts", | ||
"contracts:build": "hardhat compile" | ||
} | ||
} |
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,26 @@ | ||
import { Wallet } from 'ethers'; | ||
|
||
const hardhat = require('hardhat'); | ||
|
||
async function main() { | ||
const provider = new hardhat.ethers.providers.JsonRpcProvider(process.env.ETH_CLIENT_WEB3_URL as string); | ||
const wallet = Wallet.fromMnemonic( | ||
process.env.MNEMONIC as string, | ||
"m/44'/60'/0'/0/1" | ||
).connect(provider); | ||
|
||
|
||
const contractFactory = await hardhat.ethers.getContractFactory("WithdrawalFinalizer", { | ||
signer: wallet | ||
}); | ||
const contract = await contractFactory.deploy(); | ||
await contract.deployTransaction.wait(); | ||
console.log(`CONTRACTS_WITHDRAWAL_FINALIZER_ADDRESS=${contract.address}`); | ||
} | ||
|
||
main() | ||
.then(() => process.exit(0)) | ||
.catch((error) => { | ||
console.error(error); | ||
process.exit(1); | ||
}); |