Commit 0bf3b9b4 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

contracts-bedrock: differential fuzzing (#2980)

* core-utils: add encoding and hashing functions to core-utils

* ci: update

* contracts-bedrock: differential fuzzing

* deps: update forge-std

* contracts-bedrock: set fuzz runs to 512

* contracts-bedrock: rename differential-testing method

* contracts-bedrock: no sender as address(OptimismPortal)
parent b7087214
---
'@eth-optimism/core-utils': patch
---
Add encoding and hashing functions for bedrock
---
'@eth-optimism/contracts-bedrock': patch
'@eth-optimism/contracts-periphery': patch
---
Update forge-std
...@@ -107,7 +107,7 @@ jobs: ...@@ -107,7 +107,7 @@ jobs:
contracts-bedrock-tests: contracts-bedrock-tests:
docker: docker:
- image: ethereumoptimism/ci-builder:latest - image: ethereumoptimism/ci-builder:latest
resource_class: medium resource_class: large
steps: steps:
- restore_cache: - restore_cache:
keys: keys:
...@@ -135,11 +135,15 @@ jobs: ...@@ -135,11 +135,15 @@ jobs:
name: test name: test
command: yarn test command: yarn test
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
environment:
FOUNDRY_PROFILE: ci
- run: - run:
name: gas snapshot name: gas snapshot
command: | command: |
forge --version forge --version
forge snapshot --check || exit 0 forge snapshot --check || exit 0
environment:
FOUNDRY_PROFILE: ci
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: storage snapshot name: storage snapshot
......
...@@ -10,7 +10,6 @@ GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 74944) ...@@ -10,7 +10,6 @@ GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 74944)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35773) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35773)
DeployerWhitelist_Test:test_owner() (gas: 7591) DeployerWhitelist_Test:test_owner() (gas: 7591)
DeployerWhitelist_Test:test_storageSlots() (gas: 33427) DeployerWhitelist_Test:test_storageSlots() (gas: 33427)
Encoding_Test:test_encodeDepositTransaction() (gas: 64610)
GasPriceOracle_Test:test_baseFee() (gas: 8392) GasPriceOracle_Test:test_baseFee() (gas: 8392)
GasPriceOracle_Test:test_gasPrice() (gas: 8381) GasPriceOracle_Test:test_gasPrice() (gas: 8381)
GasPriceOracle_Test:test_l1BaseFee() (gas: 10648) GasPriceOracle_Test:test_l1BaseFee() (gas: 10648)
...@@ -24,8 +23,7 @@ GasPriceOracle_Test:test_setL1BaseFeeReverts() (gas: 11739) ...@@ -24,8 +23,7 @@ GasPriceOracle_Test:test_setL1BaseFeeReverts() (gas: 11739)
GasPriceOracle_Test:test_setOverhead() (gas: 36789) GasPriceOracle_Test:test_setOverhead() (gas: 36789)
GasPriceOracle_Test:test_setScalar() (gas: 36796) GasPriceOracle_Test:test_setScalar() (gas: 36796)
GasPriceOracle_Test:test_storageLayout() (gas: 86705) GasPriceOracle_Test:test_storageLayout() (gas: 86705)
Hashing_Test:test_hashDepositSource() (gas: 673) Hashing_Test:test_hashDepositSource() (gas: 628)
Hashing_Test:test_hashDepositTransaction() (gas: 39129)
L1BlockTest:test_basefee() (gas: 7575) L1BlockTest:test_basefee() (gas: 7575)
L1BlockTest:test_hash() (gas: 7552) L1BlockTest:test_hash() (gas: 7552)
L1BlockTest:test_number() (gas: 7629) L1BlockTest:test_number() (gas: 7629)
...@@ -50,18 +48,18 @@ L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1489673) ...@@ -50,18 +48,18 @@ L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1489673)
L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40852) L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40852)
L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24313) L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24313)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86364) L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86364)
L1StandardBridge_Test:test_depositERC20() (gas: 578548) L1StandardBridge_Test:test_depositERC20() (gas: 578572)
L1StandardBridge_Test:test_depositERC20To() (gas: 580752) L1StandardBridge_Test:test_depositERC20To() (gas: 580779)
L1StandardBridge_Test:test_depositETH() (gas: 372464) L1StandardBridge_Test:test_depositETH() (gas: 372464)
L1StandardBridge_Test:test_depositETHTo() (gas: 329608) L1StandardBridge_Test:test_depositETHTo() (gas: 329608)
L1StandardBridge_Test:test_finalizeBridgeERC20FailSendBack() (gas: 681009) L1StandardBridge_Test:test_finalizeBridgeERC20FailSendBack() (gas: 681028)
L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 490749) L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 490771)
L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 64276) L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 64276)
L1StandardBridge_Test:test_initialize() (gas: 26334) L1StandardBridge_Test:test_initialize() (gas: 26334)
L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 22376) L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 22376)
L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40940) L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40940)
L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 36264) L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 36268)
L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 35569) L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 35573)
L1StandardBridge_Test:test_receive() (gas: 519287) L1StandardBridge_Test:test_receive() (gas: 519287)
L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10845) L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10845)
L2CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 171927) L2CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 171927)
...@@ -101,16 +99,16 @@ L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 230843) ...@@ -101,16 +99,16 @@ L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 230843)
L2StandardBridge_Test:test_ERC20BridgeFailed_whenLocalTokenIsBridge() (gas: 132769) L2StandardBridge_Test:test_ERC20BridgeFailed_whenLocalTokenIsBridge() (gas: 132769)
L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21622) L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21622)
L2StandardBridge_Test:test_finalizeBridgeERC20FailSendBack() (gas: 498579) L2StandardBridge_Test:test_finalizeBridgeERC20FailSendBack() (gas: 498579)
L2StandardBridge_Test:test_finalizeDeposit() (gas: 93113) L2StandardBridge_Test:test_finalizeDeposit() (gas: 93128)
L2StandardBridge_Test:test_finalizeDeposit_failsToCompleteOutboundTransfer() (gas: 139784) L2StandardBridge_Test:test_finalizeDeposit_failsToCompleteOutboundTransfer() (gas: 139784)
L2StandardBridge_Test:test_initialize() (gas: 14823) L2StandardBridge_Test:test_initialize() (gas: 14823)
L2StandardBridge_Test:test_receive() (gas: 136330) L2StandardBridge_Test:test_receive() (gas: 136330)
L2StandardBridge_Test:test_withdraw() (gas: 352474) L2StandardBridge_Test:test_withdraw() (gas: 352486)
L2StandardBridge_Test:test_withdrawTo() (gas: 353229) L2StandardBridge_Test:test_withdrawTo() (gas: 353241)
L2StandardBridge_Test:test_withdraw_onlyEOA() (gas: 251979) L2StandardBridge_Test:test_withdraw_onlyEOA() (gas: 251991)
L2ToL1MessagePasserTest:test_burn() (gas: 112089) L2ToL1MessagePasserTest:test_burn() (gas: 112089)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 68037) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 68037)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 74928) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 74952)
LegacyERC20ETH_Test:test_approve() (gas: 10796) LegacyERC20ETH_Test:test_approve() (gas: 10796)
LegacyERC20ETH_Test:test_burn() (gas: 10681) LegacyERC20ETH_Test:test_burn() (gas: 10681)
LegacyERC20ETH_Test:test_crossDomain() (gas: 10577) LegacyERC20ETH_Test:test_crossDomain() (gas: 10577)
...@@ -121,13 +119,13 @@ LegacyERC20ETH_Test:test_mint() (gas: 10627) ...@@ -121,13 +119,13 @@ LegacyERC20ETH_Test:test_mint() (gas: 10627)
LegacyERC20ETH_Test:test_transfer() (gas: 10829) LegacyERC20ETH_Test:test_transfer() (gas: 10829)
LegacyERC20ETH_Test:test_transferFrom() (gas: 13008) LegacyERC20ETH_Test:test_transferFrom() (gas: 13008)
OptimismMintableERC20_Test:test_bridge() (gas: 9828) OptimismMintableERC20_Test:test_bridge() (gas: 9828)
OptimismMintableERC20_Test:test_burn() (gas: 52773) OptimismMintableERC20_Test:test_burn() (gas: 52788)
OptimismMintableERC20_Test:test_burnRevertsFromNotBridge() (gas: 13219) OptimismMintableERC20_Test:test_burnRevertsFromNotBridge() (gas: 13228)
OptimismMintableERC20_Test:test_erc165_supportsInterface() (gas: 7828) OptimismMintableERC20_Test:test_erc165_supportsInterface() (gas: 7828)
OptimismMintableERC20_Test:test_l1Token() (gas: 9824) OptimismMintableERC20_Test:test_l1Token() (gas: 9824)
OptimismMintableERC20_Test:test_l2Bridge() (gas: 9746) OptimismMintableERC20_Test:test_l2Bridge() (gas: 9746)
OptimismMintableERC20_Test:test_mint() (gas: 65754) OptimismMintableERC20_Test:test_mint() (gas: 65763)
OptimismMintableERC20_Test:test_mintRevertsFromNotBridge() (gas: 13243) OptimismMintableERC20_Test:test_mintRevertsFromNotBridge() (gas: 13252)
OptimismMintableERC20_Test:test_remoteToken() (gas: 9740) OptimismMintableERC20_Test:test_remoteToken() (gas: 9740)
OptimismMintableTokenFactory_Test:test_bridge() (gas: 7663) OptimismMintableTokenFactory_Test:test_bridge() (gas: 7663)
OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1113127) OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1113127)
...@@ -140,16 +138,16 @@ OptimismPortalUpgradeable_Test:test_upgrading() (gas: 230843) ...@@ -140,16 +138,16 @@ OptimismPortalUpgradeable_Test:test_upgrading() (gas: 230843)
OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17341) OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17341)
OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 14215) OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 14215)
OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 127503) OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 127503)
OptimismPortal_Test:test_cannotFinalizeRecentWithdrawal() (gas: 24754) OptimismPortal_Test:test_cannotFinalizeRecentWithdrawal() (gas: 24757)
OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 76654) OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 76654)
OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 77108) OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 77131)
OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 76659) OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 76659)
OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA() (gas: 76980) OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA() (gas: 76980)
OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 83680) OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 83680)
OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 75845) OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 75845)
OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 83384) OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 83384)
OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 84132) OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 84132)
OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 37266) OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 37269)
OptimismPortal_Test:test_isBlockFinalized() (gas: 113725) OptimismPortal_Test:test_isBlockFinalized() (gas: 113725)
OptimismPortal_Test:test_simple_isBlockFinalized() (gas: 26652) OptimismPortal_Test:test_simple_isBlockFinalized() (gas: 26652)
Proxy_Test:test_clashingFunctionSignatures() (gas: 101427) Proxy_Test:test_clashingFunctionSignatures() (gas: 101427)
...@@ -221,12 +219,12 @@ RLPReader_Test:test_readList_nonOptimalLongLengthArray1() (gas: 4233) ...@@ -221,12 +219,12 @@ RLPReader_Test:test_readList_nonOptimalLongLengthArray1() (gas: 4233)
RLPReader_Test:test_readList_nonOptimalLongLengthArray2() (gas: 4256) RLPReader_Test:test_readList_nonOptimalLongLengthArray2() (gas: 4256)
RLPReader_Test:test_readList_notLongEnough() (gas: 3874) RLPReader_Test:test_readList_notLongEnough() (gas: 3874)
RLPReader_Test:test_readList_shortListMax1() (gas: 40662) RLPReader_Test:test_readList_shortListMax1() (gas: 40662)
RLPReader_Test:test_readList_stringList() (gas: 16796) RLPReader_Test:test_readList_stringList() (gas: 16844)
RLPReader_Test:test_readString_emptyString() (gas: 1719) RLPReader_Test:test_readString_emptyString() (gas: 1719)
RLPReader_Test:test_readString_longString() (gas: 3076) RLPReader_Test:test_readString_longString() (gas: 3092)
RLPReader_Test:test_readString_longString2() (gas: 18524) RLPReader_Test:test_readString_longString2() (gas: 18524)
RLPReader_Test:test_readString_shortString() (gas: 2280) RLPReader_Test:test_readString_shortString() (gas: 2296)
RLPReader_Test:test_readString_shortString2() (gas: 2775) RLPReader_Test:test_readString_shortString2() (gas: 2791)
RLPReader_Test:test_readUint256_mediumInt1() (gas: 1235) RLPReader_Test:test_readUint256_mediumInt1() (gas: 1235)
RLPReader_Test:test_readUint256_mediumInt2() (gas: 1237) RLPReader_Test:test_readUint256_mediumInt2() (gas: 1237)
RLPReader_Test:test_readUint256_mediumInt3() (gas: 1238) RLPReader_Test:test_readUint256_mediumInt3() (gas: 1238)
...@@ -235,31 +233,31 @@ RLPReader_Test:test_readUint256_smallInt2() (gas: 1151) ...@@ -235,31 +233,31 @@ RLPReader_Test:test_readUint256_smallInt2() (gas: 1151)
RLPReader_Test:test_readUint256_smallInt3() (gas: 1127) RLPReader_Test:test_readUint256_smallInt3() (gas: 1127)
RLPReader_Test:test_readUint256_smallInt4() (gas: 1128) RLPReader_Test:test_readUint256_smallInt4() (gas: 1128)
RLPReader_Test:test_readUint256_zero() (gas: 1258) RLPReader_Test:test_readUint256_zero() (gas: 1258)
RLPWriter_Test:test_writeList_dictTest1() (gas: 37148) RLPWriter_Test:test_writeList_dictTest1() (gas: 37356)
RLPWriter_Test:test_writeList_empty() (gas: 1751) RLPWriter_Test:test_writeList_empty() (gas: 1759)
RLPWriter_Test:test_writeList_listoflists() (gas: 10969) RLPWriter_Test:test_writeList_listoflists() (gas: 11025)
RLPWriter_Test:test_writeList_listoflists2() (gas: 16779) RLPWriter_Test:test_writeList_listoflists2() (gas: 16867)
RLPWriter_Test:test_writeList_longlist1() (gas: 40730) RLPWriter_Test:test_writeList_longlist1() (gas: 40850)
RLPWriter_Test:test_writeList_longlist2() (gas: 283278) RLPWriter_Test:test_writeList_longlist2() (gas: 283846)
RLPWriter_Test:test_writeList_multiList() (gas: 22660) RLPWriter_Test:test_writeList_multiList() (gas: 22708)
RLPWriter_Test:test_writeList_shortListMax1() (gas: 36985) RLPWriter_Test:test_writeList_shortListMax1() (gas: 37177)
RLPWriter_Test:test_writeList_stringList() (gas: 10786) RLPWriter_Test:test_writeList_stringList() (gas: 10850)
RLPWriter_Test:test_writeString_bytestring00() (gas: 1022) RLPWriter_Test:test_writeString_bytestring00() (gas: 1022)
RLPWriter_Test:test_writeString_bytestring01() (gas: 978) RLPWriter_Test:test_writeString_bytestring01() (gas: 978)
RLPWriter_Test:test_writeString_bytestring7f() (gas: 1002) RLPWriter_Test:test_writeString_bytestring7f() (gas: 1002)
RLPWriter_Test:test_writeString_empty() (gas: 1704) RLPWriter_Test:test_writeString_empty() (gas: 1712)
RLPWriter_Test:test_writeString_longstring() (gas: 17180) RLPWriter_Test:test_writeString_longstring() (gas: 17196)
RLPWriter_Test:test_writeString_longstring2() (gas: 261864) RLPWriter_Test:test_writeString_longstring2() (gas: 261872)
RLPWriter_Test:test_writeString_shortstring() (gas: 2544) RLPWriter_Test:test_writeString_shortstring() (gas: 2560)
RLPWriter_Test:test_writeString_shortstring2() (gas: 15563) RLPWriter_Test:test_writeString_shortstring2() (gas: 15579)
RLPWriter_Test:test_writeUint_mediumint() (gas: 8430) RLPWriter_Test:test_writeUint_mediumint() (gas: 8446)
RLPWriter_Test:test_writeUint_mediumint2() (gas: 8780) RLPWriter_Test:test_writeUint_mediumint2() (gas: 8796)
RLPWriter_Test:test_writeUint_mediumint3() (gas: 9189) RLPWriter_Test:test_writeUint_mediumint3() (gas: 9205)
RLPWriter_Test:test_writeUint_smallint() (gas: 7350) RLPWriter_Test:test_writeUint_smallint() (gas: 7350)
RLPWriter_Test:test_writeUint_smallint2() (gas: 7352) RLPWriter_Test:test_writeUint_smallint2() (gas: 7352)
RLPWriter_Test:test_writeUint_smallint3() (gas: 7372) RLPWriter_Test:test_writeUint_smallint3() (gas: 7372)
RLPWriter_Test:test_writeUint_smallint4() (gas: 7351) RLPWriter_Test:test_writeUint_smallint4() (gas: 7351)
RLPWriter_Test:test_writeUint_zero() (gas: 7798) RLPWriter_Test:test_writeUint_zero() (gas: 7806)
ResourceMetering_Test:test_initialResourceParams() (gas: 8964) ResourceMetering_Test:test_initialResourceParams() (gas: 8964)
ResourceMetering_Test:test_updateNoGasDelta() (gas: 2008317) ResourceMetering_Test:test_updateNoGasDelta() (gas: 2008317)
ResourceMetering_Test:test_updateOneEmptyBlock() (gas: 18171) ResourceMetering_Test:test_updateOneEmptyBlock() (gas: 18171)
...@@ -268,8 +266,8 @@ ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20571) ...@@ -268,8 +266,8 @@ ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20571)
ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20594) ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20594)
ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017087) ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017087)
ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16047) ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16047)
Semver_Test:test_behindProxy() (gas: 506870) Semver_Test:test_behindProxy() (gas: 506894)
Semver_Test:test_version() (gas: 9451) Semver_Test:test_version() (gas: 9475)
SequencerFeeVault_Test:test_constructor() (gas: 7678) SequencerFeeVault_Test:test_constructor() (gas: 7678)
SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5440) SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5440)
SequencerFeeVault_Test:test_receive() (gas: 17338) SequencerFeeVault_Test:test_receive() (gas: 17338)
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.10; pragma solidity 0.8.10;
/* Testing utilities */ /* Testing utilities */
...@@ -10,7 +10,6 @@ import { L2StandardBridge } from "../L2/L2StandardBridge.sol"; ...@@ -10,7 +10,6 @@ import { L2StandardBridge } from "../L2/L2StandardBridge.sol";
import { OptimismMintableERC20Factory } from "../universal/OptimismMintableERC20Factory.sol"; import { OptimismMintableERC20Factory } from "../universal/OptimismMintableERC20Factory.sol";
import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol"; import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol"; import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol";
import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol"; import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol";
import { L2CrossDomainMessenger } from "../L2/L2CrossDomainMessenger.sol"; import { L2CrossDomainMessenger } from "../L2/L2CrossDomainMessenger.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
...@@ -23,6 +22,7 @@ import { ResolvedDelegateProxy } from "../legacy/ResolvedDelegateProxy.sol"; ...@@ -23,6 +22,7 @@ import { ResolvedDelegateProxy } from "../legacy/ResolvedDelegateProxy.sol";
import { AddressManager } from "../legacy/AddressManager.sol"; import { AddressManager } from "../legacy/AddressManager.sol";
import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol"; import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol";
import { IL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol"; import { IL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
contract CommonTest is Test { contract CommonTest is Test {
address alice = address(128); address alice = address(128);
...@@ -44,6 +44,24 @@ contract CommonTest is Test { ...@@ -44,6 +44,24 @@ contract CommonTest is Test {
bytes opaqueData bytes opaqueData
); );
FFIInterface ffi;
function _setUp() public {
// Give alice and bob some ETH
vm.deal(alice, 1 << 16);
vm.deal(bob, 1 << 16);
vm.deal(multisig, 1 << 16);
vm.label(alice, "alice");
vm.label(bob, "bob");
vm.label(multisig, "multisig");
// Make sure we have a non-zero base fee
vm.fee(1000000000);
ffi = new FFIInterface();
}
function emitTransactionDeposited( function emitTransactionDeposited(
address _from, address _from,
address _to, address _to,
...@@ -61,19 +79,6 @@ contract CommonTest is Test { ...@@ -61,19 +79,6 @@ contract CommonTest is Test {
); );
} }
function _setUp() public {
// Give alice and bob some ETH
vm.deal(alice, 1 << 16);
vm.deal(bob, 1 << 16);
vm.deal(multisig, 1 << 16);
vm.label(alice, "alice");
vm.label(bob, "bob");
vm.label(multisig, "multisig");
// Make sure we have a non-zero base fee
vm.fee(1000000000);
}
} }
contract L2OutputOracle_Initializer is CommonTest { contract L2OutputOracle_Initializer is CommonTest {
...@@ -81,6 +86,9 @@ contract L2OutputOracle_Initializer is CommonTest { ...@@ -81,6 +86,9 @@ contract L2OutputOracle_Initializer is CommonTest {
L2OutputOracle oracle; L2OutputOracle oracle;
L2OutputOracle oracleImpl; L2OutputOracle oracleImpl;
L2ToL1MessagePasser messagePasser =
L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));
// Constructor arguments // Constructor arguments
address proposer = 0x000000000000000000000000000000000000AbBa; address proposer = 0x000000000000000000000000000000000000AbBa;
address owner = 0x000000000000000000000000000000000000ACDC; address owner = 0x000000000000000000000000000000000000ACDC;
...@@ -131,6 +139,15 @@ contract L2OutputOracle_Initializer is CommonTest { ...@@ -131,6 +139,15 @@ contract L2OutputOracle_Initializer is CommonTest {
) )
); );
oracle = L2OutputOracle(address(proxy)); oracle = L2OutputOracle(address(proxy));
vm.label(address(oracle), "L2OutputOracle");
// Set the L2ToL1MessagePasser at the correct address
vm.etch(
Predeploys.L2_TO_L1_MESSAGE_PASSER,
address(new L2ToL1MessagePasser()).code
);
vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser");
} }
} }
...@@ -141,6 +158,7 @@ contract Portal_Initializer is L2OutputOracle_Initializer { ...@@ -141,6 +158,7 @@ contract Portal_Initializer is L2OutputOracle_Initializer {
function setUp() public virtual override { function setUp() public virtual override {
L2OutputOracle_Initializer.setUp(); L2OutputOracle_Initializer.setUp();
opImpl = new OptimismPortal(oracle, 7 days); opImpl = new OptimismPortal(oracle, 7 days);
Proxy proxy = new Proxy(multisig); Proxy proxy = new Proxy(multisig);
vm.prank(multisig); vm.prank(multisig);
...@@ -158,8 +176,6 @@ contract Messenger_Initializer is L2OutputOracle_Initializer { ...@@ -158,8 +176,6 @@ contract Messenger_Initializer is L2OutputOracle_Initializer {
L1CrossDomainMessenger L1Messenger; L1CrossDomainMessenger L1Messenger;
L2CrossDomainMessenger L2Messenger = L2CrossDomainMessenger L2Messenger =
L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER); L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);
L2ToL1MessagePasser messagePasser =
L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));
event SentMessage( event SentMessage(
address indexed target, address indexed target,
...@@ -225,18 +241,11 @@ contract Messenger_Initializer is L2OutputOracle_Initializer { ...@@ -225,18 +241,11 @@ contract Messenger_Initializer is L2OutputOracle_Initializer {
L2Messenger.initialize(address(L1Messenger)); L2Messenger.initialize(address(L1Messenger));
// Set the L2ToL1MessagePasser at the correct address
vm.etch(
Predeploys.L2_TO_L1_MESSAGE_PASSER,
address(new L2ToL1MessagePasser()).code
);
// Label addresses // Label addresses
vm.label(address(addressManager), "AddressManager"); vm.label(address(addressManager), "AddressManager");
vm.label(address(L1MessengerImpl), "L1CrossDomainMessenger_Impl"); vm.label(address(L1MessengerImpl), "L1CrossDomainMessenger_Impl");
vm.label(address(L1Messenger), "L1CrossDomainMessenger_Proxy"); vm.label(address(L1Messenger), "L1CrossDomainMessenger_Proxy");
vm.label(Predeploys.LEGACY_ERC20_ETH, "LegacyERC20ETH"); vm.label(Predeploys.LEGACY_ERC20_ETH, "LegacyERC20ETH");
vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser");
vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger"); vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger");
vm.label( vm.label(
...@@ -442,6 +451,164 @@ contract Bridge_Initializer is Messenger_Initializer { ...@@ -442,6 +451,164 @@ contract Bridge_Initializer is Messenger_Initializer {
} }
} }
contract FFIInterface is Test {
function getFinalizeWithdrawalTransactionInputs(
uint256 _nonce,
address _sender,
address _target,
uint64 _value,
uint256 _gasLimit,
bytes memory _data
) external returns (bytes32, bytes32, bytes32, bytes32, bytes memory) {
string[] memory cmds = new string[](9);
cmds[0] = "node";
cmds[1] = "dist/scripts/differential-testing.js";
cmds[2] = "getFinalizeWithdrawalTransactionInputs";
cmds[3] = vm.toString(_nonce);
cmds[4] = vm.toString(_sender);
cmds[5] = vm.toString(_target);
cmds[6] = vm.toString(_value);
cmds[7] = vm.toString(_gasLimit);
cmds[8] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
(
bytes32 stateRoot,
bytes32 storageRoot,
bytes32 outputRoot,
bytes32 withdrawalHash,
bytes memory withdrawalProof
) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes));
return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof);
}
function hashCrossDomainMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) external returns (bytes32) {
string[] memory cmds = new string[](9);
cmds[0] = "node";
cmds[1] = "dist/scripts/differential-testing.js";
cmds[2] = "hashCrossDomainMessage";
cmds[3] = vm.toString(_nonce);
cmds[4] = vm.toString(_sender);
cmds[5] = vm.toString(_target);
cmds[6] = vm.toString(_value);
cmds[7] = vm.toString(_gasLimit);
cmds[8] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
return abi.decode(result, (bytes32));
}
function hashWithdrawal(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) external returns (bytes32) {
string[] memory cmds = new string[](9);
cmds[0] = "node";
cmds[1] = "dist/scripts/differential-testing.js";
cmds[2] = "hashWithdrawal";
cmds[3] = vm.toString(_nonce);
cmds[4] = vm.toString(_sender);
cmds[5] = vm.toString(_target);
cmds[6] = vm.toString(_value);
cmds[7] = vm.toString(_gasLimit);
cmds[8] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
return abi.decode(result, (bytes32));
}
function hashOutputRootProof(
bytes32 _version,
bytes32 _stateRoot,
bytes32 _withdrawerStorageRoot,
bytes32 _latestBlockhash
) external returns (bytes32) {
string[] memory cmds = new string[](7);
cmds[0] = "node";
cmds[1] = "dist/scripts/differential-testing.js";
cmds[2] = "hashOutputRootProof";
cmds[3] = Strings.toHexString(uint256(_version));
cmds[4] = Strings.toHexString(uint256(_stateRoot));
cmds[5] = Strings.toHexString(uint256(_withdrawerStorageRoot));
cmds[6] = Strings.toHexString(uint256(_latestBlockhash));
bytes memory result = vm.ffi(cmds);
return abi.decode(result, (bytes32));
}
function hashDepositTransaction(
address _from,
address _to,
uint256 _mint,
uint256 _value,
uint64 _gas,
bytes memory _data,
uint256 _logIndex
) external returns (bytes32) {
string[] memory cmds = new string[](11);
cmds[0] = "node";
cmds[1] = "dist/scripts/differential-testing.js";
cmds[2] = "hashDepositTransaction";
cmds[3] = "0x0000000000000000000000000000000000000000000000000000000000000000";
cmds[4] = vm.toString(_logIndex);
cmds[5] = vm.toString(_from);
cmds[6] = vm.toString(_to);
cmds[7] = vm.toString(_mint);
cmds[8] = vm.toString(_value);
cmds[9] = vm.toString(_gas);
cmds[10] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
return abi.decode(result, (bytes32));
}
function encodeCrossDomainMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) external returns (bytes memory) {
string[] memory cmds = new string[](9);
cmds[0] = "node";
cmds[1] = "dist/scripts/differential-testing.js";
cmds[2] = "encodeCrossDomainMessage";
cmds[3] = vm.toString(_nonce);
cmds[4] = vm.toString(_sender);
cmds[5] = vm.toString(_target);
cmds[6] = vm.toString(_value);
cmds[7] = vm.toString(_gasLimit);
cmds[8] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
return abi.decode(result, (bytes));
}
function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) {
string[] memory cmds = new string[](4);
cmds[0] = "node";
cmds[1] = "dist/scripts/differential-testing.js";
cmds[2] = "decodeVersionedNonce";
cmds[3] = vm.toString(nonce);
bytes memory result = vm.ffi(cmds);
return abi.decode(result, (uint256, uint256));
}
}
// Used for testing a future upgrade beyond the current implementations. // Used for testing a future upgrade beyond the current implementations.
// We include some variables so that we can sanity check accessing storage values after an upgrade. // We include some variables so that we can sanity check accessing storage values after an upgrade.
contract NextImpl is Initializable { contract NextImpl is Initializable {
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.10; pragma solidity 0.8.10;
import { CommonTest } from "./CommonTest.t.sol"; import { CommonTest } from "./CommonTest.t.sol";
import { Encoding } from "../libraries/Encoding.sol"; import { Encoding } from "../libraries/Encoding.sol";
contract Encoding_Test is CommonTest { contract Encoding_Test is CommonTest {
function setUp() external {
_setUp();
}
function test_nonceVersioning(uint240 _nonce, uint16 _version) external { function test_nonceVersioning(uint240 _nonce, uint16 _version) external {
(uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce( (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(
Encoding.encodeVersionedNonce(_nonce, _version) Encoding.encodeVersionedNonce(_nonce, _version)
...@@ -12,4 +16,52 @@ contract Encoding_Test is CommonTest { ...@@ -12,4 +16,52 @@ contract Encoding_Test is CommonTest {
assertEq(version, _version); assertEq(version, _version);
assertEq(nonce, _nonce); assertEq(nonce, _nonce);
} }
function test_decodeVersionedNonce_differential(uint240 _nonce, uint16 _version) external {
uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version));
(uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce);
assertEq(
_version,
uint16(decodedVersion)
);
assertEq(
_nonce,
uint240(decodedNonce)
);
}
function test_encodeCrossDomainMessage_differential(
uint240 _nonce,
uint8 _version,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) external {
uint8 version = _version % 2;
uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);
bytes memory encoding = Encoding.encodeCrossDomainMessage(
nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
bytes memory _encoding = ffi.encodeCrossDomainMessage(
nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
assertEq(encoding, _encoding);
}
} }
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.10; pragma solidity 0.8.10;
import { CommonTest } from "./CommonTest.t.sol"; import { CommonTest } from "./CommonTest.t.sol";
...@@ -6,6 +6,10 @@ import { Hashing } from "../libraries/Hashing.sol"; ...@@ -6,6 +6,10 @@ import { Hashing } from "../libraries/Hashing.sol";
import { Encoding } from "../libraries/Encoding.sol"; import { Encoding } from "../libraries/Encoding.sol";
contract Hashing_Test is CommonTest { contract Hashing_Test is CommonTest {
function setUp() external {
_setUp();
}
function test_hashDepositSource() external { function test_hashDepositSource() external {
bytes32 sourceHash = Hashing.hashDepositSource( bytes32 sourceHash = Hashing.hashDepositSource(
0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959, 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,
...@@ -17,4 +21,127 @@ contract Hashing_Test is CommonTest { ...@@ -17,4 +21,127 @@ contract Hashing_Test is CommonTest {
0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc
); );
} }
function test_hashCrossDomainMessage_differential(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) external {
// Discard any fuzz tests with an invalid version
(, uint16 version) = Encoding.decodeVersionedNonce(_nonce);
vm.assume(version < 2);
bytes32 _hash = ffi.hashCrossDomainMessage(
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
bytes32 hash = Hashing.hashCrossDomainMessage(
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
assertEq(hash, _hash);
}
function test_hashWithdrawal_differential(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) external {
bytes32 hash = Hashing.hashWithdrawal(
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
bytes32 _hash = ffi.hashWithdrawal(
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
assertEq(hash, _hash);
}
function test_hashOutputRootProof_differential(
bytes32 _version,
bytes32 _stateRoot,
bytes32 _withdrawerStorageRoot,
bytes32 _latestBlockhash
) external {
Hashing.OutputRootProof memory proof = Hashing.OutputRootProof({
version: _version,
stateRoot: _stateRoot,
withdrawerStorageRoot: _withdrawerStorageRoot,
latestBlockhash: _latestBlockhash
});
bytes32 hash = Hashing.hashOutputRootProof(proof);
bytes32 _hash = ffi.hashOutputRootProof(
_version,
_stateRoot,
_withdrawerStorageRoot,
_latestBlockhash
);
assertEq(hash, _hash);
}
// TODO(tynes): foundry bug cannot serialize
// bytes32 as strings with vm.toString
function test_hashDepositTransaction_differential(
address _from,
address _to,
uint256 _mint,
uint256 _value,
uint64 _gas,
bytes memory _data,
uint256 _logIndex
) external {
bytes32 hash = Hashing.hashDepositTransaction(
_from,
_to,
_value,
_mint,
_gas,
false, // isCreate
_data,
bytes32(uint256(0)),
_logIndex
);
bytes32 _hash = ffi.hashDepositTransaction(
_from,
_to,
_mint,
_value,
_gas,
_data,
_logIndex
);
assertEq(hash, _hash);
}
} }
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.10; pragma solidity 0.8.10;
import { Portal_Initializer, CommonTest, NextImpl } from "./CommonTest.t.sol"; import { Portal_Initializer, CommonTest, NextImpl } from "./CommonTest.t.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol"; import { OptimismPortal } from "../L1/OptimismPortal.sol";
...@@ -30,8 +29,6 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -30,8 +29,6 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(address(op).balance, 100); assertEq(address(op).balance, 100);
} }
// function test_OptimismPortalDepositTransaction() external {}
// Test: depositTransaction fails when contract creation has a non-zero destination address // Test: depositTransaction fails when contract creation has a non-zero destination address
function test_OptimismPortalContractCreationReverts() external { function test_OptimismPortalContractCreationReverts() external {
// contract creation must have a target of address(0) // contract creation must have a target of address(0)
...@@ -314,6 +311,84 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -314,6 +311,84 @@ contract OptimismPortal_Test is Portal_Initializer {
vm.expectRevert("L2OutputOracle: No output found for that block number."); vm.expectRevert("L2OutputOracle: No output found for that block number.");
assertEq(op.isBlockFinalized(checkpoint + 1), false); assertEq(op.isBlockFinalized(checkpoint + 1), false);
} }
function test_finalizeWithdrawalTransaction_differential(
address _sender,
address _target,
uint64 _value,
uint8 _gasLimit,
bytes memory _data
) external {
// Cannot call the optimism portal
vm.assume(_target != address(op));
uint256 _nonce = messagePasser.nonce();
(
bytes32 stateRoot,
bytes32 storageRoot,
bytes32 outputRoot,
bytes32 withdrawalHash,
bytes memory withdrawalProof
) = ffi.getFinalizeWithdrawalTransactionInputs(
_nonce,
_sender,
_target,
_value,
uint256(_gasLimit),
_data
);
Hashing.OutputRootProof memory proof = Hashing.OutputRootProof({
version: bytes32(uint256(0)),
stateRoot: stateRoot,
withdrawerStorageRoot: storageRoot,
latestBlockhash: bytes32(uint256(0))
});
// Ensure the values returned from ffi are correct
assertEq(outputRoot, Hashing.hashOutputRootProof(proof));
assertEq(withdrawalHash, Hashing.hashWithdrawal(
_nonce,
_sender,
_target,
_value,
uint64(_gasLimit),
_data
));
// Mock the call to the oracle
vm.mockCall(
address(oracle),
abi.encodeWithSelector(oracle.getL2Output.selector),
abi.encode(outputRoot, 0)
);
// Start the withdrawal, it must be initiated by the _sender and the
// correct value must be passed along
vm.deal(_sender, _value);
vm.prank(_sender);
messagePasser.initiateWithdrawal{ value: _value }(
_target,
uint256(_gasLimit),
_data
);
// Ensure that the sentMessages is correct
assertEq(messagePasser.sentMessages(withdrawalHash), true);
vm.warp(op.FINALIZATION_PERIOD_SECONDS() + 1);
op.finalizeWithdrawalTransaction{ value: _value }(
messagePasser.nonce() - 1,
_sender,
_target,
_value,
uint64(_gasLimit),
_data,
100, // l2BlockNumber
proof,
withdrawalProof
);
}
} }
contract OptimismPortalUpgradeable_Test is Portal_Initializer { contract OptimismPortalUpgradeable_Test is Portal_Initializer {
......
...@@ -16,3 +16,8 @@ remappings = [ ...@@ -16,3 +16,8 @@ remappings = [
extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout']
bytecode_hash = 'none' bytecode_hash = 'none'
build_info = true build_info = true
ffi = true
fuzz_runs = 16
[ci]
fuzz_runs = 512
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
"build": "hardhat compile && yarn build:ts && yarn typechain", "build": "hardhat compile && yarn build:ts && yarn typechain",
"build:ts": "tsc -p tsconfig.json", "build:ts": "tsc -p tsconfig.json",
"deploy": "hardhat deploy", "deploy": "hardhat deploy",
"test": "forge test", "test": "yarn build:ts && forge test",
"gas-snapshot": "forge snapshot", "gas-snapshot": "forge snapshot",
"storage-snapshot": "./scripts/storage-snapshot.sh", "storage-snapshot": "./scripts/storage-snapshot.sh",
"slither": "./scripts/slither.sh", "slither": "./scripts/slither.sh",
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
}, },
"dependencies": { "dependencies": {
"@eth-optimism/core-utils": "^0.9.1", "@eth-optimism/core-utils": "^0.9.1",
"@ethereumjs/trie": "^5.0.0-beta.1",
"@ethereumjs/util": "^8.0.0-beta.1",
"@openzeppelin/contracts": "^4.5.0", "@openzeppelin/contracts": "^4.5.0",
"@openzeppelin/contracts-upgradeable": "^4.5.2", "@openzeppelin/contracts-upgradeable": "^4.5.2",
"@rari-capital/solmate": "https://github.com/rari-capital/solmate.git#8f9b23f8838670afda0fd8983f2c41e8037ae6bc", "@rari-capital/solmate": "https://github.com/rari-capital/solmate.git#8f9b23f8838670afda0fd8983f2c41e8037ae6bc",
...@@ -43,7 +45,7 @@ ...@@ -43,7 +45,7 @@
"ethereumjs-wallet": "^1.0.2", "ethereumjs-wallet": "^1.0.2",
"ethers": "^5.6.8", "ethers": "^5.6.8",
"excessively-safe-call": "https://github.com/nomad-xyz/ExcessivelySafeCall.git#4fcdfd3593d21381f696c790fa6180b8ef559c1e", "excessively-safe-call": "https://github.com/nomad-xyz/ExcessivelySafeCall.git#4fcdfd3593d21381f696c790fa6180b8ef559c1e",
"forge-std": "https://github.com/foundry-rs/forge-std.git#62caef29b0f87a2c6aaaf634b2ca4c09b6867c92", "forge-std": "https://github.com/foundry-rs/forge-std.git#f18682b2874fc57d7c80a511fed0b35ec4201ffa",
"hardhat": "^2.9.6", "hardhat": "^2.9.6",
"merkle-patricia-tree": "^4.2.4", "merkle-patricia-tree": "^4.2.4",
"rlp": "^2.2.7" "rlp": "^2.2.7"
......
import { BigNumber, utils, constants } from 'ethers'
import {
decodeVersionedNonce,
hashCrossDomainMessage,
DepositTx,
SourceHashDomain,
encodeCrossDomainMessage,
hashWithdrawal,
hashOutputRootProof,
} from '@eth-optimism/core-utils'
import { SecureTrie } from '@ethereumjs/trie'
import { Account, Address, toBuffer, bufferToHex } from '@ethereumjs/util'
import { predeploys } from '../src'
const { hexZeroPad, RLP, keccak256 } = utils
const args = process.argv.slice(2)
const command = args[0]
;(async () => {
switch (command) {
case 'decodeVersionedNonce': {
const input = BigNumber.from(args[1])
const [nonce, version] = decodeVersionedNonce(input)
const output = utils.defaultAbiCoder.encode(
['uint256', 'uint256'],
[nonce.toHexString(), version.toHexString()]
)
process.stdout.write(output)
break
}
case 'encodeCrossDomainMessage': {
const nonce = BigNumber.from(args[1])
const sender = args[2]
const target = args[3]
const value = BigNumber.from(args[4])
const gasLimit = BigNumber.from(args[5])
const data = args[6]
const encoding = encodeCrossDomainMessage(
nonce,
sender,
target,
value,
gasLimit,
data
)
const output = utils.defaultAbiCoder.encode(['bytes'], [encoding])
process.stdout.write(output)
break
}
case 'hashCrossDomainMessage': {
const nonce = BigNumber.from(args[1])
const sender = args[2]
const target = args[3]
const value = BigNumber.from(args[4])
const gasLimit = BigNumber.from(args[5])
const data = args[6]
const hash = hashCrossDomainMessage(
nonce,
sender,
target,
value,
gasLimit,
data
)
const output = utils.defaultAbiCoder.encode(['bytes32'], [hash])
process.stdout.write(output)
break
}
case 'hashDepositTransaction': {
// The solidity transaction hash computation currently only works with
// user deposits. System deposit transaction hashing is not supported.
const l1BlockHash = args[1]
const logIndex = BigNumber.from(args[2])
const from = args[3]
const to = args[4]
const mint = BigNumber.from(args[5])
const value = BigNumber.from(args[6])
const gas = BigNumber.from(args[7])
const data = args[8]
const tx = new DepositTx({
l1BlockHash,
logIndex,
from,
to,
mint,
value,
gas,
data,
domain: SourceHashDomain.UserDeposit,
})
const digest = tx.hash()
const output = utils.defaultAbiCoder.encode(['bytes32'], [digest])
process.stdout.write(output)
break
}
case 'hashWithdrawal': {
const nonce = BigNumber.from(args[1])
const sender = args[2]
const target = args[3]
const value = BigNumber.from(args[4])
const gas = BigNumber.from(args[5])
const data = args[6]
const hash = hashWithdrawal(nonce, sender, target, value, gas, data)
const output = utils.defaultAbiCoder.encode(['bytes32'], [hash])
process.stdout.write(output)
break
}
case 'hashOutputRootProof': {
const version = hexZeroPad(BigNumber.from(args[1]).toHexString(), 32)
const stateRoot = hexZeroPad(BigNumber.from(args[2]).toHexString(), 32)
const withdrawerStorageRoot = hexZeroPad(
BigNumber.from(args[3]).toHexString(),
32
)
const latestBlockhash = hexZeroPad(
BigNumber.from(args[4]).toHexString(),
32
)
const hash = hashOutputRootProof({
version,
stateRoot,
withdrawerStorageRoot,
latestBlockhash,
})
const output = utils.defaultAbiCoder.encode(['bytes32'], [hash])
process.stdout.write(output)
break
}
case 'getFinalizeWithdrawalTransactionInputs': {
const nonce = BigNumber.from(args[1])
const sender = args[2]
const target = args[3]
const value = BigNumber.from(args[4])
const gas = BigNumber.from(args[5])
const data = args[6]
// Compute the withdrawalHash
const withdrawalHash = hashWithdrawal(
nonce,
sender,
target,
value,
gas,
data
)
// Compute the storage slot the withdrawalHash will be stored in
const slot = utils.defaultAbiCoder.encode(
['bytes32', 'bytes32'],
[withdrawalHash, utils.hexZeroPad('0x', 32)]
)
const key = keccak256(slot)
// Create the account storage trie
const storage = new SecureTrie()
// Put a bool "true" into storage
await storage.put(toBuffer(key), toBuffer('0x01'))
// Put the storage root into the L2ToL1MessagePasser storage
const address = Address.fromString(predeploys.L2ToL1MessagePasser)
const account = Account.fromAccountData({
nonce: 0,
balance: 0,
stateRoot: storage.root,
})
const world = new SecureTrie()
await world.put(address.toBuffer(), account.serialize())
const proof = await SecureTrie.createProof(storage, toBuffer(key))
const outputRoot = hashOutputRootProof({
version: constants.HashZero,
stateRoot: bufferToHex(world.root),
withdrawerStorageRoot: bufferToHex(storage.root),
latestBlockhash: constants.HashZero,
})
const encodedProof = RLP.encode(proof)
const output = utils.defaultAbiCoder.encode(
['bytes32', 'bytes32', 'bytes32', 'bytes32', 'bytes'],
[world.root, storage.root, outputRoot, withdrawalHash, encodedProof]
)
process.stdout.write(output)
break
}
}
})().catch((err: Error) => {
console.error(err)
process.stdout.write('')
})
// Script for generating an inclusion proof for use in testing
// Intended for use with forge test --ffi, accepts abi encoded input and returns
// only the storageTrieWitness.
import { generateMockWithdrawalProof } from '../helpers'
let args = process.argv.slice(2)[0]
args = args
.replace('0x', '')
.split('')
.filter((char) => '0123456789abcdef'.includes(char))
.join('')
const main = async () => {
const proof = await generateMockWithdrawalProof('0x' + args)
console.log(proof.storageTrieWitness.slice(2))
}
main()
// Script for generating an inclusion proof for use in testing.
// Meant for manual usage, ie.
// ts-node scripts/makeProof.ts 1 0x0000000000000000000000000000000000000002 0x0000000000000000000000000000000000000003 4 500000 0x06
import { generateMockWithdrawalProof } from '../helpers'
const args = process.argv.slice(2)
const [nonce, sender, target, value, gasLimit, data] = args
const main = async () => {
const proof = await generateMockWithdrawalProof({
nonce: +nonce,
sender,
target,
value: +value,
gasLimit: +gasLimit,
data,
})
console.log(proof)
}
main()
import { ethers } from 'ethers'
import { toHexString } from '@eth-optimism/core-utils'
import { TrieTestGenerator } from './trie-test-generator'
import { predeploys } from './constants'
interface WithdrawalArgs {
nonce: number
sender: string
target: string
value: number
gasLimit: number
data: string
}
interface OutputRootProof {
version: string
stateRoot: string
withdrawerStorageRoot: string
latestBlockhash: string
}
export const deriveWithdrawalHash = (wd: WithdrawalArgs): string => {
return ethers.utils.keccak256(
ethers.utils.defaultAbiCoder.encode(
['uint256', 'address', 'address', 'uint256', 'uint256', 'bytes'],
[wd.nonce, wd.sender, wd.target, wd.value, wd.gasLimit, wd.data]
)
)
}
export const generateMockWithdrawalProof = async (
wd: WithdrawalArgs | string
): Promise<{
outputRootProof: OutputRootProof
storageTrieWitness: string
}> => {
let withdrawalHash
if (typeof wd == 'string') {
// wd should be an abi encoded string
withdrawalHash = ethers.utils.keccak256(wd)
} else {
withdrawalHash = deriveWithdrawalHash(wd as WithdrawalArgs)
}
const storageKey = ethers.utils.keccak256(
ethers.utils.hexConcat([
withdrawalHash,
ethers.utils.hexZeroPad('0x01', 32),
])
)
const storageGenerator = await TrieTestGenerator.fromNodes({
nodes: [
{
key: storageKey,
val: '0x' + '01'.padStart(2, '0'),
},
],
secure: true,
})
const generator = await TrieTestGenerator.fromAccounts({
accounts: [
{
address: predeploys.L2ToL1MessagePasser,
nonce: 0,
balance: 0,
codeHash: ethers.utils.keccak256('0x1234'),
storageRoot: toHexString(storageGenerator._trie.root),
},
],
secure: true,
})
return {
outputRootProof: {
version: ethers.constants.HashZero,
stateRoot: toHexString(generator._trie.root),
withdrawerStorageRoot: toHexString(storageGenerator._trie.root),
latestBlockhash: ethers.constants.HashZero,
},
storageTrieWitness: (
await storageGenerator.makeInclusionProofTest(storageKey)
).proof,
}
}
export const generateOutputRoot = (outputElements: {
version: string
stateRoot: string
withdrawerStorageRoot: string
latestBlockhash: string
}) => {
const { version, stateRoot, withdrawerStorageRoot, latestBlockhash } =
outputElements
return ethers.utils.solidityKeccak256(
['bytes32', 'bytes32', 'bytes32', 'bytes32'],
[version, stateRoot, withdrawerStorageRoot, latestBlockhash]
)
}
export * from './generateProofs'
export * from './constants' export * from './constants'
/* External Imports */
import * as rlp from 'rlp'
// import { default as seedbytes } from 'random-bytes-seed'
import { SecureTrie, BaseTrie } from 'merkle-patricia-tree'
import { fromHexString, toHexString } from '@eth-optimism/core-utils'
import { ethers } from 'ethers'
interface TrieNode {
key: string
val: string
}
interface InclusionProofTest {
key: string
val: string
proof: string
root: string
}
interface NodeUpdateTest extends InclusionProofTest {
newRoot: string
}
interface EthereumAccount {
address?: string
nonce: number
balance: number
codeHash: string
storageRoot?: string
storage?: TrieNode[]
}
interface AccountProofTest {
address: string
account: EthereumAccount
accountTrieWitness: string
accountTrieRoot: string
}
interface AccountUpdateTest extends AccountProofTest {
newAccountTrieRoot: string
}
const rlpEncodeAccount = (account: EthereumAccount): string => {
return toHexString(
rlp.encode([
account.nonce,
account.balance,
account.storageRoot || ethers.constants.HashZero,
account.codeHash || ethers.constants.HashZero,
])
)
}
const rlpDecodeAccount = (encoded: string): EthereumAccount => {
const decoded = rlp.decode(fromHexString(encoded)) as any
return {
nonce: decoded[0].length ? parseInt(decoded[0], 16) : 0,
balance: decoded[1].length ? parseInt(decoded[1], 16) : 0,
storageRoot: decoded[2].length
? toHexString(decoded[2])
: ethers.constants.HashZero,
codeHash: decoded[3].length
? toHexString(decoded[3])
: ethers.constants.HashZero,
}
}
const makeTrie = async (
nodes: TrieNode[],
secure?: boolean
): Promise<{
trie: SecureTrie | BaseTrie
TrieClass: any
}> => {
const TrieClass = secure ? SecureTrie : BaseTrie
const trie = new TrieClass()
for (const node of nodes) {
await trie.put(fromHexString(node.key), fromHexString(node.val))
}
return {
trie,
TrieClass,
}
}
export class TrieTestGenerator {
constructor(
public _TrieClass: any,
public _trie: SecureTrie | BaseTrie,
public _nodes: TrieNode[],
public _subGenerators?: TrieTestGenerator[]
) {}
static async fromNodes(opts: {
nodes: TrieNode[]
secure?: boolean
}): Promise<TrieTestGenerator> {
const { trie, TrieClass } = await makeTrie(opts.nodes, opts.secure)
return new TrieTestGenerator(TrieClass, trie, opts.nodes)
}
// static async fromRandom(opts: {
// seed: string
// nodeCount: number
// secure?: boolean
// keySize?: number
// valSize?: number
// }): Promise<TrieTestGenerator> {
// const getRandomBytes = seedbytes(opts.seed)
// const nodes: TrieNode[] = [...Array(opts.nodeCount)].map(() => {
// return {
// key: toHexString(getRandomBytes(opts.keySize || 32)),
// val: toHexString(getRandomBytes(opts.valSize || 32)),
// }
// })
// return TrieTestGenerator.fromNodes({
// nodes,
// secure: opts.secure,
// })
// }
static async fromAccounts(opts: {
accounts: EthereumAccount[]
secure?: boolean
}): Promise<TrieTestGenerator> {
const subGenerators: TrieTestGenerator[] = []
for (const account of opts.accounts) {
if (account.storage) {
const subGenerator = await TrieTestGenerator.fromNodes({
nodes: account.storage,
secure: opts.secure,
})
account.storageRoot = toHexString(subGenerator._trie.root)
subGenerators.push(subGenerator)
}
}
const nodes = opts.accounts.map((account) => {
return {
key: account.address as string,
val: rlpEncodeAccount(account),
}
})
const { trie, TrieClass } = await makeTrie(nodes, opts.secure)
return new TrieTestGenerator(TrieClass, trie, nodes, subGenerators)
}
public async makeInclusionProofTest(
key: string | number
): Promise<InclusionProofTest> {
if (typeof key === 'number') {
key = this._nodes[key].key
}
const trie = this._trie.copy()
const proof = await this.prove(key)
const val = await trie.get(fromHexString(key))
return {
proof: toHexString(rlp.encode(proof)),
key: toHexString(key),
val: toHexString(val),
root: toHexString(trie.root),
}
}
public async makeAllInclusionProofTests(): Promise<InclusionProofTest[]> {
return Promise.all(
this._nodes.map(async (node) => {
return this.makeInclusionProofTest(node.key)
})
)
}
public async makeNodeUpdateTest(
key: string | number,
val: string
): Promise<NodeUpdateTest> {
if (typeof key === 'number') {
key = this._nodes[key].key
}
const trie = this._trie.copy()
const proof = await this.prove(key)
const oldRoot = trie.root
await trie.put(fromHexString(key), fromHexString(val))
const newRoot = trie.root
return {
proof: toHexString(rlp.encode(proof)),
key: toHexString(key),
val: toHexString(val),
root: toHexString(oldRoot),
newRoot: toHexString(newRoot),
}
}
public async makeAccountProofTest(
address: string | number
): Promise<AccountProofTest> {
if (typeof address === 'number') {
address = this._nodes[address].key
}
const trie = this._trie.copy()
const proof = await this.prove(address)
const account = await trie.get(fromHexString(address))
return {
address,
account: rlpDecodeAccount(toHexString(account)),
accountTrieWitness: toHexString(rlp.encode(proof)),
accountTrieRoot: toHexString(trie.root),
}
}
public async makeAccountUpdateTest(
address: string | number,
account: EthereumAccount
): Promise<AccountUpdateTest> {
if (typeof address === 'number') {
address = this._nodes[address].key
}
const trie = this._trie.copy()
const proof = await this.prove(address)
const oldRoot = trie.root
await trie.put(
fromHexString(address),
fromHexString(rlpEncodeAccount(account))
)
const newRoot = trie.root
return {
address,
account,
accountTrieWitness: toHexString(rlp.encode(proof)),
accountTrieRoot: toHexString(oldRoot),
newAccountTrieRoot: toHexString(newRoot),
}
}
private async prove(key: string): Promise<any> {
return this._TrieClass.prove(this._trie, fromHexString(key))
}
}
import { expect } from 'chai'
import { BigNumber } from 'ethers'
import { DepositTx, SourceHashDomain } from '../src'
describe('Helpers', () => {
describe('DepositTx', () => {
// TODO(tynes): this is out of date now that the subversion
// byte has been added
it('should serialize/deserialize and hash', () => {
// constants serialized using optimistic-geth
// TODO(tynes): more tests
const hash =
'0xf58e30138cb01330f6450b9a5e717a63840ad2e21f17340105b388ad3c668749'
const raw =
'0x7e00f862a0f923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc94f39fd6e51aad88f6f4ce6ab8827279cfffb9226694b79f76ef2c5f0286176833e7b2eee103b1cc3244880e043da617250000880de0b6b3a7640000832dc6c080'
const tx = new DepositTx({
from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
gas: '0x2dc6c0',
data: '0x',
to: '0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244',
value: '0xde0b6b3a7640000',
domain: SourceHashDomain.UserDeposit,
l1BlockHash:
'0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959',
logIndex: 1,
mint: '0xe043da617250000',
})
const sourceHash = tx.sourceHash()
expect(sourceHash).to.deep.eq(
'0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc'
)
const encoded = tx.encode()
expect(encoded).to.deep.eq(raw)
const hashed = tx.hash()
expect(hashed).to.deep.eq(hash)
const decoded = DepositTx.decode(raw, {
domain: SourceHashDomain.UserDeposit,
l1BlockHash: tx.l1BlockHash,
logIndex: tx.logIndex,
})
expect(decoded.from).to.deep.eq(tx.from)
expect(decoded.gas).to.deep.eq(BigNumber.from(tx.gas))
expect(decoded.data).to.deep.eq(tx.data)
expect(decoded.to).to.deep.eq(tx.to)
expect(decoded.value).to.deep.eq(BigNumber.from(tx.value))
expect(decoded.domain).to.deep.eq(SourceHashDomain.UserDeposit)
expect(decoded.l1BlockHash).to.deep.eq(tx.l1BlockHash)
expect(decoded.logIndex).to.deep.eq(tx.logIndex)
expect(decoded.mint).to.deep.eq(BigNumber.from(tx.mint))
})
})
})
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"rootDir": "./src", "rootDir": ".",
"outDir": "./dist" "outDir": "./dist"
}, },
"exclude": ["hardhat.config.ts", "deploy", "tasks", "test"], "exclude": ["hardhat.config.ts", "deploy", "tasks", "test"],
"include": ["src/**/*"] "include": ["src/**/*", "scripts/differential-testing.ts"]
} }
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
"ds-test": "https://github.com/dapphub/ds-test.git#9310e879db8ba3ea6d5c6489a579118fd264a3f5", "ds-test": "https://github.com/dapphub/ds-test.git#9310e879db8ba3ea6d5c6489a579118fd264a3f5",
"ethereum-waffle": "^3.4.4", "ethereum-waffle": "^3.4.4",
"ethers": "^5.6.8", "ethers": "^5.6.8",
"forge-std": "https://github.com/foundry-rs/forge-std.git#62caef29b0f87a2c6aaaf634b2ca4c09b6867c92", "forge-std": "https://github.com/foundry-rs/forge-std.git#f18682b2874fc57d7c80a511fed0b35ec4201ffa",
"hardhat": "^2.9.6", "hardhat": "^2.9.6",
"hardhat-deploy": "^0.11.10", "hardhat-deploy": "^0.11.10",
"hardhat-gas-reporter": "^1.0.8", "hardhat-gas-reporter": "^1.0.8",
......
import { ethers, BigNumberish, BigNumber } from 'ethers'
const iface = new ethers.utils.Interface([
'function relayMessage(address,address,bytes,uint256)',
'function relayMessage(uint256,address,address,uint256,uint256,bytes)',
])
const nonceMask = BigNumber.from(
'0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
)
export const big0 = BigNumber.from(0)
export const big1 = BigNumber.from(1)
/**
* Encodes the version into the nonce.
*
* @param nonce
* @param version
*/
export const encodeVersionedNonce = (
nonce: BigNumber,
version: BigNumber
): BigNumber => {
return version.or(nonce.shl(240))
}
/**
* Decodes the version from the nonce and returns the unversioned nonce as well
* as the version. The version is encoded in the first byte of
* the nonce. Note that this nonce is the nonce held in the
* CrossDomainMessenger.
*
* @param nonce
*/
export const decodeVersionedNonce = (nonce: BigNumber): BigNumber[] => {
return [nonce.and(nonceMask), nonce.shr(240)]
}
/**
* Encodes a V1 cross domain message. This message format was used before
* bedrock and does not support value transfer because ETH was represented as an
* ERC20 natively.
*
* @param target The target of the cross domain message
* @param sender The sender of the cross domain message
* @param data The data passed along with the cross domain message
* @param nonce The cross domain message nonce
*/
export const encodeCrossDomainMessageV0 = (
target: string,
sender: string,
data: string,
nonce: BigNumber
) => {
return iface.encodeFunctionData(
'relayMessage(address,address,bytes,uint256)',
[target, sender, data, nonce]
)
}
/**
* Encodes a V1 cross domain message. This message format shipped with bedrock
* and supports value transfer with native ETH.
*
* @param nonce The cross domain message nonce
* @param sender The sender of the cross domain message
* @param target The target of the cross domain message
* @param value The value being sent with the cross domain message
* @param gasLimit The gas limit of the cross domain execution
* @param data The data passed along with the cross domain message
*/
export const encodeCrossDomainMessageV1 = (
nonce: BigNumber,
sender: string,
target: string,
value: BigNumberish,
gasLimit: BigNumberish,
data: string
) => {
return iface.encodeFunctionData(
'relayMessage(uint256,address,address,uint256,uint256,bytes)',
[nonce, sender, target, value, gasLimit, data]
)
}
/**
* Encodes a cross domain message. The version byte in the nonce determines
* the serialization format that is used.
*
* @param nonce The cross domain message nonce
* @param sender The sender of the cross domain message
* @param target The target of the cross domain message
* @param value The value being sent with the cross domain message
* @param gasLimit The gas limit of the cross domain execution
* @param data The data passed along with the cross domain message
*/
export const encodeCrossDomainMessage = (
nonce: BigNumber,
sender: string,
target: string,
value: BigNumber,
gasLimit: BigNumber,
data: string
) => {
const [, version] = decodeVersionedNonce(nonce)
if (version.eq(big0)) {
return encodeCrossDomainMessageV0(target, sender, data, nonce)
} else if (version.eq(big1)) {
return encodeCrossDomainMessageV1(
nonce,
sender,
target,
value,
gasLimit,
data
)
}
throw new Error(`unknown version ${version.toString()}`)
}
import { BigNumberish, BigNumber, utils } from 'ethers'
const { keccak256, defaultAbiCoder } = utils
import {
decodeVersionedNonce,
encodeCrossDomainMessageV0,
encodeCrossDomainMessageV1,
big0,
big1,
} from './encoding'
export interface OutputRootProof {
version: string
stateRoot: string
withdrawerStorageRoot: string
latestBlockhash: string
}
/**
* Hahses a cross domain message.
*
* @param nonce The cross domain message nonce
* @param sender The sender of the cross domain message
* @param target The target of the cross domain message
* @param value The value being sent with the cross domain message
* @param gasLimit The gas limit of the cross domain execution
* @param data The data passed along with the cross domain message
*/
export const hashCrossDomainMessage = (
nonce: BigNumber,
sender: string,
target: string,
value: BigNumber,
gasLimit: BigNumber,
data: string
) => {
const [, version] = decodeVersionedNonce(nonce)
if (version.eq(big0)) {
return hashCrossDomainMessagev0(target, sender, data, nonce)
} else if (version.eq(big1)) {
return hashCrossDomainMessagev1(
nonce,
sender,
target,
value,
gasLimit,
data
)
}
throw new Error(`unknown version ${version.toString()}`)
}
/**
* Hahses a V0 cross domain message
*
* @param target The target of the cross domain message
* @param sender The sender of the cross domain message
* @param data The data passed along with the cross domain message
* @param nonce The cross domain message nonce
*/
export const hashCrossDomainMessagev0 = (
target: string,
sender: string,
data: string,
nonce: BigNumber
) => {
return keccak256(encodeCrossDomainMessageV0(target, sender, data, nonce))
}
/**
* Hahses a V1 cross domain message
*
* @param nonce The cross domain message nonce
* @param sender The sender of the cross domain message
* @param target The target of the cross domain message
* @param value The value being sent with the cross domain message
* @param gasLimit The gas limit of the cross domain execution
* @param data The data passed along with the cross domain message
*/
export const hashCrossDomainMessagev1 = (
nonce: BigNumber,
sender: string,
target: string,
value: BigNumberish,
gasLimit: BigNumberish,
data: string
) => {
return keccak256(
encodeCrossDomainMessageV1(nonce, sender, target, value, gasLimit, data)
)
}
/**
* Hashes a withdrawal
*
* @param nonce The cross domain message nonce
* @param sender The sender of the cross domain message
* @param target The target of the cross domain message
* @param value The value being sent with the cross domain message
* @param gasLimit The gas limit of the cross domain execution
* @param data The data passed along with the cross domain message
*/
export const hashWithdrawal = (
nonce: BigNumber,
sender: string,
target: string,
value: BigNumber,
gasLimit: BigNumber,
data: string
): string => {
const types = ['uint256', 'address', 'address', 'uint256', 'uint256', 'bytes']
const encoded = defaultAbiCoder.encode(types, [
nonce,
sender,
target,
value,
gasLimit,
data,
])
return keccak256(encoded)
}
/**
* Hahses an output root proof
*
* @param proof OutputRootProof
*/
export const hashOutputRootProof = (proof: OutputRootProof): string => {
return keccak256(
defaultAbiCoder.encode(
['bytes32', 'bytes32', 'bytes32', 'bytes32'],
[
proof.version,
proof.stateRoot,
proof.withdrawerStorageRoot,
proof.latestBlockhash,
]
)
)
}
...@@ -8,3 +8,5 @@ export * from './fees' ...@@ -8,3 +8,5 @@ export * from './fees'
export * from './rollup-types' export * from './rollup-types'
export * from './op-node' export * from './op-node'
export * from './deposit-transaction' export * from './deposit-transaction'
export * from './encoding'
export * from './hashing'
...@@ -827,6 +827,20 @@ ...@@ -827,6 +827,20 @@
ethereumjs-util "^7.1.1" ethereumjs-util "^7.1.1"
miller-rabin "^4.0.0" miller-rabin "^4.0.0"
"@ethereumjs/trie@^5.0.0-beta.1":
version "5.0.0-beta.1"
resolved "https://registry.yarnpkg.com/@ethereumjs/trie/-/trie-5.0.0-beta.1.tgz#79d1108222b45bc3576d62583364c96626ce4175"
integrity sha512-OjTzt9fK5aMzm84GRSe+C7bO2zorbEWRueLbxOMlS7lHCiXA7akIQ3mzz9VBSMjT7m01hZ1r3fZIOGHzQVCHtw==
dependencies:
"@ethereumjs/util" "8.0.0-beta.1"
abstract-level "^1.0.3"
ethereum-cryptography "^1.0.3"
level "^8.0.0"
memory-level "^1.0.0"
readable-stream "^3.6.0"
rlp "4.0.0-beta.1"
semaphore-async-await "^1.5.1"
"@ethereumjs/tx@^3.2.1": "@ethereumjs/tx@^3.2.1":
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.0.tgz#14ed1b7fa0f28e1cd61e3ecbdab824205f6a4378" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.0.tgz#14ed1b7fa0f28e1cd61e3ecbdab824205f6a4378"
...@@ -851,6 +865,14 @@ ...@@ -851,6 +865,14 @@
"@ethereumjs/common" "^2.6.3" "@ethereumjs/common" "^2.6.3"
ethereumjs-util "^7.1.4" ethereumjs-util "^7.1.4"
"@ethereumjs/util@8.0.0-beta.1", "@ethereumjs/util@^8.0.0-beta.1":
version "8.0.0-beta.1"
resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.0.0-beta.1.tgz#369526faf6e9f1cadfd39c7741cc07cf33d128f8"
integrity sha512-yUg3TdJm25HiamAXbNuOagXQPmgdSrV3oEH0h+Adsxt6D7qHw8HyHLA8C+tNrLP2YwcjF1dGJ+F7WtOibzEp9g==
dependencies:
ethereum-cryptography "^1.0.3"
rlp "4.0.0-beta.1"
"@ethereumjs/vm@^5.9.0": "@ethereumjs/vm@^5.9.0":
version "5.9.0" version "5.9.0"
resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.9.0.tgz#54e485097c6dbb42554d541ef8d84d06b7ddf12f" resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.9.0.tgz#54e485097c6dbb42554d541ef8d84d06b7ddf12f"
...@@ -3183,14 +3205,6 @@ ...@@ -3183,14 +3205,6 @@
fs-extra "^9.1.0" fs-extra "^9.1.0"
lodash "^4.17.15" lodash "^4.17.15"
"@typechain/hardhat@^6.1.2":
version "6.1.2"
resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.1.2.tgz#d3beccc6937d93f9b437616b741f839a8b953693"
integrity sha512-k4Ea3pVITKB2DH8p1a5U38cyy7KZPD04Spo4q5b4wO+n2mT+uAz5dxckPtbczn/Kk5wiFq+ZkuOtw5ZKFhL/+w==
dependencies:
fs-extra "^9.1.0"
lodash "^4.17.15"
"@types/abstract-leveldown@*": "@types/abstract-leveldown@*":
version "5.0.2" version "5.0.2"
resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.2.tgz#ee81917fe38f770e29eec8139b6f16ee4a8b0a5f" resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.2.tgz#ee81917fe38f770e29eec8139b6f16ee4a8b0a5f"
...@@ -3896,6 +3910,19 @@ abort-controller@^3.0.0: ...@@ -3896,6 +3910,19 @@ abort-controller@^3.0.0:
dependencies: dependencies:
event-target-shim "^5.0.0" event-target-shim "^5.0.0"
abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741"
integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==
dependencies:
buffer "^6.0.3"
catering "^2.1.0"
is-buffer "^2.0.5"
level-supports "^4.0.0"
level-transcoder "^1.0.1"
module-error "^1.0.1"
queue-microtask "^1.2.3"
abstract-leveldown@3.0.0: abstract-leveldown@3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57"
...@@ -5310,6 +5337,16 @@ brorand@^1.0.1, brorand@^1.1.0: ...@@ -5310,6 +5337,16 @@ brorand@^1.0.1, brorand@^1.1.0:
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
browser-level@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011"
integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==
dependencies:
abstract-level "^1.0.2"
catering "^2.1.1"
module-error "^1.0.2"
run-parallel-limit "^1.1.0"
browser-stdout@1.3.1: browser-stdout@1.3.1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
...@@ -5444,6 +5481,14 @@ buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: ...@@ -5444,6 +5481,14 @@ buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0:
base64-js "^1.3.1" base64-js "^1.3.1"
ieee754 "^1.1.13" ieee754 "^1.1.13"
buffer@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.2.1"
bufferutil@^4.0.1: bufferutil@^4.0.1:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b" resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b"
...@@ -5669,6 +5714,11 @@ caseless@^0.12.0, caseless@~0.12.0: ...@@ -5669,6 +5714,11 @@ caseless@^0.12.0, caseless@~0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
catering@^2.1.0, catering@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510"
integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==
cbor@^5.0.2: cbor@^5.0.2:
version "5.2.0" version "5.2.0"
resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c" resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c"
...@@ -5901,6 +5951,17 @@ class-utils@^0.3.5: ...@@ -5901,6 +5951,17 @@ class-utils@^0.3.5:
isobject "^3.0.0" isobject "^3.0.0"
static-extend "^0.1.1" static-extend "^0.1.1"
classic-level@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27"
integrity sha512-qw5B31ANxSluWz9xBzklRWTUAJ1SXIdaVKTVS7HcTGKOAmExx65Wo5BUICW+YGORe2FOUaDghoI9ZDxj82QcFg==
dependencies:
abstract-level "^1.0.2"
catering "^2.1.0"
module-error "^1.0.1"
napi-macros "~2.0.0"
node-gyp-build "^4.3.0"
clean-regexp@^1.0.0: clean-regexp@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7" resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7"
...@@ -8994,9 +9055,9 @@ forever-agent@~0.6.1: ...@@ -8994,9 +9055,9 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
"forge-std@https://github.com/foundry-rs/forge-std.git#62caef29b0f87a2c6aaaf634b2ca4c09b6867c92": "forge-std@https://github.com/foundry-rs/forge-std.git#f18682b2874fc57d7c80a511fed0b35ec4201ffa":
version "0.0.0" version "0.0.0"
resolved "https://github.com/foundry-rs/forge-std.git#62caef29b0f87a2c6aaaf634b2ca4c09b6867c92" resolved "https://github.com/foundry-rs/forge-std.git#f18682b2874fc57d7c80a511fed0b35ec4201ffa"
form-data@^2.2.0: form-data@^2.2.0:
version "2.5.1" version "2.5.1"
...@@ -10113,7 +10174,7 @@ idna-uts46-hx@^2.3.1: ...@@ -10113,7 +10174,7 @@ idna-uts46-hx@^2.3.1:
dependencies: dependencies:
punycode "2.1.0" punycode "2.1.0"
ieee754@^1.1.13: ieee754@^1.1.13, ieee754@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
...@@ -10399,7 +10460,7 @@ is-buffer@^1.1.4, is-buffer@^1.1.5: ...@@ -10399,7 +10460,7 @@ is-buffer@^1.1.4, is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-buffer@~2.0.3: is-buffer@^2.0.5, is-buffer@~2.0.3:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
...@@ -11399,6 +11460,11 @@ level-sublevel@6.6.4: ...@@ -11399,6 +11460,11 @@ level-sublevel@6.6.4:
typewiselite "~1.0.0" typewiselite "~1.0.0"
xtend "~4.0.0" xtend "~4.0.0"
level-supports@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a"
integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==
level-supports@~1.0.0: level-supports@~1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d"
...@@ -11406,6 +11472,14 @@ level-supports@~1.0.0: ...@@ -11406,6 +11472,14 @@ level-supports@~1.0.0:
dependencies: dependencies:
xtend "^4.0.2" xtend "^4.0.2"
level-transcoder@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c"
integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==
dependencies:
buffer "^6.0.3"
module-error "^1.0.1"
level-ws@0.0.0: level-ws@0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b"
...@@ -11441,6 +11515,14 @@ level@^6.0.1: ...@@ -11441,6 +11515,14 @@ level@^6.0.1:
level-packager "^5.1.0" level-packager "^5.1.0"
leveldown "^5.4.0" leveldown "^5.4.0"
level@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394"
integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==
dependencies:
browser-level "^1.0.1"
classic-level "^1.2.0"
leveldown@^5.4.0: leveldown@^5.4.0:
version "5.6.0" version "5.6.0"
resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-5.6.0.tgz#16ba937bb2991c6094e13ac5a6898ee66d3eee98" resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-5.6.0.tgz#16ba937bb2991c6094e13ac5a6898ee66d3eee98"
...@@ -12102,6 +12184,15 @@ memdown@~3.0.0: ...@@ -12102,6 +12184,15 @@ memdown@~3.0.0:
ltgt "~2.2.0" ltgt "~2.2.0"
safe-buffer "~5.1.1" safe-buffer "~5.1.1"
memory-level@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692"
integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==
dependencies:
abstract-level "^1.0.0"
functional-red-black-tree "^1.0.1"
module-error "^1.0.1"
memorystream@^0.3.1: memorystream@^0.3.1:
version "0.3.1" version "0.3.1"
resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
...@@ -12665,6 +12756,11 @@ modify-values@^1.0.0: ...@@ -12665,6 +12756,11 @@ modify-values@^1.0.0:
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
module-error@^1.0.1, module-error@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86"
integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==
morgan@^1.10.0: morgan@^1.10.0:
version "1.10.0" version "1.10.0"
resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7"
...@@ -12910,6 +13006,11 @@ node-gyp-build@^4.2.0: ...@@ -12910,6 +13006,11 @@ node-gyp-build@^4.2.0:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739"
integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==
node-gyp-build@^4.3.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40"
integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==
node-gyp-build@~4.1.0: node-gyp-build@~4.1.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb"
...@@ -14428,7 +14529,7 @@ querystring@0.2.0: ...@@ -14428,7 +14529,7 @@ querystring@0.2.0:
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
queue-microtask@^1.2.2: queue-microtask@^1.2.2, queue-microtask@^1.2.3:
version "1.2.3" version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
...@@ -15139,6 +15240,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: ...@@ -15139,6 +15240,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0" hash-base "^3.0.0"
inherits "^2.0.1" inherits "^2.0.1"
rlp@4.0.0-beta.1:
version "4.0.0-beta.1"
resolved "https://registry.yarnpkg.com/rlp/-/rlp-4.0.0-beta.1.tgz#46983ee758344e5eee48f135129407434cfea2b6"
integrity sha512-UVIENF7Rw+nX5cpfzw6X3/oXNQKsSZ8HbDJUeU9RoIs1LLyMjcPZR1o26i1vFbpuVN8GRmcdopEYOMjVsLRsQQ==
rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.6: rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.6:
version "2.2.6" version "2.2.6"
resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c"
...@@ -15163,6 +15269,13 @@ run-async@^2.2.0, run-async@^2.4.0: ...@@ -15163,6 +15269,13 @@ run-async@^2.2.0, run-async@^2.4.0:
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
run-parallel-limit@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba"
integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==
dependencies:
queue-microtask "^1.2.2"
run-parallel@^1.1.9: run-parallel@^1.1.9:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment