Skip to content

Commit 5253079

Browse files
committed
Implement moving fact hashes
1 parent 44e262a commit 5253079

File tree

6 files changed

+92
-1
lines changed

6 files changed

+92
-1
lines changed

solidity/src/interfaces/modules/ICairoFactRegistryModule.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,12 @@ interface ICairoFactRegistryModule {
4343
function isMockedForInternal() external view returns (bool);
4444

4545
function setIsMockedForInternal(bool isMocked) external;
46+
47+
// ========= Moving facts ========= //
48+
49+
function _receiveCairoFactHash(bytes32 factHash, bool isMocked) external;
50+
51+
function getStorageSlotForCairoFact(bytes32 factHash, bool isMocked) external pure returns (bytes32);
52+
53+
function moveCairoFactFromStorageProof(uint256 originChainId, uint256 blockNumber, bytes32 factHash, bool isMocked) external;
4654
}

solidity/src/interfaces/modules/messaging/receiver/IReceiverModule.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ interface IReceiverModule {
1616
uint256 originalMmrId,
1717
bool isSiblingSynced
1818
) external;
19+
20+
function receiveCairoFactHash(bytes32 factHash, bool isMocked) external;
1921
}

solidity/src/interfaces/modules/messaging/sender/IUniversalSenderModule.sol

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,11 @@ interface IUniversalSenderModule {
3434
bool isOffchainGrownDestination,
3535
bytes calldata _xDomainMsgGasData
3636
) external payable;
37+
38+
/// @notice Send Cairo fact hash that was registered on our chain to the destination chain
39+
/// @param destinationChainId the chain ID of the destination chain
40+
/// @param factHash the hash of the fact
41+
/// @param isMocked if true, the fact is mocked
42+
/// @param _xDomainMsgGasData the gas data for the cross-domain message, depends on the destination chain
43+
function sendCairoFactHash(uint256 destinationChainId, bytes32 factHash, bool isMocked, bytes calldata _xDomainMsgGasData) external payable;
3744
}

solidity/src/modules/CairoFactRegistryModule.sol

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity ^0.8.20;
44
import {ICairoFactRegistryModule} from "../interfaces/modules/ICairoFactRegistryModule.sol";
55
import {IFactsRegistry} from "../interfaces/external/IFactsRegistry.sol";
66
import {AccessController} from "../libraries/AccessController.sol";
7+
import {ISatellite} from "../interfaces/ISatellite.sol";
78

89
struct CairoFactRegistryModuleStorage {
910
// It is stored here so that it can be storage proven between satellites.
@@ -67,7 +68,7 @@ contract CairoFactRegistryModule is ICairoFactRegistryModule, AccessController {
6768
/// @inheritdoc ICairoFactRegistryModule
6869
function isCairoMockedFactValid(bytes32 factHash) external view returns (bool) {
6970
CairoFactRegistryModuleStorage storage ms = moduleStorage();
70-
return ms.mockedFacts[factHash] || address(ms.fallbackMockedContract) != address(0) && ms.fallbackMockedContract.isValid(factHash);
71+
return ms.mockedFacts[factHash] || (address(ms.fallbackMockedContract) != address(0) && ms.fallbackMockedContract.isValid(factHash));
7172
}
7273

7374
/// @inheritdoc ICairoFactRegistryModule
@@ -113,4 +114,47 @@ contract CairoFactRegistryModule is ICairoFactRegistryModule, AccessController {
113114
moduleStorage().isMockedForInternal = isMocked;
114115
emit IsMockedForInternalSet(isMocked);
115116
}
117+
118+
// ========= Moving facts ========= //
119+
120+
function _saveCairoFact(bytes32 factHash, bool isMocked) internal {
121+
CairoFactRegistryModuleStorage storage ms = moduleStorage();
122+
if (isMocked) {
123+
ms.mockedFacts[factHash] = true;
124+
if (address(ms.fallbackMockedContract) != address(0)) {
125+
ms.fallbackMockedContract.setValid(factHash);
126+
}
127+
} else {
128+
ms.facts[factHash] = true;
129+
if (address(ms.externalFactRegistry) != address(0)) {
130+
ms.externalFactRegistry.setValid(factHash);
131+
}
132+
}
133+
}
134+
135+
/// @inheritdoc ICairoFactRegistryModule
136+
function _receiveCairoFactHash(bytes32 factHash, bool isMocked) external onlyModule {
137+
_saveCairoFact(factHash, isMocked);
138+
}
139+
140+
/// @inheritdoc ICairoFactRegistryModule
141+
function getStorageSlotForCairoFact(bytes32 factHash, bool isMocked) public pure returns (bytes32) {
142+
uint256 baseSlot = uint256(MODULE_STORAGE_POSITION) + (isMocked ? 1 : 0);
143+
return keccak256(abi.encode(factHash, baseSlot));
144+
}
145+
146+
/// @inheritdoc ICairoFactRegistryModule
147+
function moveCairoFactFromStorageProof(uint256 originChainId, uint256 blockNumber, bytes32 factHash, bool isMocked) external {
148+
bytes32 slot = getStorageSlotForCairoFact(factHash, isMocked);
149+
150+
ISatellite satellite = ISatellite(address(this));
151+
152+
uint256 accountU256 = satellite.getSatelliteConnection(originChainId).satelliteAddress;
153+
require(accountU256 >> 160 == 0, "NON_EVM_SATELLITE");
154+
address account = address(uint160(accountU256));
155+
156+
require(uint256(satellite.storageSlot(originChainId, blockNumber, account, slot)) == 1, "FACT_NOT_SAVED");
157+
158+
_saveCairoFact(factHash, isMocked);
159+
}
116160
}

solidity/src/modules/messaging/receiver/AbstractReceiverModule.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ abstract contract AbstractReceiverModule is IReceiverModule {
2525
ISatellite(address(this))._createMmrFromForeign(newMmrId, rootsForHashingFunctions, mmrSize, accumulatedChainId, originChainId, originalMmrId, isOffchainGrown);
2626
}
2727

28+
function receiveCairoFactHash(bytes32 factHash, bool isMocked) external onlyCrossdomainCounterpart {
29+
ISatellite(address(this))._receiveCairoFactHash(factHash, isMocked);
30+
}
31+
2832
modifier onlyCrossdomainCounterpart() {
2933
require(isCrossdomainCounterpart(), "Only crossdomain counterpart allowed");
3034
_;

solidity/src/modules/messaging/sender/UniversalSenderModule.sol

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ contract UniversalSenderModule is IUniversalSenderModule {
2525

2626
ILibSatellite.SatelliteConnection memory satellite = s.satelliteConnectionRegistry[destinationChainId];
2727

28+
require(satellite.inboxAddress != address(0x0), "Invalid destination chain");
29+
2830
bytes memory data = abi.encodeWithSelector(
2931
satellite.sendMessageSelector,
3032
satellite.satelliteAddress,
@@ -97,4 +99,28 @@ contract UniversalSenderModule is IUniversalSenderModule {
9799
(bool success, ) = address(this).call{value: msg.value}(data);
98100
require(success, "Function call failed");
99101
}
102+
103+
function sendCairoFactHash(uint256 destinationChainId, bytes32 factHash, bool isMocked, bytes calldata _xDomainMsgGasData) external payable {
104+
ISatellite.SatelliteStorage storage s = LibSatellite.satelliteStorage();
105+
if (isMocked) {
106+
require(ISatellite(address(this)).isCairoMockedFactValid(factHash), "ERR_FACT_NOT_VALID");
107+
} else {
108+
require(ISatellite(address(this)).isCairoFactValid(factHash), "ERR_FACT_NOT_VALID");
109+
}
110+
111+
ILibSatellite.SatelliteConnection memory satellite = s.satelliteConnectionRegistry[destinationChainId];
112+
113+
require(satellite.inboxAddress != address(0x0), "Invalid destination chain");
114+
115+
bytes memory data = abi.encodeWithSelector(
116+
satellite.sendMessageSelector,
117+
satellite.satelliteAddress,
118+
satellite.inboxAddress,
119+
abi.encodeWithSignature("receiveCairoFactHash(bytes32,bool)", factHash, isMocked),
120+
_xDomainMsgGasData
121+
);
122+
123+
(bool success, ) = address(this).call{value: msg.value}(data);
124+
require(success, "Function call failed");
125+
}
100126
}

0 commit comments

Comments
 (0)