mirror of
https://github.com/luxfi/teleport.git
synced 2026-10-30 15:15:49 +00:00
Solidity library computing D = keccak256("LUX-WARP-ZAP-CORE-v1" || core), the
canonical Warp ZAP message digest, byte-for-byte identical to the Go reference
(luxfi/warp message.go marshalZAP + teleport/payload.go ComputeMessageHash).
core = 0x01||u32(networkId)||srcChain32||0x0(32)||u64(0)||u64(0)||u32(11)
"Pulsar-SHA3"||u32(90)||payload; payload(90)=u8(3)||u64(dest)||token(20)||
u256(amount)||recip(20)||u8(vaultIsZero)||u64(nonce). Proven against all 5
luxfi/warp sol_compatible fixtures via forge (test/forge/WarpZapDigest.t.sol,
foundry.toml scoped to the lib so it coexists with the Hardhat/OZ suite).
This is the on-chain half of the warp RLP->ZAP lockstep; BridgeV2.burn/claim
wire to it next (+ Envelope source-lineage fields).
54 lines
2.3 KiB
Solidity
54 lines
2.3 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import {WarpZapDigest} from "../../contracts/lib/WarpZapDigest.sol";
|
|
|
|
/// Byte-equality oracle: every D below is the Go reference output from
|
|
/// github.com/luxfi/warp/teleport/fixtures (the "sol_compatible_*" vectors).
|
|
/// If Solidity computeD matches all of them, the on-chain digest is byte-
|
|
/// identical to what the validator set signs.
|
|
contract WarpZapDigestTest {
|
|
/// 20-byte address with every byte == b (the fixtures use all-same-byte
|
|
/// addresses; building them avoids EIP-55 address-literal ambiguity).
|
|
function rep(uint8 b) internal pure returns (address) {
|
|
uint160 x = 0;
|
|
for (uint256 i = 0; i < 20; i++) { x = (x << 8) | uint160(b); }
|
|
return address(x);
|
|
}
|
|
|
|
function test_small_burn() public pure {
|
|
bytes32 d = WarpZapDigest.computeD(
|
|
96369, bytes32(uint256(0x17871)), 1,
|
|
rep(0x11), 1000000000000000000, rep(0x22), true, 0);
|
|
require(d == 0x6fc798dfa7a7ac7012a02aca8d689aa582987131092301df58827fa5231b5ab9, "small_burn");
|
|
}
|
|
|
|
function test_large_vault() public pure {
|
|
bytes32 d = WarpZapDigest.computeD(
|
|
96369, bytes32(uint256(0x17871)), 42,
|
|
rep(0xaa), 123456789000000000000000000, rep(0xbb), false, 1);
|
|
require(d == 0x211990725d2020531f401e6480d292bab3054637863f61f4faa21f143cbc42f8, "large_vault");
|
|
}
|
|
|
|
function test_uint256_max() public pure {
|
|
bytes32 d = WarpZapDigest.computeD(
|
|
1, bytes32(uint256(1)), 96369,
|
|
rep(0xcc), type(uint256).max, rep(0xdd), false, type(uint64).max);
|
|
require(d == 0x653ec7199df29d151b6a8ac3681e9160b77987b4d5a06aa13a6afd286d858651, "uint256_max");
|
|
}
|
|
|
|
function test_one_wei() public pure {
|
|
bytes32 d = WarpZapDigest.computeD(
|
|
3, bytes32(uint256(3)), 7,
|
|
rep(0xee), 1, rep(0xff), true, 99);
|
|
require(d == 0xd385a6faf34a8ff1f7dd6edbb6b3aab14cf5237b07121916e99e2c7740245e8a, "one_wei");
|
|
}
|
|
|
|
function test_repeated_ab() public pure {
|
|
bytes32 d = WarpZapDigest.computeD(
|
|
96369, 0xabababababababababababababababababababababababababababababababab, 1,
|
|
rep(0x11), 1000000000000000000, rep(0x22), true, 0);
|
|
require(d == 0x72063ff81c4da92d7c4aacb4131452230bc0d8cfba2953af76d533c8abd34d84, "repeated_ab");
|
|
}
|
|
}
|