From e5ffa9ade5b1159064311ce87dca56daba76c7e4 Mon Sep 17 00:00:00 2001 From: OneTony Date: Mon, 20 Nov 2023 12:09:33 +0200 Subject: [PATCH 1/2] feat: oracle contract --- solidity/contracts/MockOracle.sol | 46 +++++++++++++++++++++++++++++ solidity/test/e2e/Common.sol | 9 ++++++ solidity/test/unit/MockOracle.t.sol | 39 ++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 solidity/contracts/MockOracle.sol create mode 100644 solidity/test/unit/MockOracle.t.sol diff --git a/solidity/contracts/MockOracle.sol b/solidity/contracts/MockOracle.sol new file mode 100644 index 0000000..6fcf54b --- /dev/null +++ b/solidity/contracts/MockOracle.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.19; + +/** + * @title MockOracle + * @notice This contract's purpose is to return the latest stored L1 block header and timestamp + * @notice Every X minutes a "magical" off-chain agent provides the latest block header and timestamp + */ +contract MockOracle { + /** + * @notice Emits when the block header and timestamp are updated + */ + event BlockHeaderUpdated(bytes _blockHeader, uint256 _blockTimestamp, uint256 _blockNumber); + + /** + * @notice The block header + */ + bytes public blockHeader; + + /** + * @notice The block timestamp of the latest block header + */ + uint256 public blockTimestamp; + + /** + * @notice Updates the block header and timestamp + * @param _blockHeader The block header + * @param _blockTimestamp The block timestamp + * @param _blockNumber The block number + */ + function updateBlockHeader(bytes memory _blockHeader, uint256 _blockTimestamp, uint256 _blockNumber) external { + blockHeader = _blockHeader; + blockTimestamp = _blockTimestamp; + + emit BlockHeaderUpdated(_blockHeader, _blockTimestamp, _blockNumber); + } + + /** + * @notice Returns the latest block header and timestamp + * @return _blockHeader The block header + * @return _blockTimestamp The block timestamp + */ + function getLatestBlockHeader() external view returns (bytes memory _blockHeader, uint256 _blockTimestamp) { + return (blockHeader, blockTimestamp); + } +} diff --git a/solidity/test/e2e/Common.sol b/solidity/test/e2e/Common.sol index a0a42ae..3b222bd 100644 --- a/solidity/test/e2e/Common.sol +++ b/solidity/test/e2e/Common.sol @@ -5,11 +5,15 @@ import {DSTestPlus} from '@defi-wonderland/solidity-utils/solidity/test/DSTestPl import {IERC20} from 'isolmate/interfaces/tokens/IERC20.sol'; import {SafeProxy} from 'safe-contracts/proxies/SafeProxy.sol'; import {Enum} from 'safe-contracts/common/Enum.sol'; + import {StorageMirror} from 'contracts/StorageMirror.sol'; import {UpdateStorageMirrorGuard} from 'contracts/UpdateStorageMirrorGuard.sol'; import {GuardCallbackModule} from 'contracts/GuardCallbackModule.sol'; +import {MockOracle} from 'contracts/MockOracle.sol'; + import {IGuardCallbackModule} from 'interfaces/IGuardCallbackModule.sol'; import {ISafe} from 'interfaces/ISafe.sol'; + import {IGnosisSafeProxyFactory} from 'test/e2e/IGnosisSafeProxyFactory.sol'; import {TestConstants} from 'test/utils/TestConstants.sol'; import {ContractDeploymentAddress} from 'test/utils/ContractDeploymentAddress.sol'; @@ -25,6 +29,7 @@ contract CommonE2EBase is DSTestPlus, TestConstants { StorageMirror public storageMirror; UpdateStorageMirrorGuard public updateStorageMirrorGuard; GuardCallbackModule public guardCallbackModule; + MockOracle public oracle; ISafe public safe; IGnosisSafeProxyFactory public gnosisSafeProxyFactory = IGnosisSafeProxyFactory(GNOSIS_SAFE_PROXY_FACTORY); @@ -52,6 +57,10 @@ contract CommonE2EBase is DSTestPlus, TestConstants { updateStorageMirrorGuard = new UpdateStorageMirrorGuard(guardCallbackModule); // deployer nonce 2 label(address(updateStorageMirrorGuard), 'UpdateStorageMirrorGuard'); + vm.prank(deployer); + oracle = new MockOracle(); // deployer nonce 3 + label(address(oracle), 'MockOracle'); + // Make sure the theoritical address was calculated correctly assert(address(updateStorageMirrorGuard) == _updateStorageMirrorGuardTheoriticalAddress); diff --git a/solidity/test/unit/MockOracle.t.sol b/solidity/test/unit/MockOracle.t.sol new file mode 100644 index 0000000..fd7527c --- /dev/null +++ b/solidity/test/unit/MockOracle.t.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.4 <0.9.0; + +import {Test} from 'forge-std/Test.sol'; +import {MockOracle} from 'contracts/MockOracle.sol'; + +abstract contract Base is Test { + event BlockHeaderUpdated(bytes _blockHeader, uint256 _blockTimestamp, uint256 _blockNumber); + + MockOracle public oracle; + + function setUp() public { + oracle = new MockOracle(); + } +} + +contract UnitMockOracle is Base { + function testUpdateBlockHeader(bytes memory _blockHeader, uint256 _blockTimestamp, uint256 _blockNumber) public { + vm.expectEmit(true, true, true, true); + emit BlockHeaderUpdated(_blockHeader, _blockTimestamp, _blockNumber); + oracle.updateBlockHeader(_blockHeader, _blockTimestamp, _blockNumber); + + assertEq(_blockHeader, oracle.blockHeader(), 'Block header should be saved'); + assertEq(_blockTimestamp, oracle.blockTimestamp(), 'Block timestamp should be saved'); + } + + function testGetLatestBlockHeader() public { + bytes memory _blockHeader = '0x1234'; + uint256 _blockTimestamp = 1234; + uint256 _blockNumber = 1234; + + oracle.updateBlockHeader(_blockHeader, _blockTimestamp, _blockNumber); + + (bytes memory _savedBlockHeader, uint256 _savedBlockTimestamp) = oracle.getLatestBlockHeader(); + + assertEq(_blockHeader, _savedBlockHeader, 'Block header should be saved'); + assertEq(_blockTimestamp, _savedBlockTimestamp, 'Block timestamp should be saved'); + } +} From 66e2c1914c6e06dec9ef17341cc99387fc695637 Mon Sep 17 00:00:00 2001 From: OneTony Date: Mon, 20 Nov 2023 12:31:52 +0200 Subject: [PATCH 2/2] fix: naming --- .../contracts/{MockOracle.sol => BlockHeaderOracle.sol} | 4 ++-- solidity/test/e2e/Common.sol | 6 +++--- solidity/test/unit/MockOracle.t.sol | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) rename solidity/contracts/{MockOracle.sol => BlockHeaderOracle.sol} (96%) diff --git a/solidity/contracts/MockOracle.sol b/solidity/contracts/BlockHeaderOracle.sol similarity index 96% rename from solidity/contracts/MockOracle.sol rename to solidity/contracts/BlockHeaderOracle.sol index 6fcf54b..cc082ff 100644 --- a/solidity/contracts/MockOracle.sol +++ b/solidity/contracts/BlockHeaderOracle.sol @@ -2,11 +2,11 @@ pragma solidity =0.8.19; /** - * @title MockOracle + * @title BlockHeaderOracle * @notice This contract's purpose is to return the latest stored L1 block header and timestamp * @notice Every X minutes a "magical" off-chain agent provides the latest block header and timestamp */ -contract MockOracle { +contract BlockHeaderOracle { /** * @notice Emits when the block header and timestamp are updated */ diff --git a/solidity/test/e2e/Common.sol b/solidity/test/e2e/Common.sol index 3b222bd..e5c2fe7 100644 --- a/solidity/test/e2e/Common.sol +++ b/solidity/test/e2e/Common.sol @@ -9,7 +9,7 @@ import {Enum} from 'safe-contracts/common/Enum.sol'; import {StorageMirror} from 'contracts/StorageMirror.sol'; import {UpdateStorageMirrorGuard} from 'contracts/UpdateStorageMirrorGuard.sol'; import {GuardCallbackModule} from 'contracts/GuardCallbackModule.sol'; -import {MockOracle} from 'contracts/MockOracle.sol'; +import {BlockHeaderOracle} from 'contracts/BlockHeaderOracle.sol'; import {IGuardCallbackModule} from 'interfaces/IGuardCallbackModule.sol'; import {ISafe} from 'interfaces/ISafe.sol'; @@ -29,7 +29,7 @@ contract CommonE2EBase is DSTestPlus, TestConstants { StorageMirror public storageMirror; UpdateStorageMirrorGuard public updateStorageMirrorGuard; GuardCallbackModule public guardCallbackModule; - MockOracle public oracle; + BlockHeaderOracle public oracle; ISafe public safe; IGnosisSafeProxyFactory public gnosisSafeProxyFactory = IGnosisSafeProxyFactory(GNOSIS_SAFE_PROXY_FACTORY); @@ -58,7 +58,7 @@ contract CommonE2EBase is DSTestPlus, TestConstants { label(address(updateStorageMirrorGuard), 'UpdateStorageMirrorGuard'); vm.prank(deployer); - oracle = new MockOracle(); // deployer nonce 3 + oracle = new BlockHeaderOracle(); // deployer nonce 3 label(address(oracle), 'MockOracle'); // Make sure the theoritical address was calculated correctly diff --git a/solidity/test/unit/MockOracle.t.sol b/solidity/test/unit/MockOracle.t.sol index fd7527c..7f586b0 100644 --- a/solidity/test/unit/MockOracle.t.sol +++ b/solidity/test/unit/MockOracle.t.sol @@ -2,19 +2,19 @@ pragma solidity >=0.8.4 <0.9.0; import {Test} from 'forge-std/Test.sol'; -import {MockOracle} from 'contracts/MockOracle.sol'; +import {BlockHeaderOracle} from 'contracts/BlockHeaderOracle.sol'; abstract contract Base is Test { event BlockHeaderUpdated(bytes _blockHeader, uint256 _blockTimestamp, uint256 _blockNumber); - MockOracle public oracle; + BlockHeaderOracle public oracle; function setUp() public { - oracle = new MockOracle(); + oracle = new BlockHeaderOracle(); } } -contract UnitMockOracle is Base { +contract UnitBlockHeaderOracle is Base { function testUpdateBlockHeader(bytes memory _blockHeader, uint256 _blockTimestamp, uint256 _blockNumber) public { vm.expectEmit(true, true, true, true); emit BlockHeaderUpdated(_blockHeader, _blockTimestamp, _blockNumber);