generated from defi-wonderland/solidity-foundry-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' of github.com:defi-wonderland/safe-liveness into f…
…ix/storage-mirror-types
- Loading branch information
Showing
6 changed files
with
210 additions
and
10 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity =0.8.19; | ||
|
||
import {IBlockHeaderOracle} from 'interfaces/IBlockHeaderOracle.sol'; | ||
import {IVerifierModule} from 'interfaces/IVerifierModule.sol'; | ||
import {IStorageMirrorRootRegistry} from 'interfaces/IStorageMirrorRootRegistry.sol'; | ||
|
||
/** | ||
* @title StorageMirrorRootRegistry | ||
* @notice This contract should accept and store storageRoots of the StorageMirror contract in L1. | ||
*/ | ||
contract StorageMirrorRootRegistry is IStorageMirrorRootRegistry { | ||
/** | ||
* @notice The address of the StorageMirror contract in Home chain | ||
*/ | ||
address public immutable STORAGE_MIRROR; | ||
|
||
/** | ||
* @notice The address of the Verifier Module | ||
*/ | ||
IVerifierModule public immutable VERIFIER_MODULE; | ||
|
||
/** | ||
* @notice The block header oracle | ||
*/ | ||
IBlockHeaderOracle public immutable BLOCK_HEADER_ORACLE; | ||
|
||
/** | ||
* @notice The latest verified storage root of the StorageMirror contract in Home chain | ||
*/ | ||
bytes32 public latestVerifiedStorageMirrorStorageRoot; | ||
|
||
/** | ||
* @notice The latest verified block number of the Home chain | ||
*/ | ||
uint256 public latestVerifiedBlockNumber; | ||
|
||
constructor(address _storageMirror, IVerifierModule _verifierModule, IBlockHeaderOracle _blockHeaderOracle) { | ||
STORAGE_MIRROR = _storageMirror; | ||
VERIFIER_MODULE = _verifierModule; | ||
BLOCK_HEADER_ORACLE = _blockHeaderOracle; | ||
} | ||
|
||
/** | ||
* @notice Users can use to propose and verify a storage root of the StorageMirror contract in Home chain | ||
* @dev Calls queryL1BlockHeader to get the block header of the Home chain | ||
* @dev Call verifier module for the actual verificationn | ||
* @param _accountProof The account proof of the StorageMirror contract in Home chain | ||
*/ | ||
function proposeAndVerifyStorageMirrorStorageRoot(bytes memory _accountProof) external { | ||
bytes memory _blockHeader = _queryL1BlockHeader(); | ||
|
||
(bytes32 _latestVerifiedStorageMirrorStorageRoot, uint256 _blockNumber) = | ||
VERIFIER_MODULE.extractStorageMirrorStorageRoot(_blockHeader, _accountProof); | ||
|
||
latestVerifiedStorageMirrorStorageRoot = _latestVerifiedStorageMirrorStorageRoot; | ||
latestVerifiedBlockNumber = _blockNumber; | ||
|
||
emit VerifiedStorageMirrorStorageRoot(_blockNumber, latestVerifiedStorageMirrorStorageRoot); | ||
} | ||
|
||
/** | ||
* @notice Function that queries an oracle to get the latest bridged block header of the Home chain | ||
* @return _blockHeader The block header of the Home chain | ||
*/ | ||
function _queryL1BlockHeader() internal view returns (bytes memory _blockHeader) { | ||
(_blockHeader,) = BLOCK_HEADER_ORACLE.getLatestBlockHeader(); | ||
} | ||
} |
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
File renamed without changes.
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,88 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity >=0.8.4 <0.9.0; | ||
|
||
import {Test} from 'forge-std/Test.sol'; | ||
import {BlockHeaderOracle} from 'contracts/BlockHeaderOracle.sol'; | ||
import {StorageMirrorRootRegistry} from 'contracts/StorageMirrorRootRegistry.sol'; | ||
import {IBlockHeaderOracle} from 'interfaces/IBlockHeaderOracle.sol'; | ||
import {IStorageMirrorRootRegistry} from 'interfaces/IStorageMirrorRootRegistry.sol'; | ||
import {IVerifierModule} from 'interfaces/IVerifierModule.sol'; | ||
|
||
contract StorageMirrorRootRegistryForTest is StorageMirrorRootRegistry { | ||
constructor( | ||
address _storageMirror, | ||
IVerifierModule _verifierModule, | ||
IBlockHeaderOracle _blockHeaderOracle | ||
) StorageMirrorRootRegistry(_storageMirror, _verifierModule, _blockHeaderOracle) {} | ||
|
||
function queryL1BlockHeader() external view returns (bytes memory _blockHeader) { | ||
_blockHeader = _queryL1BlockHeader(); | ||
} | ||
} | ||
|
||
abstract contract Base is Test { | ||
event VerifiedStorageMirrorStorageRoot(uint256 indexed _homeChainBlockNumber, bytes32 _storageRoot); | ||
|
||
address public user; | ||
address public storageMirror; | ||
StorageMirrorRootRegistry public storageMirrorRootRegistry; | ||
StorageMirrorRootRegistryForTest public storageMirrorRootRegistryForTest; | ||
BlockHeaderOracle public blockHeaderOracle; | ||
IVerifierModule public verifierModule; | ||
|
||
function setUp() public { | ||
user = makeAddr('user'); | ||
storageMirror = makeAddr('StorageMirror'); | ||
blockHeaderOracle = new BlockHeaderOracle(); | ||
verifierModule = IVerifierModule(makeAddr('VerifierModule')); | ||
storageMirrorRootRegistry = | ||
new StorageMirrorRootRegistry(storageMirror, verifierModule, IBlockHeaderOracle(blockHeaderOracle)); | ||
storageMirrorRootRegistryForTest = | ||
new StorageMirrorRootRegistryForTest(storageMirror, verifierModule, IBlockHeaderOracle(blockHeaderOracle)); | ||
} | ||
} | ||
|
||
contract UnitStorageMirrorRootRegistryQueryL1BlockHeader is Base { | ||
function testQueryL1BlockHeader(bytes memory _blockHeader, uint256 _blockTimestamp, uint256 _blockNumber) public { | ||
vm.prank(user); | ||
blockHeaderOracle.updateBlockHeader(_blockHeader, _blockTimestamp, _blockNumber); | ||
|
||
vm.expectCall(address(blockHeaderOracle), abi.encodeWithSelector(blockHeaderOracle.getLatestBlockHeader.selector)); | ||
vm.prank(user); | ||
bytes memory _savedBlockHeader = storageMirrorRootRegistryForTest.queryL1BlockHeader(); | ||
|
||
assertEq(_blockHeader, _savedBlockHeader, 'Block header should be saved'); | ||
} | ||
} | ||
|
||
contract UnitStorageMirrorRootRegistryProposeAndVerifyStorageMirrorStorageRoot is Base { | ||
function testProposeAndVerifyStorageMirrorStorageRoot(bytes memory _accountProof) public { | ||
bytes memory _blockHeader = '0x1234'; | ||
uint256 _blockTimestamp = 1234; | ||
uint256 _blockNumber = 1234; | ||
bytes32 _storageRoot = '0x1234'; | ||
|
||
vm.prank(user); | ||
blockHeaderOracle.updateBlockHeader(_blockHeader, _blockTimestamp, _blockNumber); | ||
|
||
vm.mockCall( | ||
address(verifierModule), | ||
abi.encodeWithSelector(verifierModule.extractStorageMirrorStorageRoot.selector, _blockHeader, _accountProof), | ||
abi.encode(_storageRoot, _blockNumber) | ||
); | ||
vm.expectCall( | ||
address(verifierModule), | ||
abi.encodeWithSelector(verifierModule.extractStorageMirrorStorageRoot.selector, _blockHeader, _accountProof) | ||
); | ||
|
||
vm.expectEmit(true, true, true, true); | ||
emit VerifiedStorageMirrorStorageRoot(_blockNumber, _storageRoot); | ||
|
||
vm.prank(user); | ||
storageMirrorRootRegistry.proposeAndVerifyStorageMirrorStorageRoot(_accountProof); | ||
|
||
assertEq( | ||
_storageRoot, storageMirrorRootRegistry.latestVerifiedStorageMirrorStorageRoot(), 'Storage root should be saved' | ||
); | ||
} | ||
} |
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