diff --git a/contracts/PreConfirmations.sol b/contracts/PreConfirmations.sol index aea3d20..9dc8500 100644 --- a/contracts/PreConfirmations.sol +++ b/contracts/PreConfirmations.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity ^0.8.15; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IProviderRegistry} from "./interfaces/IProviderRegistry.sol"; import {IUserRegistry} from "./interfaces/IUserRegistry.sol"; -import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /** * @title PreConfCommitmentStore - A contract for managing preconfirmation commitments and bids. @@ -113,7 +113,7 @@ contract PreConfCommitmentStore is Ownable { address _providerRegistry, address _userRegistry, address _oracle - ) Ownable(msg.sender) { + ) { oracle = _oracle; providerRegistry = IProviderRegistry(_providerRegistry); userRegistry = IUserRegistry(_userRegistry); @@ -149,7 +149,7 @@ contract PreConfCommitmentStore is Ownable { uint64 _blockNumber ) public view returns (bytes32) { return - MessageHashUtils.toTypedDataHash( + ECDSA.toTypedDataHash( DOMAIN_SEPARATOR_BID, keccak256( abi.encode( @@ -178,7 +178,7 @@ contract PreConfCommitmentStore is Ownable { string memory _bidSignature ) public view returns (bytes32) { return - MessageHashUtils.toTypedDataHash( + ECDSA.toTypedDataHash( DOMAIN_SEPARATOR_PRECONF, keccak256( abi.encode( diff --git a/contracts/ProviderRegistry.sol b/contracts/ProviderRegistry.sol index c5ccf11..1bac5f0 100644 --- a/contracts/ProviderRegistry.sol +++ b/contracts/ProviderRegistry.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity ^0.8.15; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {PreConfCommitmentStore} from "./PreConfirmations.sol"; import {IProviderRegistry} from "./interfaces/IProviderRegistry.sol"; @@ -75,7 +75,7 @@ contract ProviderRegistry is IProviderRegistry, Ownable, ReentrancyGuard { uint256 _minStake, address _feeRecipient, uint16 _feePercent - ) Ownable(msg.sender) { + ) { minStake = _minStake; feeRecipient = _feeRecipient; feePercent = _feePercent; diff --git a/contracts/UserRegistry.sol b/contracts/UserRegistry.sol index 71b4fe5..ea9fc1d 100644 --- a/contracts/UserRegistry.sol +++ b/contracts/UserRegistry.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity ^0.8.15; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {IUserRegistry} from "./interfaces/IUserRegistry.sol"; /// @title User Registry @@ -71,7 +71,7 @@ contract UserRegistry is IUserRegistry, Ownable, ReentrancyGuard { uint256 _minStake, address _feeRecipient, uint16 _feePercent - ) Ownable(msg.sender) { + ) { minStake = _minStake; feeRecipient = _feeRecipient; feePercent = _feePercent; diff --git a/contracts/interfaces/IProviderRegistry.sol b/contracts/interfaces/IProviderRegistry.sol index b22be2b..69a969d 100644 --- a/contracts/interfaces/IProviderRegistry.sol +++ b/contracts/interfaces/IProviderRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity ^0.8.15; interface IProviderRegistry { function registerAndStake() external payable; diff --git a/contracts/interfaces/IUserRegistry.sol b/contracts/interfaces/IUserRegistry.sol index aa0d601..44e72c7 100644 --- a/contracts/interfaces/IUserRegistry.sol +++ b/contracts/interfaces/IUserRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity ^0.8.15; interface IUserRegistry { struct PreConfCommitment { diff --git a/hardhat.config.js b/hardhat.config.js index 6ebb520..f8d50ca 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -4,7 +4,7 @@ require("solidity-docgen"); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { - solidity: "0.8.20", + solidity: "0.8.15", networks: { localhost: { url: "http://127.0.0.1:8545", // Ganache default port diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index 7c8b7a2..fd81a96 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 7c8b7a27284f503ce8ae23d63ac9403096dcf6fe +Subproject commit fd81a96f01cc42ef1c9a5399364968d0e07e9e90 diff --git a/test/OracleTest.sol b/test/OracleTest.sol index 275ac6b..8f47022 100644 --- a/test/OracleTest.sol +++ b/test/OracleTest.sol @@ -80,6 +80,111 @@ contract OracleTest is Test { oracle.receiveBlockData(txnList, blockNumber, blockBuilderName); } + /** + constructAndStoreCommitment is a helper function to construct and store a commitment + */ + function constructAndStoreCommitment( + uint64 bid, + uint64 blockNumber, + string memory txnHash, + uint256 bidderPk, + uint256 signerPk + ) public returns (bytes32 commitmentIndex) { + bytes32 bidHash = preConfCommitmentStore.getBidHash( + txnHash, + bid, + blockNumber + ); + + + (uint8 v,bytes32 r, bytes32 s) = vm.sign(bidderPk, bidHash); + bytes memory bidSignature = abi.encodePacked(r, s, v); + + bytes32 commitmentHash = preConfCommitmentStore.getPreConfHash( + txnHash, + bid, + blockNumber, + bidHash, + _bytesToHexString(bidSignature) + ); + + (v,r,s) = vm.sign(signerPk, commitmentHash); + bytes memory commitmentSignature = abi.encodePacked(r, s, v); + + commitmentIndex = preConfCommitmentStore.storeCommitment( + bid, + blockNumber, + txnHash, + bidSignature, + commitmentSignature + ); + + return commitmentIndex; + } + + function test_ReceiveBlockDataWithCommitments() public { + string[] memory txnList = new string[](1); + txnList[0] = string(abi.encodePacked(keccak256("0xkartik"))); + uint64 blockNumber = 200; + uint64 bid = 2; + string memory blockBuilderName = "kartik builder"; + (address user, uint256 userPk) = makeAddrAndKey("alice"); + + vm.deal(user, 200000 ether); + vm.startPrank(user); + userRegistry.registerAndStake{value: 250 ether }(); + providerRegistry.registerAndStake{value: 250 ether}(); + vm.stopPrank(); + + bytes32 commitmentIndex = constructAndStoreCommitment(bid, blockNumber, txnList[0], userPk, userPk); + vm.prank(address(0x6d503Fd50142C7C469C7c6B64794B55bfa6883f3)); + oracle.addBuilderAddress("kartik builder", user); + vm.expectEmit(true, true, false, true); + emit BlockDataReceived(txnList, blockNumber, blockBuilderName); + oracle.receiveBlockData(txnList, blockNumber, blockBuilderName); + + bytes32[] memory commitmentHashes = preConfCommitmentStore.getCommitmentsByBlockNumber(blockNumber); + assertEq(commitmentHashes.length, 1); + assertEq(userRegistry.getProviderAmount(user), bid); + + } + + + function test_ReceiveBlockDataWithCommitmentsSlashed() public { + string[] memory txnList = new string[](1); + txnList[0] = string(abi.encodePacked(keccak256("0xkartik"))); + uint64 blockNumber = 200; + uint64 bid = 2; + string memory blockBuilderName = "kartik builder"; + (address user, uint256 userPk) = makeAddrAndKey("alice"); + + vm.deal(user, 200000 ether); + vm.startPrank(user); + userRegistry.registerAndStake{value: 250 ether }(); + providerRegistry.registerAndStake{value: 250 ether}(); + vm.stopPrank(); + uint256 ogStake = providerRegistry.checkStake(user); + + string memory commitedTxn = string(abi.encodePacked(keccak256("0xSlash"))); + bytes32 commitmentIndex = constructAndStoreCommitment(bid, blockNumber, commitedTxn, userPk, userPk); + vm.prank(address(0x6d503Fd50142C7C469C7c6B64794B55bfa6883f3)); + oracle.addBuilderAddress("kartik builder", user); + vm.expectEmit(true, true, false, true); + emit BlockDataReceived(txnList, blockNumber, blockBuilderName); + oracle.receiveBlockData(txnList, blockNumber, blockBuilderName); + + bytes32[] memory commitmentHashes = preConfCommitmentStore.getCommitmentsByBlockNumber(blockNumber); + assertEq(commitmentHashes.length, 1); + + // Ensuring no rewards + assertEq(userRegistry.getProviderAmount(user), 0); + + // Detect slashing + uint256 postSlashStake = providerRegistry.checkStake(user); + assertEq(postSlashStake + bid, ogStake); + + } + // function test_ProcessCommitment_Slash() public { // TODO(@ckartik): Add test // }