diff --git a/contracts/MerkleTreeWithHistory.sol b/contracts/MerkleTreeWithHistory.sol new file mode 100644 index 0000000..47e0d25 --- /dev/null +++ b/contracts/MerkleTreeWithHistory.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.21; + +import { Poseidon } from "./Poseidon.sol"; + +/// @author modified from tornado (https://github.com/tornadocash/tornado-core/blob/master/contracts/MerkleTreeWithHistory.sol) +abstract contract MerkleTreeWithHistory { + uint256 public constant FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + uint256 public constant ZERO_VALUE = 14789368534087791069534203144842955855369356487450677079547439497078245981966; // = keccak256("receba") % FIELD_SIZE + uint32 public constant ROOT_HISTORY_SIZE = 30; + uint256 public immutable LEVELS; + + mapping(uint256 index => bytes32 hash) public filledSubtrees; + mapping(uint256 index => bytes32 root) public roots; + uint32 public currentRootIndex = 0; + uint32 public nextIndex = 0; + + constructor(uint8 levels) { + if (levels > 32) revert InvalidLevel(); + LEVELS = levels; + for (uint32 i = 0; i < levels; ++i) { + filledSubtrees[i] = zeros(i); + } + roots[0] = zeros(levels - 1); + } + + function insert(bytes32 leaf) internal returns (uint32 index) { + if (uint256(leaf) >= FIELD_SIZE) revert FieldOverflow(); + + uint32 nextIndex_ = nextIndex; + if (nextIndex_ == 2 ** LEVELS) revert FullTree(); + uint32 currentIndex = nextIndex_; + bytes32 currentLevelHash = leaf; + bytes32 left; + bytes32 right; + + for (uint32 i = 0; i < LEVELS; ++i) { + if (currentIndex % 2 == 0) { + left = currentLevelHash; + right = zeros(i); + filledSubtrees[i] = currentLevelHash; + } else { + left = filledSubtrees[i]; + right = currentLevelHash; + } + currentLevelHash = Poseidon.hash(left, right); + currentIndex >>= 1; + } + + uint32 newRootIndex = (currentRootIndex + 1) % ROOT_HISTORY_SIZE; + currentRootIndex = newRootIndex; + nextIndex = nextIndex_ + 1; + roots[newRootIndex] = currentLevelHash; + return nextIndex_; + } + + function isKnownRoot(bytes32 root) public view returns (bool) { + if (root == 0) return false; + uint32 currentRootIndex_ = currentRootIndex; + uint32 i = currentRootIndex_; + do { + if (root == roots[i]) return true; + if (i == 0) i = ROOT_HISTORY_SIZE; + --i; + } while (i != currentRootIndex_); + return false; + } + + function lastRoot() public view returns (bytes32) { + return roots[currentRootIndex]; + } + + function zeros(uint256 i) public pure returns (bytes32) { + if (i == 0) return 0x20b27c6750705c1d7d3d64d3ba12a5bbd8fd2da2c638186f8268efc44fb87f0e; + else if (i == 1) return 0x1ff9bcd7757de41fd8ccfe79a1423535b3132a80b5193026aefd443a14667ea8; + else if (i == 2) return 0x06477e81d01a57ad482a3aecfbedd3a84fc713f7a3b500102618b51d3e446b69; + else if (i == 3) return 0x2bc3f870f707405f8dcf1a60037680737470570f039258caf6492b5cb1f14042; + else if (i == 4) return 0x2a3d4a1d56795d0a8749ae2168af84347df6cdc6b68b9e0ba59ef33de8373b10; + else if (i == 5) return 0x2d09102b12ab9bb2e4bfb16a12766137f6d92e2366e052fd29fb89394571662c; + else if (i == 6) return 0x2271b8bcc95bfcc33d82ad6ffc88438a82ad4fa2f0b3831b84c556b059bc80fc; + else if (i == 7) return 0x1812a5f766e048c28e0b449d322547fde7b6f328554de85c6c417318a9c688f9; + else if (i == 8) return 0x26b7d439314c1101ccba00d997ebc316d9ea7f84e6a870f522fc3a7271f8f40f; + else if (i == 9) return 0x28670e46e3e68da6783e88ee744148125bae04d5ff1310c297e91e9feac099c7; + else if (i == 10) return 0x1456d91c08c49db11a3baa1b5ea2ea2ba9ab4087fcbdc9bfef5ee6c78897d371; + else if (i == 11) return 0x05050a34f017642c04435348c44fa8a594b28052d47102534b4fae278e1dd484; + else if (i == 12) return 0x1db004f66d9f4dbb2262dff5100127e2094b7967d4f4a727230cc72c4286329a; + else if (i == 13) return 0x0fdce35f1c9aeb4b2f08124c6a7bb378a6a0b06468f7a6e403e43f2cdad5f397; + else if (i == 14) return 0x2d930f785c54791032ed0a23bfc1f935e88c408dd4a1d35692bb00740f441d82; + else if (i == 15) return 0x1a9ca3445ff82d31e7f7771a105079e9df4f67cb23615ae0b7081caecbdc5eb3; + else if (i == 16) return 0x21f3885b2f56b8aa5c4babf2b83076308b4561a9af150adfb62e94fd56baaca0; + else if (i == 17) return 0x2d07775565fe64cd24a2063d0cdbb8a0314e9e30e11be2fd2edb1e9bac831f2e; + else if (i == 18) return 0x03559388471591276d58713cd692bb5a3d6939761e72899fe22a0e484a144159; + else if (i == 19) return 0x0d820dd92ebac62c9e9a45a9965f2d74952773d95f540ef423fdbf2db15f6f10; + else if (i == 20) return 0x013b486fdfe2458cd376ae0c6d93758d0d68497ebb8d2301f261e6ba541eaa2b; + else if (i == 21) return 0x15f77945b225c1140db94532bb98a6e56c33bfadf1d8de46909949410590bad1; + else if (i == 22) return 0x0f2b99784ca7f7a0b12026ada700937acc61cdcbd60015b7b98b19b419776fb0; + else if (i == 23) return 0x125bef9fd271c7e80592f4443d4b8bca4da0e6981030f5edd053cdbc13dd3314; + else if (i == 24) return 0x03a5f22e7657928a039bd6879aba619b46ea95b0bfc543b12a69c40f287ca50b; + else if (i == 25) return 0x249d1550c266802254391b29f2420d4fd6de26c2852878666030c3ea15f8405f; + else if (i == 26) return 0x02d974a7f28a27cb5c84800814eced585ba30e7ceef8cf55da5e3393053376ef; + else if (i == 27) return 0x2bcffe57a6de4431e031917a9fe49caa34c3f2ad60f4f61530854b0611a573e9; + else if (i == 28) return 0x2408804108b892cef0945f7091026ad757d26662192c2bb6262a4749e1acd105; + else if (i == 29) return 0x01b9687125c34c4b02adbbaea306112bebbd9c0e2f96adcdf50632a0905639e3; + else if (i == 30) return 0x1eacb24c41bbddadfe0feab68a196f4525c1b5512359825680ec527eed62b1a5; + else if (i == 31) return 0x246c192ae53614a9a4fcf4dc24f2e198fca7539ae3d779cd592360fc0ea9d479; + else revert InvalidLevel(); + } +} + +error FullTree(); +error InvalidLevel(); +error FieldOverflow(); diff --git a/contracts/Poseidon.sol b/contracts/Poseidon.sol new file mode 100644 index 0000000..67b0914 --- /dev/null +++ b/contracts/Poseidon.sol @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.21; + +/// @author modified from poseidon-solidity (https://github.com/vimwitch/poseidon-solidity/blob/main/contracts/PoseidonT3.sol) +library Poseidon { + uint256 private constant M00 = 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b; + uint256 private constant M01 = 0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771; + uint256 private constant M02 = 0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7; + uint256 private constant M10 = 0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0; + uint256 private constant M11 = 0x2e2419f9ec02ec394c9871c832963dc1b89d743c8c7b964029b2311687b1fe23; + uint256 private constant M12 = 0x176cc029695ad02582a70eff08a6fd99d057e12e58e7d7b6b16cdfabc8ee2911; + + function hash(bytes32 left, bytes32 right) internal pure returns (bytes32 out) { + // solhint-disable no-inline-assembly + // slither-disable-next-line assembly + assembly ("memory-safe") { + // solhint-enable no-inline-assembly + + let F := 21888242871839275222246405745257275088548364400416034343698204186575808495617 + let M20 := 0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736d + let M21 := 0x101071f0032379b697315876690f053d148d4e109f5fb065c8aacc55a0f89bfa + let M22 := 0x19a3fc0a56702bf417ba7fee3802593fa644470307043f7773279cd71d25d5e0 + + // forgefmt: disable-start + let state1 := add(mod(left, F), 0x00f1445235f2148c5986587169fc1bcd887b08d4d00868df5696fff40956e864) + let state2 := add(mod(right, F), 0x08dff3487e8ac99e1f29a058d0fa80b930c728730b7ab36ce879f3890ecf73f5) + let scratch0 := mulmod(state1, state1, F) + state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F) + scratch0 := mulmod(state2, state2, F) + state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F) + scratch0 := add( + 0x2f27be690fdaee46c3ce28f7532b13c856c35342c84bda6e20966310fadc01d0, + add(add(15452833169820924772166449970675545095234312153403844297388521437673434406763, mulmod(state1, M10, F)), mulmod(state2, M20, F)) + ) + let scratch1 := add( + 0x2b2ae1acf68b7b8d2416bebf3d4f6234b763fe04b8043ee48b8327bebca16cf2, + add(add(18674271267752038776579386132900109523609358935013267566297499497165104279117, mulmod(state1, M11, F)), mulmod(state2, M21, F)) + ) + let scratch2 := add( + 0x0319d062072bef7ecca5eac06f97d4d55952c175ab6b03eae64b44c7dbf11cfa, + add(add(14817777843080276494683266178512808687156649753153012854386334860566696099579, mulmod(state1, M12, F)), mulmod(state2, M22, F)) + ) + let state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := mulmod(scratch1, scratch1, F) + scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F) + state0 := mulmod(scratch2, scratch2, F) + scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F) + state0 := add(0x28813dcaebaeaa828a376df87af4a63bc8b7bf27ad49c6298ef7b387bf28526d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x2727673b2ccbc903f181bf38e1c1d40d2033865200c352bc150928adddf9cb78, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x234ec45ca27727c2e74abd2b2a1494cd6efbd43e340587d6b8fb9e31e65cc632, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := mulmod(state1, state1, F) + state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F) + scratch0 := mulmod(state2, state2, F) + state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F) + scratch0 := add(0x15b52534031ae18f7f862cb2cf7cf760ab10a8150a337b1ccd99ff6e8797d428, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x0dc8fad6d9e4b35f5ed9a3d186b79ce38e0e8a8d1b58b132d701d4eecf68d1f6, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x1bcd95ffc211fbca600f705fad3fb567ea4eb378f62e1fec97805518a47e4d9c, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := mulmod(scratch1, scratch1, F) + scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F) + state0 := mulmod(scratch2, scratch2, F) + scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F) + state0 := add(0x10520b0ab721cadfe9eff81b016fc34dc76da36c2578937817cb978d069de559, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x1f6d48149b8e7f7d9b257d8ed5fbbaf42932498075fed0ace88a9eb81f5627f6, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x1d9655f652309014d29e00ef35a2089bfff8dc1c816f0dc9ca34bdb5460c8705, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x04df5a56ff95bcafb051f7b1cd43a99ba731ff67e47032058fe3d4185697cc7d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x0672d995f8fff640151b3d290cedaf148690a10a8c8424a7f6ec282b6e4be828, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x099952b414884454b21200d7ffafdd5f0c9a9dcc06f2708e9fc1d8209b5c75b9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x052cba2255dfd00c7c483143ba8d469448e43586a9b4cd9183fd0e843a6b9fa6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x0b8badee690adb8eb0bd74712b7999af82de55707251ad7716077cb93c464ddc, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x119b1590f13307af5a1ee651020c07c749c15d60683a8050b963d0a8e4b2bdd1, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x03150b7cd6d5d17b2529d36be0f67b832c4acfc884ef4ee5ce15be0bfb4a8d09, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x2cc6182c5e14546e3cf1951f173912355374efb83d80898abe69cb317c9ea565, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x005032551e6378c450cfe129a404b3764218cadedac14e2b92d2cd73111bf0f9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x233237e3289baa34bb147e972ebcb9516469c399fcc069fb88f9da2cc28276b5, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x05c8f4f4ebd4a6e3c980d31674bfbe6323037f21b34ae5a4e80c2d4c24d60280, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x0a7b1db13042d396ba05d818a319f25252bcf35ef3aeed91ee1f09b2590fc65b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x2a73b71f9b210cf5b14296572c9d32dbf156e2b086ff47dc5df542365a404ec0, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x1ac9b0417abcc9a1935107e9ffc91dc3ec18f2c4dbe7f22976a760bb5c50c460, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x12c0339ae08374823fabb076707ef479269f3e4d6cb104349015ee046dc93fc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x0b7475b102a165ad7f5b18db4e1e704f52900aa3253baac68246682e56e9a28e, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x037c2849e191ca3edb1c5e49f6e8b8917c843e379366f2ea32ab3aa88d7f8448, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x05a6811f8556f014e92674661e217e9bd5206c5c93a07dc145fdb176a716346f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x29a795e7d98028946e947b75d54e9f044076e87a7b2883b47b675ef5f38bd66e, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x20439a0c84b322eb45a3857afc18f5826e8c7382c8a1585c507be199981fd22f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x2e0ba8d94d9ecf4a94ec2050c7371ff1bb50f27799a84b6d4a2a6f2a0982c887, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x143fd115ce08fb27ca38eb7cce822b4517822cd2109048d2e6d0ddcca17d71c8, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x0c64cbecb1c734b857968dbbdcf813cdf8611659323dbcbfc84323623be9caf1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x028a305847c683f646fca925c163ff5ae74f348d62c2b670f1426cef9403da53, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x2e4ef510ff0b6fda5fa940ab4c4380f26a6bcb64d89427b824d6755b5db9e30c, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x0081c95bc43384e663d79270c956ce3b8925b4f6d033b078b96384f50579400e, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x2ed5f0c91cbd9749187e2fade687e05ee2491b349c039a0bba8a9f4023a0bb38, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x30509991f88da3504bbf374ed5aae2f03448a22c76234c8c990f01f33a735206, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x1c3f20fd55409a53221b7c4d49a356b9f0a1119fb2067b41a7529094424ec6ad, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x10b4e7f3ab5df003049514459b6e18eec46bb2213e8e131e170887b47ddcb96c, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x2a1982979c3ff7f43ddd543d891c2abddd80f804c077d775039aa3502e43adef, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x1c74ee64f15e1db6feddbead56d6d55dba431ebc396c9af95cad0f1315bd5c91, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x07533ec850ba7f98eab9303cace01b4b9e4f2e8b82708cfa9c2fe45a0ae146a0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x21576b438e500449a151e4eeaf17b154285c68f42d42c1808a11abf3764c0750, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x2f17c0559b8fe79608ad5ca193d62f10bce8384c815f0906743d6930836d4a9e, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x2d477e3862d07708a79e8aae946170bc9775a4201318474ae665b0b1b7e2730e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x162f5243967064c390e095577984f291afba2266c38f5abcd89be0f5b2747eab, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x2b4cb233ede9ba48264ecd2c8ae50d1ad7a8596a87f29f8a7777a70092393311, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x2c8fbcb2dd8573dc1dbaf8f4622854776db2eece6d85c4cf4254e7c35e03b07a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x1d6f347725e4816af2ff453f0cd56b199e1b61e9f601e9ade5e88db870949da9, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x204b0c397f4ebe71ebc2d8b3df5b913df9e6ac02b68d31324cd49af5c4565529, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x0c4cb9dc3c4fd8174f1149b3c63c3c2f9ecb827cd7dc25534ff8fb75bc79c502, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x174ad61a1448c899a25416474f4930301e5c49475279e0639a616ddc45bc7b54, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x1a96177bcf4d8d89f759df4ec2f3cde2eaaa28c177cc0fa13a9816d49a38d2ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x066d04b24331d71cd0ef8054bc60c4ff05202c126a233c1a8242ace360b8a30a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x2a4c4fc6ec0b0cf52195782871c6dd3b381cc65f72e02ad527037a62aa1bd804, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x13ab2d136ccf37d447e9f2e14a7cedc95e727f8446f6d9d7e55afc01219fd649, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x1121552fca26061619d24d843dc82769c1b04fcec26f55194c2e3e869acc6a9a, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x00ef653322b13d6c889bc81715c37d77a6cd267d595c4a8909a5546c7c97cff1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x0e25483e45a665208b261d8ba74051e6400c776d652595d9845aca35d8a397d3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x29f536dcb9dd7682245264659e15d88e395ac3d4dde92d8c46448db979eeba89, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x2a56ef9f2c53febadfda33575dbdbd885a124e2780bbea170e456baace0fa5be, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x1c8361c78eb5cf5decfb7a2d17b5c409f2ae2999a46762e8ee416240a8cb9af1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x151aff5f38b20a0fc0473089aaf0206b83e8e68a764507bfd3d0ab4be74319c5, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x04c6187e41ed881dc1b239c88f7f9d43a9f52fc8c8b6cdd1e76e47615b51f100, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x13b37bd80f4d27fb10d84331f6fb6d534b81c61ed15776449e801b7ddc9c2967, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x01a5c536273c2d9df578bfbd32c17b7a2ce3664c2a52032c9321ceb1c4e8a8e4, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x2ab3561834ca73835ad05f5d7acb950b4a9a2c666b9726da832239065b7c3b02, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x1d4d8ec291e720db200fe6d686c0d613acaf6af4e95d3bf69f7ed516a597b646, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x041294d2cc484d228f5784fe7919fd2bb925351240a04b711514c9c80b65af1d, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x154ac98e01708c611c4fa715991f004898f57939d126e392042971dd90e81fc6, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x0b339d8acca7d4f83eedd84093aef51050b3684c88f8b0b04524563bc6ea4da4, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x0955e49e6610c94254a4f84cfbab344598f0e71eaff4a7dd81ed95b50839c82e, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x06746a6156eba54426b9e22206f15abca9a6f41e6f535c6f3525401ea0654626, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x0f18f5a0ecd1423c496f3820c549c27838e5790e2bd0a196ac917c7ff32077fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x04f6eeca1751f7308ac59eff5beb261e4bb563583ede7bc92a738223d6f76e13, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x2b56973364c4c4f5c1a3ec4da3cdce038811eb116fb3e45bc1768d26fc0b3758, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x123769dd49d5b054dcd76b89804b1bcb8e1392b385716a5d83feb65d437f29ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x2147b424fc48c80a88ee52b91169aacea989f6446471150994257b2fb01c63e9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x0fdc1f58548b85701a6c5505ea332a29647e6f34ad4243c2ea54ad897cebe54d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x12373a8251fea004df68abcf0f7786d4bceff28c5dbbe0c3944f685cc0a0b1f2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x21e4f4ea5f35f85bad7ea52ff742c9e8a642756b6af44203dd8a1f35c1a90035, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x16243916d69d2ca3dfb4722224d4c462b57366492f45e90d8a81934f1bc3b147, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x1efbe46dd7a578b4f66f9adbc88b4378abc21566e1a0453ca13a4159cac04ac2, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x07ea5e8537cf5dd08886020e23a7f387d468d5525be66f853b672cc96a88969a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x05a8c4f9968b8aa3b7b478a30f9a5b63650f19a75e7ce11ca9fe16c0b76c00bc, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x20f057712cc21654fbfe59bd345e8dac3f7818c701b9c7882d9d57b72a32e83f, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x04a12ededa9dfd689672f8c67fee31636dcd8e88d01d49019bd90b33eb33db69, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x27e88d8c15f37dcee44f1e5425a51decbd136ce5091a6767e49ec9544ccd101a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x2feed17b84285ed9b8a5c8c5e95a41f66e096619a7703223176c41ee433de4d1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x1ed7cc76edf45c7c404241420f729cf394e5942911312a0d6972b8bd53aff2b8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x15742e99b9bfa323157ff8c586f5660eac6783476144cdcadf2874be45466b1a, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x1aac285387f65e82c895fc6887ddf40577107454c6ec0317284f033f27d0c785, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x25851c3c845d4790f9ddadbdb6057357832e2e7a49775f71ec75a96554d67c77, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x15a5821565cc2ec2ce78457db197edf353b7ebba2c5523370ddccc3d9f146a67, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x2411d57a4813b9980efa7e31a1db5966dcf64f36044277502f15485f28c71727, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x002e6f8d6520cd4713e335b8c0b6d2e647e9a98e12f4cd2558828b5ef6cb4c9b, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x2ff7bc8f4380cde997da00b616b0fcd1af8f0e91e2fe1ed7398834609e0315d2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x00b9831b948525595ee02724471bcd182e9521f6b7bb68f1e93be4febb0d3cbe, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x0a2f53768b8ebf6a86913b0e57c04e011ca408648a4743a87d77adbf0c9c3512, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x00248156142fd0373a479f91ff239e960f599ff7e94be69b7f2a290305e1198d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x171d5620b87bfb1328cf8c02ab3f0c9a397196aa6a542c2350eb512a2b2bcda9, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x170a4f55536f7dc970087c7c10d6fad760c952172dd54dd99d1045e4ec34a808, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x29aba33f799fe66c2ef3134aea04336ecc37e38c1cd211ba482eca17e2dbfae1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x1e9bc179a4fdd758fdd1bb1945088d47e70d114a03f6a0e8b5ba650369e64973, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x1dd269799b660fad58f7f4892dfb0b5afeaad869a9c4b44f9c9e1c43bdaf8f09, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x22cdbc8b70117ad1401181d02e15459e7ccd426fe869c7c95d1dd2cb0f24af38, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x0ef042e454771c533a9f57a55c503fcefd3150f52ed94a7cd5ba93b9c7dacefd, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x11609e06ad6c8fe2f287f3036037e8851318e8b08a0359a03b304ffca62e8284, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x1166d9e554616dba9e753eea427c17b7fecd58c076dfe42708b08f5b783aa9af, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x2de52989431a859593413026354413db177fbf4cd2ac0b56f855a888357ee466, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x3006eb4ffc7a85819a6da492f3a8ac1df51aee5b17b8e89d74bf01cf5f71e9ad, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x2af41fbb61ba8a80fdcf6fff9e3f6f422993fe8f0a4639f962344c8225145086, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x119e684de476155fe5a6b41a8ebc85db8718ab27889e85e781b214bace4827c3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x1835b786e2e8925e188bea59ae363537b51248c23828f047cff784b97b3fd800, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x28201a34c594dfa34d794996c6433a20d152bac2a7905c926c40e285ab32eeb6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x083efd7a27d1751094e80fefaf78b000864c82eb571187724a761f88c22cc4e7, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x0b6f88a3577199526158e61ceea27be811c16df7774dd8519e079564f61fd13b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x0ec868e6d15e51d9644f66e1d6471a94589511ca00d29e1014390e6ee4254f5b, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x2af33e3f866771271ac0c9b3ed2e1142ecd3e74b939cd40d00d937ab84c98591, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x0b520211f904b5e7d09b5d961c6ace7734568c547dd6858b364ce5e47951f178, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x0b2d722d0919a1aad8db58f10062a92ea0c56ac4270e822cca228620188a1d40, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x1f790d4d7f8cf094d980ceb37c2453e957b54a9991ca38bbe0061d1ed6e562d4, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x0171eb95dfbf7d1eaea97cd385f780150885c16235a2a6a8da92ceb01e504233, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x0c2d0e3b5fd57549329bf6885da66b9b790b40defd2c8650762305381b168873, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x1162fb28689c27154e5a8228b4e72b377cbcafa589e283c35d3803054407a18d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x2f1459b65dee441b64ad386a91e8310f282c5a92a89e19921623ef8249711bc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x1e6ff3216b688c3d996d74367d5cd4c1bc489d46754eb712c243f70d1b53cfbb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x01ca8be73832b8d0681487d27d157802d741a6f36cdc2a0576881f9326478875, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x1f7735706ffe9fc586f976d5bdf223dc680286080b10cea00b9b5de315f9650e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x2522b60f4ea3307640a0c2dce041fba921ac10a3d5f096ef4745ca838285f019, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x23f0bee001b1029d5255075ddc957f833418cad4f52b6c3f8ce16c235572575b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x2bc1ae8b8ddbb81fcaac2d44555ed5685d142633e9df905f66d9401093082d59, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x0f9406b8296564a37304507b8dba3ed162371273a07b1fc98011fcd6ad72205f, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x2360a8eb0cc7defa67b72998de90714e17e75b174a52ee4acb126c8cd995f0a8, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x15871a5cddead976804c803cbaef255eb4815a5e96df8b006dcbbc2767f88948, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x193a56766998ee9e0a8652dd2f3b1da0362f4f54f72379544f957ccdeefb420f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x2a394a43934f86982f9be56ff4fab1703b2e63c8ad334834e4309805e777ae0f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x1859954cfeb8695f3e8b635dcb345192892cd11223443ba7b4166e8876c0d142, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x04e1181763050e58013444dbcb99f1902b11bc25d90bbdca408d3819f4fed32b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x0fdb253dee83869d40c335ea64de8c5bb10eb82db08b5e8b1f5e5552bfd05f23, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x058cbe8a9a5027bdaa4efb623adead6275f08686f1c08984a9d7c5bae9b4f1c0, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x1382edce9971e186497eadb1aeb1f52b23b4b83bef023ab0d15228b4cceca59a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x03464990f045c6ee0819ca51fd11b0be7f61b8eb99f14b77e1e6634601d9e8b5, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x23f7bfc8720dc296fff33b41f98ff83c6fcab4605db2eb5aaa5bc137aeb70a58, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x0a59a158e3eec2117e6e94e7f0e9decf18c3ffd5e1531a9219636158bbaf62f2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x06ec54c80381c052b58bf23b312ffd3ce2c4eba065420af8f4c23ed0075fd07b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x118872dc832e0eb5476b56648e867ec8b09340f7a7bcb1b4962f0ff9ed1f9d01, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x13d69fa127d834165ad5c7cba7ad59ed52e0b0f0e42d7fea95e1906b520921b1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x169a177f63ea681270b1c6877a73d21bde143942fb71dc55fd8a49f19f10c77b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x04ef51591c6ead97ef42f287adce40d93abeb032b922f66ffb7e9a5a7450544d, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x256e175a1dc079390ecd7ca703fb2e3b19ec61805d4f03ced5f45ee6dd0f69ec, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x30102d28636abd5fe5f2af412ff6004f75cc360d3205dd2da002813d3e2ceeb2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x10998e42dfcd3bbf1c0714bc73eb1bf40443a3fa99bef4a31fd31be182fcc792, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x193edd8e9fcf3d7625fa7d24b598a1d89f3362eaf4d582efecad76f879e36860, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x18168afd34f2d915d0368ce80b7b3347d1c7a561ce611425f2664d7aa51f0b5d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x29383c01ebd3b6ab0c017656ebe658b6a328ec77bc33626e29e2e95b33ea6111, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x10646d2f2603de39a1f4ae5e7771a64a702db6e86fb76ab600bf573f9010c711, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x0beb5e07d1b27145f575f1395a55bf132f90c25b40da7b3864d0242dcb1117fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x16d685252078c133dc0d3ecad62b5c8830f95bb2e54b59abdffbf018d96fa336, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x0a6abd1d833938f33c74154e0404b4b40a555bbbec21ddfafd672dd62047f01a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x1a679f5d36eb7b5c8ea12a4c2dedc8feb12dffeec450317270a6f19b34cf1860, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x0980fb233bd456c23974d50e0ebfde4726a423eada4e8f6ffbc7592e3f1b93d6, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x161b42232e61b84cbf1810af93a38fc0cece3d5628c9282003ebacb5c312c72b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x0ada10a90c7f0520950f7d47a60d5e6a493f09787f1564e5d09203db47de1a0b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x1a730d372310ba82320345a29ac4238ed3f07a8a2b4e121bb50ddb9af407f451, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x2c8120f268ef054f817064c369dda7ea908377feaba5c4dffbda10ef58e8c556, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x1c7c8824f758753fa57c00789c684217b930e95313bcb73e6e7b8649a4968f70, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x2cd9ed31f5f8691c8e39e4077a74faa0f400ad8b491eb3f7b47b27fa3fd1cf77, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x23ff4f9d46813457cf60d92f57618399a5e022ac321ca550854ae23918a22eea, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x09945a5d147a4f66ceece6405dddd9d0af5a2c5103529407dff1ea58f180426d, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x188d9c528025d4c2b67660c6b771b90f7c7da6eaa29d3f268a6dd223ec6fc630, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x3050e37996596b7f81f68311431d8734dba7d926d3633595e0c0d8ddf4f0f47f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x15af1169396830a91600ca8102c35c426ceae5461e3f95d89d829518d30afd78, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x1da6d09885432ea9a06d9f37f873d985dae933e351466b2904284da3320d8acc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := add(0x2796ea90d269af29f5f8acf33921124e4e4fad3dbe658945e546ee411ddaa9cb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x202d7dd1da0f6b4b0325c8b3307742f01e15612ec8e9304a7cb0319e01d32d60, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x096d6790d05bb759156a952ba263d672a2d7f9c788f4c831a29dace4c0f8be5f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := add(0x054efa1f65b0fce283808965275d877b438da23ce5b13e1963798cb1447d25a4, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x1b162f83d917e93edb3308c29802deb9d8aa690113b2e14864ccf6e18e4165f1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x21e5241e12564dd6fd9f1cdd2a0de39eedfefc1466cc568ec5ceb745a0506edc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := mulmod(scratch1, scratch1, F) + scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F) + state0 := mulmod(scratch2, scratch2, F) + scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F) + state0 := add(0x1cfb5662e8cf5ac9226a80ee17b36abecb73ab5f87e161927b4349e10e4bdf08, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x0f21177e302a771bbae6d8d1ecb373b62c99af346220ac0129c53f666eb24100, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x1671522374606992affb0dd7f71b12bec4236aede6290546bcef7e1f515c2320, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := mulmod(state1, state1, F) + state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F) + scratch0 := mulmod(state2, state2, F) + state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F) + scratch0 := add(0x0fa3ec5b9488259c2eb4cf24501bfad9be2ec9e42c5cc8ccd419d2a692cad870, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) + scratch1 := add(0x193c0e04e0bd298357cb266c1506080ed36edce85c648cc085e8c57b1ab54bba, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) + scratch2 := add(0x102adf8ef74735a27e9128306dcbc3c99f6f7291cd406578ce14ea2adaba68f8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) + state0 := mulmod(scratch0, scratch0, F) + scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) + state0 := mulmod(scratch1, scratch1, F) + scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F) + state0 := mulmod(scratch2, scratch2, F) + scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F) + state0 := add(0x0fe0af7858e49859e2a54d6f1ad945b1316aa24bfbdd23ae40a6d0cb70c3eab1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) + state1 := add(0x216f6717bbc7dedb08536a2220843f4e2da5f1daa9ebdefde8a5ea7344798d22, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) + state2 := add(0x1da55cc900f0d21f4a3e694391918a1b3c23b2ac773c6b3ef88e2e4228325161, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) + scratch0 := mulmod(state0, state0, F) + state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) + scratch0 := mulmod(state1, state1, F) + state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F) + scratch0 := mulmod(state2, state2, F) + state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F) + + mstore(0x0, mod(add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)), F)) + // forgefmt: disable-end + + out := mload(0) + } + } +} diff --git a/contracts/Receba.sol b/contracts/Receba.sol new file mode 100644 index 0000000..4fe2e5e --- /dev/null +++ b/contracts/Receba.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.21; + +import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import { SafeTransferLib } from "solady/src/utils/SafeTransferLib.sol"; +import { MerkleTreeWithHistory, FieldOverflow } from "./MerkleTreeWithHistory.sol"; +import { UltraVerifier } from "../circuits/contract/receba/plonk_vk.sol"; + +contract Receba is MerkleTreeWithHistory { + using SafeTransferLib for address payable; + + IERC721 public immutable DELIVERABLE; + uint256 public immutable DENOMINATION; + UltraVerifier public immutable VERIFIER; + + mapping(bytes32 commitment => bool inserted) public commitments; + mapping(bytes32 nullifierHash => bool spent) public nullifierHashes; + + constructor(IERC721 deliverable, uint256 denomination, UltraVerifier verifier) MerkleTreeWithHistory(8) { + DELIVERABLE = deliverable; + DENOMINATION = denomination; + VERIFIER = verifier; + } + + function deposit(bytes32 commitment) external payable { + if (msg.value != DENOMINATION) revert InvalidValue(); + if (commitments[commitment]) revert AlreadyInserted(); + + commitments[commitment] = true; + uint32 leafIndex = insert(commitment); + emit Deposit(commitment, leafIndex); + } + + function withdraw( + address payable recipient, + address payable relayer, + uint256 fee, + bytes32 root, + bytes32 nullifierHash, + bytes calldata proof + ) external { + if (fee > DENOMINATION) revert InvalidValue(); + if (uint256(nullifierHash) >= FIELD_SIZE) revert FieldOverflow(); + if (nullifierHashes[nullifierHash]) revert AlreadySpent(); + if (!isKnownRoot(root)) revert InvalidRoot(); + + bytes32[] memory publicInputs = new bytes32[](5); + publicInputs[0] = bytes32(uint256(uint160(address(recipient)))); + publicInputs[1] = bytes32(uint256(uint160(address(relayer)))); + publicInputs[2] = bytes32(fee); + publicInputs[3] = root; + publicInputs[4] = nullifierHash; + assert(VERIFIER.verify(proof, publicInputs)); + + nullifierHashes[nullifierHash] = true; + emit Withdraw(recipient, relayer, fee, nullifierHash); + + recipient.safeTransferETH(DENOMINATION - fee); + if (fee != 0) relayer.safeTransferETH(fee); + } + + // function request(bytes32 commitment, uint256 deliverableId, address courier) external { + // // _checkAuthorized(ownerOf(uint256(commitment)), msg.sender, uint256(commitment)); + // // _burn(uint256(commitment)); + // DELIVERABLE.ownerOf(deliverableId).safeTransferETH(DENOMINATION / 2); + // courier.safeTransferETH(DENOMINATION / 2); + // } + + event Deposit(bytes32 indexed commitment, uint32 indexed leafIndex); + event Withdraw(address indexed recipient, address indexed relayer, uint256 fee, bytes32 indexed nullifierHash); +} + +error AlreadyInserted(); +error AlreadySpent(); +error InvalidRoot(); +error InvalidFee(); +error InvalidValue(); + +struct Location { + uint128 latitude; + uint128 longitude; +} diff --git a/scripts/deploy/receba.ts b/scripts/deploy/receba.ts index 8159f99..58125e0 100644 --- a/scripts/deploy/receba.ts +++ b/scripts/deploy/receba.ts @@ -2,7 +2,9 @@ import type { DeployFunction } from 'hardhat-deploy/types'; const fn: DeployFunction = async ({ deployments: { deploy }, getNamedAccounts }) => { const { deployer: from } = await getNamedAccounts(); - await deploy('Deliverable', { from, log: true }); + const { address: verifier } = await deploy('UltraVerifier', { from, log: true }); + const { address: deliverable } = await deploy('Deliverable', { from, log: true }); + await deploy('Receba', { args: [deliverable, 10n ** 16n, verifier], from, log: true }); }; fn.tags = ['receba']; diff --git a/test/Receba.t.sol b/test/Receba.t.sol new file mode 100644 index 0000000..e4e38bf --- /dev/null +++ b/test/Receba.t.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.21; + +import { PoseidonT2 } from "poseidon-solidity/PoseidonT2.sol"; +import { PoseidonT3 } from "poseidon-solidity/PoseidonT3.sol"; +import { Test, stdJson } from "forge-std/Test.sol"; +import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; +import { Deliverable } from "../contracts/Deliverable.sol"; +import { Receba, UltraVerifier } from "../contracts/Receba.sol"; + +contract RecebaTest is Test, ERC721Holder { + using stdJson for string; + + uint256 internal constant BOB_KEY = 0xb0b; + address internal immutable BOB = vm.addr(BOB_KEY); + + Deliverable public deliverable; + Receba public receba; + + function setUp() external { + deliverable = new Deliverable(); + receba = new Receba(deliverable, 1 ether, new UltraVerifier()); + vm.label(BOB, "bob"); + } + + function test() external { + uint256 secret = 420; + uint256 nullifier = 69; + bytes32 commitment = bytes32(PoseidonT3.hash([nullifier, secret])); + bytes32 nullifierHash = bytes32(PoseidonT2.hash([nullifier])); + receba.deposit{ value: 1 ether }(commitment); + receba.withdraw( + payable(address(0x11)), + payable(address(0x22)), + 33, + 0x2432ed3bfbc63acf84c018272f20505534230dbac3746bf9fbd7d95ddfc80f45, + nullifierHash, + hex"0972875d385e251d6ad07b464efb4f8e2193dd0f174c11ca2d68b8730d4c2d6e2b955a6eeeaafbc30f9d85e4687c06204c0b80f62cfb875b6c9b12ddadffeda813dc70509d289317d7bee48d3309688ccfc8355b1f5b23023e51b1933efc1d381e9ac57f31f7dd9cfe364cd0b20adeaa6af7e0e2083618e99961372bfe59f18a0eb97f014ca7aeaebc97f5d21f8e45a6eefca374f809c363c07bb938cd503ca7026b65d3c2a2c64b2171963dab2d28ed4791f4f5e5c3aee03abb0c7c45126fc41291a5f131a8bd6c2f9149f318b819b57b3385d286804848237c979fb9a306f2205d110019cba636e566f7b1249a5ec57f658fbf5846f28d85e7e4d62f16a1421eba775dbd40ed2622348270146f0e7382b98396978e39d8edbddec482f79a8f21c7bf48a12ae196702152594a2aa8dfd7203034a087f8ac405663dd3a8d932c07ba9c848746c83fc6d206605cdd04064737a13b682fa84cb458b241262c08662ce168a945fd35c02a91555699cc521e46ccceb3be916f4f0c5157e2fc3e99400a3b41101c8e3784176a562cfc53d2b6ce4d52faf5ac06ad89197b03f05c5668108d3c90fa78ef8d2ab958feb121b01240731d72736b1c0bec62ce91b9a6cdea196bc30e2d1cc0bb3d5bb848a91136471b718d16c80e292c24936061e145501a2ff1aee3f15368f411584fe1dec048c14fd7ece386cc5997d61d0ef31facef622904a99112ee4d653f5394c003074f769f65eee23e8a5ef075de93e4dd5374012086e880aa43ae1c094b1970f4633f6b935e398327949ebd3d8bbaaf41d2db9f185d59300a80111fe77b1e211f5898eb9236b5fd901275e34f31dc3d006514b4294cd9f079ea9bf2707d2b2aa1c898fd885fd17c31e9214878e0c2fb550b707105cb573a66b3ff667866974a8d6bef5cd2a7863993a2833de81ac42869b64fa1274f2058011857f50a2f5ae26568410037e377f107ff3b6a623713cfa1e1b0e120b9dec7f8116ebffab5a0c376b2f8ff6998d157a4db47958f51ef54015a516c21c6665f338ba1e9d1d786060b91937fc41c43dc244aed9258c92ca8912f80bb056397efae8c29a568f5a3d31ab56460d5393e2e1f2c042364e0674933a4429315c1af975f66cf9975b3bcd749fd4ef805c2fdd98b319d2d72265c2142bf070917fe7b66a32e673e5be9e7d691d0af76ed12505772e6573c5f725cab5432a36d0132156015d939d33b556bde6899981d5226547d594f64fd596bfd60024f3b1b0febe06bd5635605e6669a30667c140696857503c55b95aaca815747ba492bca1347f13c92cfec5ba7c28639fa9a5d840fa13216cae9c8de32675ede58f8db1504c60ab77a2ac995adafd387edd8c953e02500e804e31619926d9475d7b537ac23ab55fe4976dc9221e4dc83081531355d5171768bac5a214cf6381749cd319523fdf3d8852bfaa636a0c83be178746a4f5c97be7274d93cf38b61bd4d0b068f0637e98a0456a91bb979d2fcc398cb27ddb0bfe473e7f16499c769729efc04cf18f030c5fd0cfe72bec133cae1c34bf19bdd61c2276657fc05184f685fc4657c1b0f93cc15eaca2253c268091fb07f2c656886f4fa18b0cb0ad193b06a4f570b19255b35575aba90ad1f28a07a772614a6987230b8cde7d12a5a9f6137d385740de068f2f2621eae193f93f8019b697ea79e1470adc7cd7d721e2f8540c485b40f6b1f46d46d05a4ff9bf9be3aacae1af3216c0b6bc18efd2976df779d4c22c80405a62167d36eaf84fedb006e8b39fded6eb6990bd5cbc6d49bcfa5a9882e591aa86bcd94d40c0e9e0eea202d0174006f802708655bc5103a74ee72b145db990808e65a8ffa9fb56ed33085b90b7ba45bed68a5c89ff68a2b6cd4ed44f8054e265738e9b178c3427d336abed1eb50a0039903848df867ffb9d0fc33b948a8a112808bee9882d392cc54c54aaccf37538a281b40e7b511fc98283f5c565b5cf0140b42427a8dba89b2b12b10e5e07befd5ab72dba5aed37c4f80ef4eb2e2fa041595f8965c98a180990d90d71ef1c08c212eca7663a894fc06d99f410f6a97181720aeea3ea388777f69f69d580305286cb2221121a2567bbe324f336bf2342c10f5d59ab677ec9be5f85f8473bdf2b73ea4c3a629bb507ce0cf8f69f9d3bfdc1f9bbe62e79b6f2681da9cef3a75c41c8ade812816e5793854281aadb5bc6fdd2635e9799ea548f99c4d9c4d1873fb86a6dc42acc06bd934c74d44558140e2160c4ff067842b8f1195c835d6f1804faa9667ac55884efb62bab0b357da3eb51710987d0ca7464a661307d7f60d0269a4fb384768d587f3098a8bbedbc7995763117fd7322a05c3222e07e314b3e59862c3ec310bd423b3db1e0202b133fe31fa07c895fe2371bea94f1d52bdf5c53d5270980045443bcaf790db213831cb7ef428d3a84d1a85d6cb1663a52300664abfc5a9acd178c7cc3e4714a8aa51a0b9f02ed61020204c4dc40ec6f23edfa40f1e7ff2602adc6d5933d93959897e24db9b01da242b2e1336a33cfd4dce9fcfaa25932b3b172c24ccab9a93be7eb10feea70bc836199b44f6c181eac5a7b9943cf2f994a9a8dcfa0da11758a915fb4d81891d2634712cc4f9532ad0a837c260cbeee39aa685c763371c0870d06988b41d6420416fa9e1d422ce2b999d8feb93985fc4b634900ba090f8992b6e0dbc00ed790ec7c2f2d6d122f8a26fa2fa893f5596445a6d7dd9e0ae261efb90e6925656982db264aeacffc34cd195ee1ba86c6b29ec328eb421da3be4e8ada95358abbfb81c38b7f7a1fcc377486bf386461828606bd6c7a1f01a59126e7dcc2c2f0128d72a2024c927ecb2916baac3e6bfec1ad5b3751e1b5bcec16f482c68fb618c137b295e451a3efab01aa06a8db5f7aafd8bb0aea37a17b5e2982237589731169c7800d76912a9abe8fb87af06aa58c0c11fdca1dded7818f0f1ded299dd047f7cd4108a56a05bac21f4d9a82b8f4707ef3761825c2a63473c80003dd95e7715e014" + ); + } + + receive() external payable { } +} diff --git a/webapp/wagmi.config.ts b/webapp/wagmi.config.ts index 42b4687..b1935af 100644 --- a/webapp/wagmi.config.ts +++ b/webapp/wagmi.config.ts @@ -2,6 +2,7 @@ import { foundry as chain } from 'viem/chains'; import { defineConfig } from '@wagmi/cli'; import { getAddress } from 'viem'; import { foundry } from '@wagmi/cli/plugins'; +import { address as receba } from '../deployments/localhost/Receba.json' assert { type: 'json' }; import { address as deliverable } from '../deployments/localhost/Deliverable.json' assert { type: 'json' }; export default defineConfig({ @@ -10,6 +11,7 @@ export default defineConfig({ foundry({ project: '..', deployments: { + Receba: { [chain.id]: getAddress(receba) }, Deliverable: { [chain.id]: getAddress(deliverable) }, }, }),