Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "crates/miden-agglayer/solidity-compat/lib/forge-std"]
path = crates/miden-agglayer/solidity-compat/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "crates/miden-agglayer/solidity-compat/lib/agglayer-contracts"]
path = crates/miden-agglayer/solidity-compat/lib/agglayer-contracts
url = https://github.com/agglayer/agglayer-contracts
2 changes: 2 additions & 0 deletions .taplo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
exclude = ["crates/miden-agglayer/solidity-compat/lib/*"]

[formatting]
align_entries = true
column_width = 120
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- [BREAKING] Introduce `NoteAttachment` as part of `NoteMetadata` and remove `aux` and `execution_hint` ([#2249](https://github.com/0xMiden/miden-base/pull/2249), [#2252](https://github.com/0xMiden/miden-base/pull/2252), [#2260](https://github.com/0xMiden/miden-base/pull/2260)).
- [BREAKING] Introduce `NoteAttachment` as part of `NoteMetadata` and remove `aux` and `execution_hint` ([#2249](https://github.com/0xMiden/miden-base/pull/2249), [#2252](https://github.com/0xMiden/miden-base/pull/2252), [#2260](https://github.com/0xMiden/miden-base/pull/2260), [#2268](https://github.com/0xMiden/miden-base/pull/2268), [#2279](https://github.com/0xMiden/miden-base/pull/2279)).
- Introduce standard `NetworkAccountTarget` attachment for use in network transactions which replaces `NoteTag::NetworkAccount` ([#2257](https://github.com/0xMiden/miden-base/pull/2257)).
- Add a foundry test suite for verifying AggLayer contracts compatibility ([#2312](https://github.com/0xMiden/miden-base/pull/2312)).

### Changes

Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ build-no-std: ## Build without the standard library
build-no-std-testing: ## Build without the standard library. Includes the `testing` feature
$(BUILD_GENERATED_FILES_IN_SRC) cargo build --no-default-features --target wasm32-unknown-unknown --workspace --exclude bench-transaction --features testing

# --- test vectors --------------------------------------------------------------------------------

.PHONY: generate-solidity-test-vectors
generate-solidity-test-vectors: ## Regenerate Solidity MMR test vectors using Foundry
cd crates/miden-agglayer/solidity-compat && forge test -vv --match-test test_generateVectors
cd crates/miden-agglayer/solidity-compat && forge test -vv --match-test test_generateCanonicalZeros

# --- benchmarking --------------------------------------------------------------------------------

.PHONY: bench-tx
Expand Down
3 changes: 3 additions & 0 deletions _typos.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[default]
extend-ignore-identifiers-re = [".*1st.*", ".*2nd.*", ".*3rd.*"]

[files]
extend-exclude = ["crates/miden-agglayer/solidity-compat/lib"]
9 changes: 9 additions & 0 deletions crates/miden-agglayer/solidity-compat/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Foundry artifacts
/out/
/cache/

# Foundry broadcast files
/broadcast/

# Environment
.env
50 changes: 50 additions & 0 deletions crates/miden-agglayer/solidity-compat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Solidity Compatibility Tests

This directory contains Foundry tests for generating test vectors to verify
that the Miden MMR Frontier implementation is compatible with the Solidity
`DepositContractBase.sol` from [agglayer-contracts v2](https://github.com/agglayer/agglayer-contracts).

## Prerequisites

Install [Foundry](https://book.getfoundry.sh/getting-started/installation):

```bash
curl -L https://foundry.paradigm.xyz | bash
foundryup
```

## Generating Test Vectors

From the repository root, you can regenerate both canonical zeros and MMR frontier test vectors with:

```bash
make generate-solidity-test-vectors
```

Or from this directory:

```bash
# Install dependencies (first time only)
forge install

# Generate canonical zeros (test-vectors/canonical_zeros.json)
forge test -vv --match-test test_generateCanonicalZeros

# Generate MMR frontier vectors (test-vectors/mmr_frontier_vectors.json)
forge test -vv --match-test test_generateVectors
```

## Generated Files

- `test-vectors/canonical_zeros.json` - Canonical zeros for each tree height (ZERO_n = keccak256(ZERO_{n-1} || ZERO_{n-1}))
- `test-vectors/mmr_frontier_vectors.json` - Leaf-root pairs after adding leaves 0..31

### Canonical Zeros

The canonical zeros should match the constants in:
`crates/miden-agglayer/asm/bridge/canonical_zeros.masm`

### MMR Frontier Vectors

The `test_generateVectors` adds leaves `0, 1, 2, ...` (as left-padded 32-byte values)
and outputs the root after each addition.
11 changes: 11 additions & 0 deletions crates/miden-agglayer/solidity-compat/foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"lib/agglayer-contracts": {
"rev": "e468f9b0967334403069aa650d9f1164b1731ebb"
},
"lib/forge-std": {
"tag": {
"name": "v1.14.0",
"rev": "1801b0541f4fda118a10798fd3486bb7051c5dd6"
}
}
}
14 changes: 14 additions & 0 deletions crates/miden-agglayer/solidity-compat/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[profile.default]
libs = ["lib"]
out = "out"
solc = "0.8.20"
src = "src"

remappings = ["@agglayer/=lib/agglayer-contracts/contracts/"]

# Emit extra output for test vector generation
ffi = false
verbosity = 2

# Allow writing test vectors to file
fs_permissions = [{ access = "read-write", path = "test-vectors" }]
Submodule agglayer-contracts added at e468f9
1 change: 1 addition & 0 deletions crates/miden-agglayer/solidity-compat/lib/forge-std
Submodule forge-std added at f61e4d
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"canonical_zeros": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5",
"0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30",
"0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85",
"0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344",
"0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d",
"0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968",
"0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83",
"0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af",
"0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0",
"0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5",
"0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892",
"0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c",
"0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb",
"0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc",
"0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2",
"0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f",
"0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a",
"0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0",
"0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0",
"0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2",
"0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9",
"0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377",
"0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652",
"0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef",
"0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d",
"0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0",
"0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e",
"0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e",
"0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322",
"0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735",
"0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"vectors": [
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000000", "root": "0x27ae5ba08d7291c96c8cbddcc148bf48a6d68c7974b94356f53754ef6171d757", "count": 1},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000001", "root": "0x4a90a2c108a29b7755a0a915b9bb950233ce71f8a01859350d7b73cc56f57a62", "count": 2},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000002", "root": "0x2757cc260a62cc7c7708c387ea99f2a6bb5f034ed00da845734bec4d3fa3abfe", "count": 3},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000003", "root": "0xcb305ccda4331eb3fd9e17b81a5a0b336fb37a33f927698e9fb0604e534c6a01", "count": 4},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000004", "root": "0xa377a6262d3bae7be0ce09c2cc9f767b0f31848c268a4bdc12b63a451bb97281", "count": 5},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000005", "root": "0x440213f4dff167e3f5c655fbb6a3327af3512affed50ce3c1a3f139458a8a6d1", "count": 6},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000006", "root": "0xdd716d2905f2881005341ff1046ced5ee15cc63139716f56ed6be1d075c3f4a7", "count": 7},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000007", "root": "0xd6ebf96fcc3344fa755057b148162f95a93491bc6e8be756d06ec64df4df90fc", "count": 8},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000008", "root": "0x8b3bf2c95f3d0f941c109adfc3b652fadfeaf6f34be52524360a001cb151b5c9", "count": 9},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000009", "root": "0x74a5712654eccd015c44aca31817fd8bee8da400ada986a78384ef3594f2d459", "count": 10},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000000a", "root": "0x95dd1209b92cce04311dfc8670b03428408c4ff62beb389e71847971f73702fa", "count": 11},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000000b", "root": "0x0a83f3b2a75e19b7255b1de379ea9a71aef9716a3aef20a86abe625f088bbebf", "count": 12},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000000c", "root": "0x601ba73b45858be76c8d02799fd70a5e1713e04031aa3be6746f95a17c343173", "count": 13},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000000d", "root": "0x93d741c47aa73e36d3c7697758843d6af02b10ed38785f367d1602c8638adb0d", "count": 14},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000000e", "root": "0x578f0d0a9b8ed5a4f86181b7e479da7ad72576ba7d3f36a1b72516aa0900c8ac", "count": 15},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000000f", "root": "0x995c30e6b58c6e00e06faf4b5c94a21eb820b9db7ad30703f8e3370c2af10c11", "count": 16},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000010", "root": "0x49fb7257be1e954c377dc2557f5ca3f6fc7002d213f2772ab6899000e465236c", "count": 17},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000011", "root": "0x06fee72550896c50e28b894c60a3132bfe670e5c7a77ab4bb6a8ffb4abcf9446", "count": 18},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000012", "root": "0xbba3a807e79d33c6506cd5ecb5d50417360f8be58139f6dbe2f02c92e4d82491", "count": 19},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000013", "root": "0x1243fbd4d21287dbdaa542fa18a6a172b60d1af2c517b242914bdf8d82a98293", "count": 20},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000014", "root": "0x02b7b57e407fbccb506ed3199922d6d9bd0f703a1919d388c76867399ed44286", "count": 21},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000015", "root": "0xa15e7890d8f860a2ef391f9f58602dec7027c19e8f380980f140bbb92a3e00ba", "count": 22},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000016", "root": "0x2cb7eff4deb9bf6bbb906792bc152f1e63759b30e7829bfb5f3257ee600303f5", "count": 23},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000017", "root": "0xb1b034b4784411dc6858a0da771acef31be60216be0520a7950d29f66aee1fc5", "count": 24},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000018", "root": "0x3b17098f521ca0719e144a12bb79fdc51a3bc70385b5c2ee46b5762aae741f4f", "count": 25},
{"leaf": "0x0000000000000000000000000000000000000000000000000000000000000019", "root": "0xd3e054489aa750d41938143011666a83e5e6b1477cce5ad612447059c2d8b939", "count": 26},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000001a", "root": "0x6d15443ab2f39cce7fbe131843cdad6f27400eb179efb866569dd48baaf3ed4d", "count": 27},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000001b", "root": "0xf9386ef40320c369185e48132f8fbf2f3e78d9598495dd342bcf4f41388d460d", "count": 28},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000001c", "root": "0xb618ebe1f7675ef246a8cbb93519469076d5caacd4656330801537933e27b172", "count": 29},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000001d", "root": "0x6c8c90b5aa967c98061a2dd09ea74dfb61fd9e86e308f14453e9e0ae991116de", "count": 30},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000001e", "root": "0x06f51cfc733d71220d6e5b70a6b33a8d47a1ab55ac045fac75f26c762d7b29c9", "count": 31},
{"leaf": "0x000000000000000000000000000000000000000000000000000000000000001f", "root": "0x82d1ddf8c6d986dee7fc6fa2d7120592d1dc5026b1bb349fcc9d5c73ac026f56", "count": 32}
]
}
87 changes: 87 additions & 0 deletions crates/miden-agglayer/solidity-compat/test/MMRTestVectors.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
Copy link
Contributor

@partylikeits1983 partylikeits1983 Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: if we don't need the console.log() we can remove the Test.sol import (i think, need to double check)

import "@agglayer/v2/lib/DepositContractBase.sol";

/**
* @title MMRTestVectors
* @notice Test contract that generates test vectors for verifying compatibility
* between Solidity's DepositContractBase and Miden's MMR Frontier implementation.
*
* Run with: forge test -vv --match-contract MMRTestVectors
*
* The output can be compared against the Rust KeccakMmrFrontier32 implementation
* in crates/miden-testing/tests/agglayer/mmr_frontier.rs
*/
contract MMRTestVectors is Test, DepositContractBase {

/**
* @notice Generates the canonical zeros and saves to JSON file.
* ZERO_0 = 0x0...0 (32 zero bytes)
* ZERO_n = keccak256(ZERO_{n-1} || ZERO_{n-1})
*
* Output file: test-vectors/canonical_zeros.json
*/
function test_generateCanonicalZeros() public {
string memory json = "{\n";
json = string.concat(json, ' "canonical_zeros": [\n');

bytes32 zero = bytes32(0);
for (uint256 height = 0; height < 32; height++) {
if (height < 31) {
json = string.concat(json, ' "', vm.toString(zero), '",\n');
} else {
json = string.concat(json, ' "', vm.toString(zero), '"\n');
}
zero = keccak256(abi.encodePacked(zero, zero));
}
json = string.concat(json, " ]\n}");
Comment on lines +31 to +39
Copy link
Contributor

@partylikeits1983 partylikeits1983 Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

writing a JSON in Solidity, nice :)

I've done this before, but I this is not ideal, we can use a foundry "cheatcode" instead. I opened a PR on this branch to show a simpler way to do this, so we don't have to do string manipulation in solidity.

Opened a PR here: #2314


// Print to console
console.log(json);
Comment on lines +41 to +42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this console.log()?


// Save to file
string memory outputPath = "test-vectors/canonical_zeros.json";
vm.writeFile(outputPath, json);
console.log("\nSaved to:", outputPath);
}

/**
* @notice Generates MMR frontier vectors (leaf-root pairs) and saves to JSON file.
* Output file: test-vectors/mmr_frontier_vectors.json
*/
function test_generateVectors() public {
string memory json = "{\n";
json = string.concat(json, ' "vectors": [\n');

for (uint256 i = 0; i < 32; i++) {
bytes32 leaf = bytes32(i);
_addLeaf(leaf);
bytes32 root = getRoot();

// Build JSON object for this vector
string memory vectorJson = string.concat(
' {"leaf": "', vm.toString(leaf),
'", "root": "', vm.toString(root),
'", "count": ', vm.toString(depositCount), "}"
);

if (i < 31) {
json = string.concat(json, vectorJson, ",\n");
} else {
json = string.concat(json, vectorJson, "\n");
}
}

json = string.concat(json, " ]\n}");

// Print to console
console.log(json);
Comment on lines +79 to +80
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment


// Save to file
string memory outputPath = "test-vectors/mmr_frontier_vectors.json";
vm.writeFile(outputPath, json);
console.log("\nSaved to:", outputPath);
}
}
2 changes: 2 additions & 0 deletions crates/miden-testing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,7 @@ miden-crypto = { workspace = true }
miden-protocol = { features = ["std"], workspace = true }
primitive-types = { workspace = true }
rstest = { workspace = true }
serde = { features = ["derive"], version = "1.0" }
Copy link
Contributor Author

@mmagician mmagician Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: to be changed once #2313 lands

serde_json = { version = "1.0" }
tokio = { features = ["macros", "rt"], workspace = true }
winter-rand-utils = { version = "0.13" }
Loading