forked from matter-labs/era-contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request matter-labs#164 from matter-labs/dev
Syncing main with dev (tests only)
- Loading branch information
Showing
24 changed files
with
964 additions
and
833 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
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,3 +1,6 @@ | ||
[submodule "l1-contracts/lib/forge-std"] | ||
path = l1-contracts/lib/forge-std | ||
url = https://github.com/foundry-rs/forge-std | ||
[submodule "l1-contracts/lib/murky"] | ||
path = l1-contracts/lib/murky | ||
url = https://github.com/dmfxyz/murky |
19 changes: 0 additions & 19 deletions
19
l1-contracts/contracts/dev-contracts/test/TransactionValidatorTest.sol
This file was deleted.
Oops, something went wrong.
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
66 changes: 66 additions & 0 deletions
66
l1-contracts/test/foundry/unit/concrete/Merkle/Merkle.t.sol
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: MIT | ||
pragma solidity 0.8.20; | ||
|
||
import {Test} from "forge-std/Test.sol"; | ||
import {MerkleTest} from "solpp/dev-contracts/test/MerkleTest.sol"; | ||
import {MerkleTreeNoSort} from "./MerkleTreeNoSort.sol"; | ||
|
||
contract MerkleTestTest is Test { | ||
MerkleTreeNoSort merkleTree; | ||
MerkleTest merkleTest; | ||
bytes32[] elements; | ||
bytes32 root; | ||
|
||
function setUp() public { | ||
merkleTree = new MerkleTreeNoSort(); | ||
merkleTest = new MerkleTest(); | ||
|
||
for (uint256 i = 0; i < 65; i++) { | ||
elements.push(keccak256(abi.encodePacked(i))); | ||
} | ||
|
||
root = merkleTree.getRoot(elements); | ||
} | ||
|
||
function testElements(uint256 i) public { | ||
vm.assume(i < elements.length); | ||
bytes32 leaf = elements[i]; | ||
bytes32[] memory proof = merkleTree.getProof(elements, i); | ||
|
||
bytes32 rootFromContract = merkleTest.calculateRoot(proof, i, leaf); | ||
|
||
assertEq(rootFromContract, root); | ||
} | ||
|
||
function testFirstElement() public { | ||
testElements(0); | ||
} | ||
|
||
function testLastElement() public { | ||
testElements(elements.length - 1); | ||
} | ||
|
||
function testEmptyProof_shouldRevert() public { | ||
bytes32 leaf = elements[0]; | ||
bytes32[] memory proof; | ||
|
||
vm.expectRevert(bytes("xc")); | ||
merkleTest.calculateRoot(proof, 0, leaf); | ||
} | ||
|
||
function testLeafIndexTooBig_shouldRevert() public { | ||
bytes32 leaf = elements[0]; | ||
bytes32[] memory proof = merkleTree.getProof(elements, 0); | ||
|
||
vm.expectRevert(bytes("px")); | ||
merkleTest.calculateRoot(proof, 2 ** 255, leaf); | ||
} | ||
|
||
function testProofLengthTooLarge_shouldRevert() public { | ||
bytes32 leaf = elements[0]; | ||
bytes32[] memory proof = new bytes32[](256); | ||
|
||
vm.expectRevert(bytes("bt")); | ||
merkleTest.calculateRoot(proof, 0, leaf); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
l1-contracts/test/foundry/unit/concrete/Merkle/MerkleTreeNoSort.sol
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,19 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.20; | ||
|
||
import "murky/common/MurkyBase.sol"; | ||
|
||
contract MerkleTreeNoSort is MurkyBase { | ||
/******************** | ||
* HASHING FUNCTION * | ||
********************/ | ||
|
||
/// The original Merkle tree contains the ascending sort and concat prior to hashing, so we need to override it | ||
function hashLeafPairs(bytes32 left, bytes32 right) public pure override returns (bytes32 _hash) { | ||
assembly { | ||
mstore(0x0, left) | ||
mstore(0x20, right) | ||
_hash := keccak256(0x0, 0x40) | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
l1-contracts/test/foundry/unit/concrete/PriorityQueue/OnEmptyQueue.sol
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,22 @@ | ||
pragma solidity 0.8.20; | ||
|
||
import {PriorityQueueSharedTest} from "./_PriorityQueue_Shared.t.sol"; | ||
|
||
contract OnEmptyQueueTest is PriorityQueueSharedTest { | ||
function test_gets() public { | ||
assertEq(0, priorityQueue.getSize()); | ||
assertEq(0, priorityQueue.getFirstUnprocessedPriorityTx()); | ||
assertEq(0, priorityQueue.getTotalPriorityTxs()); | ||
assertTrue(priorityQueue.isEmpty()); | ||
} | ||
|
||
function test_failGetFront() public { | ||
vm.expectRevert(bytes("D")); | ||
priorityQueue.front(); | ||
} | ||
|
||
function test_failPopFront() public { | ||
vm.expectRevert(bytes("s")); | ||
priorityQueue.popFront(); | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
l1-contracts/test/foundry/unit/concrete/PriorityQueue/PopOperations.sol
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,71 @@ | ||
pragma solidity 0.8.20; | ||
|
||
import {PriorityQueueSharedTest} from "./_PriorityQueue_Shared.t.sol"; | ||
import {PriorityOperation} from "../../../../../cache/solpp-generated-contracts/dev-contracts/test/PriorityQueueTest.sol"; | ||
|
||
contract PopOperationsTest is PriorityQueueSharedTest { | ||
uint public constant NUMBER_OPERATIONS = 10; | ||
|
||
function setUp() public { | ||
push_mock_entries(NUMBER_OPERATIONS); | ||
} | ||
|
||
function test_after_pop() public { | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getSize()); | ||
|
||
PriorityOperation memory front = priorityQueue.popFront(); | ||
assertEq(keccak256(abi.encode(0)), front.canonicalTxHash); | ||
assertEq(uint64(0), front.expirationTimestamp); | ||
assertEq(uint192(0), front.layer2Tip); | ||
|
||
assertEq(NUMBER_OPERATIONS - 1, priorityQueue.getSize()); | ||
assertEq(1, priorityQueue.getFirstUnprocessedPriorityTx()); | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getTotalPriorityTxs()); | ||
assertFalse(priorityQueue.isEmpty()); | ||
|
||
// Ok - one more pop | ||
PriorityOperation memory front2 = priorityQueue.popFront(); | ||
assertEq(keccak256(abi.encode(1)), front2.canonicalTxHash); | ||
assertEq(uint64(1), front2.expirationTimestamp); | ||
assertEq(uint192(1), front2.layer2Tip); | ||
|
||
assertEq(NUMBER_OPERATIONS - 2, priorityQueue.getSize()); | ||
assertEq(2, priorityQueue.getFirstUnprocessedPriorityTx()); | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getTotalPriorityTxs()); | ||
assertFalse(priorityQueue.isEmpty()); | ||
} | ||
|
||
function test_pop_until_limit() public { | ||
for (uint i = 0; i < NUMBER_OPERATIONS; ++i) { | ||
PriorityOperation memory front = priorityQueue.popFront(); | ||
assertEq(keccak256(abi.encode(i)), front.canonicalTxHash); | ||
} | ||
|
||
assertEq(0, priorityQueue.getSize()); | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getFirstUnprocessedPriorityTx()); | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getTotalPriorityTxs()); | ||
assertTrue(priorityQueue.isEmpty()); | ||
|
||
// And now let's push something. | ||
|
||
PriorityOperation memory dummyOp = PriorityOperation({ | ||
canonicalTxHash: keccak256(abi.encode(300)), | ||
expirationTimestamp: uint64(300), | ||
layer2Tip: uint192(300) | ||
}); | ||
priorityQueue.pushBack(dummyOp); | ||
|
||
assertEq(1, priorityQueue.getSize()); | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getFirstUnprocessedPriorityTx()); | ||
assertEq(NUMBER_OPERATIONS + 1, priorityQueue.getTotalPriorityTxs()); | ||
assertFalse(priorityQueue.isEmpty()); | ||
|
||
PriorityOperation memory front_end = priorityQueue.popFront(); | ||
assertEq(keccak256(abi.encode(300)), front_end.canonicalTxHash); | ||
assertTrue(priorityQueue.isEmpty()); | ||
|
||
// And now let's go over the limit and fail. | ||
vm.expectRevert(bytes.concat("s")); | ||
priorityQueue.popFront(); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
l1-contracts/test/foundry/unit/concrete/PriorityQueue/PushOperations.sol
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,25 @@ | ||
pragma solidity 0.8.20; | ||
|
||
import {PriorityQueueSharedTest} from "./_PriorityQueue_Shared.t.sol"; | ||
import {PriorityOperation} from "../../../../../cache/solpp-generated-contracts/dev-contracts/test/PriorityQueueTest.sol"; | ||
|
||
contract PushOperationsTest is PriorityQueueSharedTest { | ||
uint public constant NUMBER_OPERATIONS = 10; | ||
|
||
function setUp() public { | ||
push_mock_entries(NUMBER_OPERATIONS); | ||
} | ||
|
||
function test_front() public { | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getSize()); | ||
PriorityOperation memory front = priorityQueue.front(); | ||
assertEq(keccak256(abi.encode(0)), front.canonicalTxHash); | ||
assertEq(uint64(0), front.expirationTimestamp); | ||
assertEq(uint192(0), front.layer2Tip); | ||
// This is 'front' and not popFront, so the amount should not change. | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getSize()); | ||
assertEq(0, priorityQueue.getFirstUnprocessedPriorityTx()); | ||
assertEq(NUMBER_OPERATIONS, priorityQueue.getTotalPriorityTxs()); | ||
assertFalse(priorityQueue.isEmpty()); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
l1-contracts/test/foundry/unit/concrete/PriorityQueue/_PriorityQueue_Shared.t.sol
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,25 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.20; | ||
|
||
import {Test} from "forge-std/Test.sol"; | ||
import {PriorityQueueTest, PriorityOperation} from "solpp/dev-contracts/test/PriorityQueueTest.sol"; | ||
|
||
contract PriorityQueueSharedTest is Test { | ||
PriorityQueueTest internal priorityQueue; | ||
|
||
constructor() { | ||
priorityQueue = new PriorityQueueTest(); | ||
} | ||
|
||
// Pushes 'count' entries into the priority queue. | ||
function push_mock_entries(uint count) public { | ||
for (uint i = 0; i < count; ++i) { | ||
PriorityOperation memory dummyOp = PriorityOperation({ | ||
canonicalTxHash: keccak256(abi.encode(i)), | ||
expirationTimestamp: uint64(i), | ||
layer2Tip: uint192(i) | ||
}); | ||
priorityQueue.pushBack(dummyOp); | ||
} | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
l1-contracts/test/foundry/unit/concrete/TransactionValidator/ValidateL1L2Tx.t.sol
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,64 @@ | ||
pragma solidity 0.8.20; | ||
|
||
import {TransactionValidatorSharedTest} from "./_TransactionValidator_Shared.t.sol"; | ||
import {IMailbox} from "solpp/zksync/interfaces/IMailbox.sol"; | ||
import {TransactionValidator} from "solpp/zksync/libraries/TransactionValidator.sol"; | ||
|
||
contract ValidateL1L2TxTest is TransactionValidatorSharedTest { | ||
function test_BasicRequestL1L2() public pure { | ||
IMailbox.L2CanonicalTransaction memory testTx = createTestTransaction(); | ||
testTx.gasLimit = 500000; | ||
validateL1ToL2Transaction(testTx, 500000); | ||
} | ||
|
||
function test_RevertWhen_GasLimitDoesntCoverOverhead() public { | ||
IMailbox.L2CanonicalTransaction memory testTx = createTestTransaction(); | ||
// The limit is so low, that it doesn't even cover the overhead | ||
testTx.gasLimit = 0; | ||
vm.expectRevert(bytes("my")); | ||
validateL1ToL2Transaction(testTx, 500000); | ||
} | ||
|
||
function test_RevertWhen_GasLimitHigherThanMax() public { | ||
IMailbox.L2CanonicalTransaction memory testTx = createTestTransaction(); | ||
// We should fail, if user asks for too much gas. | ||
// Notice, that we subtract the transaction overhead costs from the user's gas limit | ||
// before checking that it is below the max gas limit. | ||
uint256 priorityTxMaxGasLimit = 500000; | ||
testTx.gasLimit = priorityTxMaxGasLimit + 1000000; | ||
vm.expectRevert(bytes("ui")); | ||
validateL1ToL2Transaction(testTx, priorityTxMaxGasLimit); | ||
} | ||
|
||
function test_RevertWhen_TooMuchPubdata() public { | ||
IMailbox.L2CanonicalTransaction memory testTx = createTestTransaction(); | ||
// We should fail, if user's transaction could output too much pubdata. | ||
// We can allow only 99k of pubdata (otherwise we'd exceed the ethereum calldata limits). | ||
|
||
uint256 priorityTxMaxGasLimit = 500000; | ||
testTx.gasLimit = priorityTxMaxGasLimit; | ||
// So if the pubdata costs per byte is 1 - then this transaction could produce 500k of pubdata. | ||
// (hypothetically, assuming all the gas was spent on writing). | ||
testTx.gasPerPubdataByteLimit = 1; | ||
vm.expectRevert(bytes("uk")); | ||
validateL1ToL2Transaction(testTx, priorityTxMaxGasLimit); | ||
} | ||
|
||
function test_RevertWhen_BelowMinimumCost() public { | ||
IMailbox.L2CanonicalTransaction memory testTx = createTestTransaction(); | ||
uint256 priorityTxMaxGasLimit = 500000; | ||
testTx.gasLimit = 200000; | ||
vm.expectRevert(bytes("up")); | ||
validateL1ToL2Transaction(testTx, priorityTxMaxGasLimit); | ||
} | ||
|
||
function test_RevertWhen_HugePubdata() public { | ||
IMailbox.L2CanonicalTransaction memory testTx = createTestTransaction(); | ||
uint256 priorityTxMaxGasLimit = 500000; | ||
testTx.gasLimit = 400000; | ||
// Setting huge pubdata limit should cause the panic. | ||
testTx.gasPerPubdataByteLimit = type(uint256).max; | ||
vm.expectRevert(); | ||
validateL1ToL2Transaction(testTx, priorityTxMaxGasLimit); | ||
} | ||
} |
Oops, something went wrong.