diff --git a/contracts/contracts/core/BidderRegistry.sol b/contracts/contracts/core/BidderRegistry.sol index f3ff4ef16..706e3ac58 100644 --- a/contracts/contracts/core/BidderRegistry.sol +++ b/contracts/contracts/core/BidderRegistry.sol @@ -5,6 +5,7 @@ import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/acces import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import {IBidderRegistry} from "../interfaces/IBidderRegistry.sol"; +import {BidderRegistryStorage} from "./BidderRegistryStorage.sol"; import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; import {WindowFromBlockNumber} from "../utils/WindowFromBlockNumber.sol"; import {FeePayout} from "../utils/FeePayout.sol"; @@ -14,86 +15,11 @@ import {FeePayout} from "../utils/FeePayout.sol"; /// @notice This contract is for bidder registry and staking. contract BidderRegistry is IBidderRegistry, + BidderRegistryStorage, Ownable2StepUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { - using FeePayout for FeePayout.Tracker; - - /// @dev For improved precision - uint256 constant public PRECISION = 10 ** 25; - uint256 constant public PERCENT = 100 * PRECISION; - - /// @dev Address of the pre-confirmations contract - address public preConfirmationsContract; - - /// @dev Fee percent that would be taken by protocol when provider is slashed - uint16 public feePercent; - - /// @dev Block tracker contract - IBlockTracker public blockTrackerContract; - - /// Struct enabling automatic protocol fee payouts - FeePayout.Tracker public protocolFeeTracker; - - /// @dev Mapping for if bidder is registered - mapping(address => bool) public bidderRegistered; - - // Mapping from bidder addresses and window numbers to their locked funds - mapping(address => mapping(uint256 => uint256)) public lockedFunds; - - // Mapping from bidder addresses and blocks to their used funds - mapping(address => mapping(uint64 => uint256)) public usedFunds; - - /// Mapping from bidder addresses and window numbers to their funds per window - mapping(address => mapping(uint256 => uint256)) public maxBidPerBlock; - - /// @dev Mapping from bidder addresses to their locked amount based on bidID (commitmentDigest) - mapping(bytes32 => BidState) public bidPayment; - - /// @dev Amount assigned to bidders - mapping(address => uint256) public providerAmount; - - /// @dev Amount assigned to bidders - uint256 public blocksPerWindow; - - /// @dev Event emitted when a bidder is registered with their deposited amount - event BidderRegistered( - address indexed bidder, - uint256 indexed depositedAmount, - uint256 indexed windowNumber - ); - - /// @dev Event emitted when funds are retrieved from a bidder's deposit - event FundsRetrieved( - bytes32 indexed commitmentDigest, - address indexed bidder, - uint256 indexed window, - uint256 amount - ); - - /// @dev Event emitted when funds are retrieved from a bidder's deposit - event FundsRewarded( - bytes32 indexed commitmentDigest, - address indexed bidder, - address indexed provider, - uint256 window, - uint256 amount - ); - - /// @dev Event emitted when a bidder withdraws their deposit - event BidderWithdrawal( - address indexed bidder, - uint256 indexed window, - uint256 indexed amount - ); - - /// @dev Event emitted when the protocol fee recipient is updated - event ProtocolFeeRecipientUpdated(address indexed newProtocolFeeRecipient); - - /// @dev Event emitted when the fee payout period in blocks is updated - event FeePayoutPeriodBlocksUpdated(uint256 indexed newFeePayoutPeriodBlocks); - /** * @dev Modifier to restrict a function to only be callable by the pre-confirmations contract. */ diff --git a/contracts/contracts/core/BidderRegistryStorage.sol b/contracts/contracts/core/BidderRegistryStorage.sol new file mode 100644 index 000000000..f6963a20b --- /dev/null +++ b/contracts/contracts/core/BidderRegistryStorage.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: BSL 1.1 +pragma solidity 0.8.20; + +import {FeePayout} from "../utils/FeePayout.sol"; +import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; +import {IBidderRegistry} from "../interfaces/IBidderRegistry.sol"; + +abstract contract BidderRegistryStorage { + using FeePayout for FeePayout.Tracker; + + /// @dev For improved precision + uint256 constant public PRECISION = 10 ** 25; + uint256 constant public PERCENT = 100 * PRECISION; + + /// @dev Address of the pre-confirmations contract + address public preConfirmationsContract; + + /// @dev Fee percent that would be taken by protocol when provider is slashed + uint16 public feePercent; + + /// @dev Block tracker contract + IBlockTracker public blockTrackerContract; + + /// Struct enabling automatic protocol fee payouts + FeePayout.Tracker public protocolFeeTracker; + + /// @dev Mapping for if bidder is registered + mapping(address => bool) public bidderRegistered; + + // Mapping from bidder addresses and window numbers to their locked funds + mapping(address => mapping(uint256 => uint256)) public lockedFunds; + + // Mapping from bidder addresses and blocks to their used funds + mapping(address => mapping(uint64 => uint256)) public usedFunds; + + /// Mapping from bidder addresses and window numbers to their funds per window + mapping(address => mapping(uint256 => uint256)) public maxBidPerBlock; + + /// @dev Mapping from bidder addresses to their locked amount based on bidID (commitmentDigest) + mapping(bytes32 => IBidderRegistry.BidState) public bidPayment; + + /// @dev Amount assigned to bidders + mapping(address => uint256) public providerAmount; + + /// @dev Amount assigned to bidders + uint256 public blocksPerWindow; +} diff --git a/contracts/contracts/core/BlockTracker.sol b/contracts/contracts/core/BlockTracker.sol index 018a12ff5..907a5f0e8 100644 --- a/contracts/contracts/core/BlockTracker.sol +++ b/contracts/contracts/core/BlockTracker.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: BSL 1.1 pragma solidity 0.8.20; +import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; +import {BlockTrackerStorage} from "./BlockTrackerStorage.sol"; import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; @@ -9,19 +11,7 @@ import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; * @title BlockTracker * @dev A contract that tracks Ethereum blocks and their winners. */ -contract BlockTracker is IBlockTracker, Ownable2StepUpgradeable, UUPSUpgradeable { - - /// @dev Permissioned address of the oracle account. - address public oracleAccount; - - uint256 public currentWindow; - uint256 public blocksPerWindow; - - // Mapping from block number to the winner's address - mapping(uint256 => address) public blockWinners; - - /// @dev Maps builder names to their respective Ethereum addresses. - mapping(string => address) public blockBuilderNameToAddress; +contract BlockTracker is IBlockTracker, BlockTrackerStorage, Ownable2StepUpgradeable, UUPSUpgradeable { /// @dev Modifier to ensure that the sender is the oracle account. modifier onlyOracle() { diff --git a/contracts/contracts/core/BlockTrackerStorage.sol b/contracts/contracts/core/BlockTrackerStorage.sol new file mode 100644 index 000000000..389bd8a2a --- /dev/null +++ b/contracts/contracts/core/BlockTrackerStorage.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSL 1.1 +pragma solidity 0.8.20; + +abstract contract BlockTrackerStorage { + /// @dev Permissioned address of the oracle account. + address public oracleAccount; + + uint256 public currentWindow; + + uint256 public blocksPerWindow; + + // Mapping from block number to the winner's address + mapping(uint256 => address) public blockWinners; + + /// @dev Maps builder names to their respective Ethereum addresses. + mapping(string => address) public blockBuilderNameToAddress; +} diff --git a/contracts/contracts/core/Oracle.sol b/contracts/contracts/core/Oracle.sol index 3b96e4f30..736c476a1 100644 --- a/contracts/contracts/core/Oracle.sol +++ b/contracts/contracts/core/Oracle.sol @@ -5,36 +5,16 @@ import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/acces import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {IPreconfManager} from "../interfaces/IPreconfManager.sol"; import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; - -/// @title Oracle Contract -/// @author Kartik Chopra -/// @notice This contract is for settling commitments made by providers. +import {OracleStorage} from "./OracleStorage.sol"; +import {IOracle} from "../interfaces/IOracle.sol"; /** - * @title Oracle - A contract for Fetching L1 Block Builder Info and Block Data. + * @title Oracle + * @notice A contract for Fetching L1 Block Builder Info and Block Data. + * @author Kartik Chopra * @dev This contract serves as an oracle to fetch and process Ethereum Layer 1 block data. */ -contract Oracle is Ownable2StepUpgradeable, UUPSUpgradeable { - /// @dev Maps builder names to their respective Ethereum addresses. - mapping(string => address) public blockBuilderNameToAddress; - - /// @dev Permissioned address of the oracle account. - address public oracleAccount; - - /// @dev Reference to the PreconfManager contract interface. - IPreconfManager private _preConfContract; - - /// @dev Reference to the BlockTracker contract interface. - IBlockTracker private _blockTrackerContract; - - /// @dev Event emitted when the oracle account is set. - event OracleAccountSet( - address indexed oldOracleAccount, - address indexed newOracleAccount - ); - - /// @dev Event emitted when a commitment is processed. - event CommitmentProcessed(bytes32 indexed commitmentIndex, bool isSlash); +contract Oracle is OracleStorage, IOracle, Ownable2StepUpgradeable, UUPSUpgradeable { /// @dev Modifier to ensure that the sender is the oracle account. modifier onlyOracle() { diff --git a/contracts/contracts/core/OracleStorage.sol b/contracts/contracts/core/OracleStorage.sol new file mode 100644 index 000000000..e977d18b9 --- /dev/null +++ b/contracts/contracts/core/OracleStorage.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSL 1.1 +pragma solidity 0.8.20; + +import {IPreconfManager} from "../interfaces/IPreconfManager.sol"; +import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; + +abstract contract OracleStorage { + /// @dev Maps builder names to their respective Ethereum addresses. + mapping(string => address) public blockBuilderNameToAddress; + + /// @dev Permissioned address of the oracle account. + address public oracleAccount; + + /// @dev Reference to the PreconfManager contract interface. + IPreconfManager internal _preConfContract; + + /// @dev Reference to the BlockTracker contract interface. + IBlockTracker internal _blockTrackerContract; +} diff --git a/contracts/contracts/core/PreconfManager.sol b/contracts/contracts/core/PreconfManager.sol index 2238a3790..b3e7093dc 100644 --- a/contracts/contracts/core/PreconfManager.sol +++ b/contracts/contracts/core/PreconfManager.sol @@ -8,6 +8,7 @@ import {IProviderRegistry} from "../interfaces/IProviderRegistry.sol"; import {IBidderRegistry} from "../interfaces/IBidderRegistry.sol"; import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; import {IPreconfManager} from "../interfaces/IPreconfManager.sol"; +import {PreconfManagerStorage} from "./PreconfManagerStorage.sol"; import {WindowFromBlockNumber} from "../utils/WindowFromBlockNumber.sol"; /** @@ -16,6 +17,7 @@ import {WindowFromBlockNumber} from "../utils/WindowFromBlockNumber.sol"; */ contract PreconfManager is IPreconfManager, + PreconfManagerStorage, Ownable2StepUpgradeable, UUPSUpgradeable { @@ -56,35 +58,6 @@ contract PreconfManager is // Hex characters bytes public constant HEXCHARS = "0123456789abcdef"; - // Represents the dispatch window in milliseconds - uint64 public commitmentDispatchWindow; - - /// @dev Address of the oracle contract - address public oracleContract; - - /// @dev The number of blocks per window - uint256 public blocksPerWindow; - - /// @dev Address of provider registry - IProviderRegistry public providerRegistry; - - /// @dev Address of bidderRegistry - IBidderRegistry public bidderRegistry; - - /// @dev Address of blockTracker - IBlockTracker public blockTracker; - - /// @dev Mapping from provider to commitments count - mapping(address => uint256) public commitmentsCount; - - /// @dev Commitment Hash -> Opened Commitemnt - /// @dev Only stores valid commitments - mapping(bytes32 => OpenedCommitment) public openedCommitments; - - /// @dev Unopened Commitment Hash -> Unopened Commitment - /// @dev Only stores valid unopened commitments - mapping(bytes32 => UnopenedCommitment) public unopenedCommitments; - /** * @dev Makes sure transaction sender is oracle contract */ diff --git a/contracts/contracts/core/PreconfManagerStorage.sol b/contracts/contracts/core/PreconfManagerStorage.sol new file mode 100644 index 000000000..8ddee876d --- /dev/null +++ b/contracts/contracts/core/PreconfManagerStorage.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSL 1.1 +pragma solidity 0.8.20; + +import {IProviderRegistry} from "../interfaces/IProviderRegistry.sol"; +import {IBidderRegistry} from "../interfaces/IBidderRegistry.sol"; +import {IBlockTracker} from "../interfaces/IBlockTracker.sol"; +import {IPreconfManager} from "../interfaces/IPreconfManager.sol"; + +abstract contract PreconfManagerStorage { + // Represents the dispatch window in milliseconds + uint64 public commitmentDispatchWindow; + + /// @dev Address of the oracle contract + address public oracleContract; + + /// @dev The number of blocks per window + uint256 public blocksPerWindow; + + /// @dev Address of provider registry + IProviderRegistry public providerRegistry; + + /// @dev Address of bidderRegistry + IBidderRegistry public bidderRegistry; + + /// @dev Address of blockTracker + IBlockTracker public blockTracker; + + /// @dev Mapping from provider to commitments count + mapping(address => uint256) public commitmentsCount; + + /// @dev Commitment Hash -> Opened Commitemnt + /// @dev Only stores valid commitments + mapping(bytes32 => IPreconfManager.OpenedCommitment) public openedCommitments; + + /// @dev Unopened Commitment Hash -> Unopened Commitment + /// @dev Only stores valid unopened commitments + mapping(bytes32 => IPreconfManager.UnopenedCommitment) public unopenedCommitments; +} diff --git a/contracts/contracts/core/ProviderRegistry.sol b/contracts/contracts/core/ProviderRegistry.sol index e25ecce74..1cfa28303 100644 --- a/contracts/contracts/core/ProviderRegistry.sol +++ b/contracts/contracts/core/ProviderRegistry.sol @@ -6,6 +6,7 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import {PreconfManager} from "./PreconfManager.sol"; import {IProviderRegistry} from "../interfaces/IProviderRegistry.sol"; +import {ProviderRegistryStorage} from "./ProviderRegistryStorage.sol"; import {FeePayout} from "../utils/FeePayout.sol"; /// @title Provider Registry @@ -13,67 +14,11 @@ import {FeePayout} from "../utils/FeePayout.sol"; /// @notice This contract is for provider registry and staking. contract ProviderRegistry is IProviderRegistry, + ProviderRegistryStorage, Ownable2StepUpgradeable, UUPSUpgradeable, ReentrancyGuardUpgradeable { - using FeePayout for FeePayout.Tracker; - - /// @dev For improved precision - uint256 public constant PRECISION = 10 ** 25; - uint256 public constant PERCENT = 100 * PRECISION; - - /// @dev Minimum stake required for registration - uint256 public minStake; - - /// @dev Address of the pre-confirmations contract - address public preConfirmationsContract; - - /// @dev Fee percent that would be taken by protocol when provider is slashed - uint16 public feePercent; - - /// @dev Configurable withdrawal delay in milliseconds - uint256 public withdrawalDelay; - - /// Struct enabling automatic penalty fee payouts - FeePayout.Tracker public penaltyFeeTracker; - - /// @dev Mapping from provider address to whether they are registered or not - mapping(address => bool) public providerRegistered; - - /// @dev Mapping from a provider's EOA address to their BLS public key - mapping(address => bytes) public eoaToBlsPubkey; - - /// @dev Mapping from provider addresses to their staked amount - mapping(address => uint256) public providerStakes; - - /// @dev Mapping of provider to withdrawal request timestamp - mapping(address => uint256) public withdrawalRequests; - - /// @dev Event emitted when a provider is registered - event ProviderRegistered(address indexed provider, uint256 stakedAmount, bytes blsPublicKey); - - /// @dev Event emitted when funds are deposited - event FundsDeposited(address indexed provider, uint256 amount); - - /// @dev Event emitted when funds are slashed - event FundsSlashed(address indexed provider, uint256 amount); - - /// @dev Event emitted when withdrawal is requested - event Unstake(address indexed provider, uint256 timestamp); - - /// @dev Event emitted when withdrawal is completed - event Withdraw(address indexed provider, uint256 amount); - - /// @dev Event emitted when the withdrawal delay is updated - event WithdrawalDelayUpdated(uint256 newWithdrawalDelay); - - /// @dev Event emitted when the penalty fee recipient is updated - event PenaltyFeeRecipientUpdated(address indexed newPenaltyFeeRecipient); - - /// @dev Event emitted when the fee payout period in blocks is updated - event FeePayoutPeriodBlocksUpdated(uint256 indexed newFeePayoutPeriodBlocks); - /** * @dev Modifier to restrict a function to only be callable by the pre-confirmations contract. */ diff --git a/contracts/contracts/core/ProviderRegistryStorage.sol b/contracts/contracts/core/ProviderRegistryStorage.sol new file mode 100644 index 000000000..d556dec99 --- /dev/null +++ b/contracts/contracts/core/ProviderRegistryStorage.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSL 1.1 +pragma solidity 0.8.20; + +import {FeePayout} from "../utils/FeePayout.sol"; + +abstract contract ProviderRegistryStorage { + using FeePayout for FeePayout.Tracker; + + /// @dev For improved precision + uint256 public constant PRECISION = 10 ** 25; + uint256 public constant PERCENT = 100 * PRECISION; + + /// @dev Minimum stake required for registration + uint256 public minStake; + + /// @dev Address of the pre-confirmations contract + address public preConfirmationsContract; + + /// @dev Fee percent that would be taken by protocol when provider is slashed + uint16 public feePercent; + + /// @dev Configurable withdrawal delay in milliseconds + uint256 public withdrawalDelay; + + /// Struct enabling automatic penalty fee payouts + FeePayout.Tracker public penaltyFeeTracker; + + /// @dev Mapping from provider address to whether they are registered or not + mapping(address => bool) public providerRegistered; + + /// @dev Mapping from a provider's EOA address to their BLS public key + mapping(address => bytes) public eoaToBlsPubkey; + + /// @dev Mapping from provider addresses to their staked amount + mapping(address => uint256) public providerStakes; + + /// @dev Mapping of provider to withdrawal request timestamp + mapping(address => uint256) public withdrawalRequests; +} diff --git a/contracts/contracts/interfaces/IBidderRegistry.sol b/contracts/contracts/interfaces/IBidderRegistry.sol index 2f9edc97c..c1feea902 100644 --- a/contracts/contracts/interfaces/IBidderRegistry.sol +++ b/contracts/contracts/interfaces/IBidderRegistry.sol @@ -24,6 +24,43 @@ interface IBidderRegistry { Withdrawn } + /// @dev Event emitted when a bidder is registered with their deposited amount + event BidderRegistered( + address indexed bidder, + uint256 indexed depositedAmount, + uint256 indexed windowNumber + ); + + /// @dev Event emitted when funds are retrieved from a bidder's deposit + event FundsRetrieved( + bytes32 indexed commitmentDigest, + address indexed bidder, + uint256 indexed window, + uint256 amount + ); + + /// @dev Event emitted when funds are retrieved from a bidder's deposit + event FundsRewarded( + bytes32 indexed commitmentDigest, + address indexed bidder, + address indexed provider, + uint256 window, + uint256 amount + ); + + /// @dev Event emitted when a bidder withdraws their deposit + event BidderWithdrawal( + address indexed bidder, + uint256 indexed window, + uint256 indexed amount + ); + + /// @dev Event emitted when the protocol fee recipient is updated + event ProtocolFeeRecipientUpdated(address indexed newProtocolFeeRecipient); + + /// @dev Event emitted when the fee payout period in blocks is updated + event FeePayoutPeriodBlocksUpdated(uint256 indexed newFeePayoutPeriodBlocks); + function openBid( bytes32 commitmentDigest, uint256 bid, diff --git a/contracts/contracts/interfaces/IOracle.sol b/contracts/contracts/interfaces/IOracle.sol new file mode 100644 index 000000000..831e6b1fd --- /dev/null +++ b/contracts/contracts/interfaces/IOracle.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL 1.1 +pragma solidity 0.8.20; + +interface IOracle { + + /// @dev Event emitted when the oracle account is set. + event OracleAccountSet( + address indexed oldOracleAccount, + address indexed newOracleAccount + ); + + /// @dev Event emitted when a commitment is processed. + event CommitmentProcessed(bytes32 indexed commitmentIndex, bool isSlash); + + receive() external payable; + + fallback() external payable; + + function initialize( + address preConfContract_, + address blockTrackerContract_, + address oracleAccount_, + address owner_ + ) external; + + function processBuilderCommitmentForBlockNumber( + bytes32 commitmentIndex, + uint256 blockNumber, + address builder, + bool isSlash, + uint256 residualBidPercentAfterDecay + ) external; + + function setOracleAccount(address newOracleAccount) external; +} diff --git a/contracts/contracts/interfaces/IProviderRegistry.sol b/contracts/contracts/interfaces/IProviderRegistry.sol index 10633139a..11f0fc0b3 100644 --- a/contracts/contracts/interfaces/IProviderRegistry.sol +++ b/contracts/contracts/interfaces/IProviderRegistry.sol @@ -2,6 +2,31 @@ pragma solidity 0.8.20; interface IProviderRegistry { + + /// @dev Event emitted when a provider is registered + event ProviderRegistered(address indexed provider, uint256 stakedAmount, bytes blsPublicKey); + + /// @dev Event emitted when funds are deposited + event FundsDeposited(address indexed provider, uint256 amount); + + /// @dev Event emitted when funds are slashed + event FundsSlashed(address indexed provider, uint256 amount); + + /// @dev Event emitted when withdrawal is requested + event Unstake(address indexed provider, uint256 timestamp); + + /// @dev Event emitted when withdrawal is completed + event Withdraw(address indexed provider, uint256 amount); + + /// @dev Event emitted when the withdrawal delay is updated + event WithdrawalDelayUpdated(uint256 newWithdrawalDelay); + + /// @dev Event emitted when the penalty fee recipient is updated + event PenaltyFeeRecipientUpdated(address indexed newPenaltyFeeRecipient); + + /// @dev Event emitted when the fee payout period in blocks is updated + event FeePayoutPeriodBlocksUpdated(uint256 indexed newFeePayoutPeriodBlocks); + function registerAndStake(bytes calldata blsPublicKey) external payable; function stake() external payable; @@ -14,8 +39,4 @@ interface IProviderRegistry { ) external; function isProviderValid(address committerAddress) external view; - - function minStake() external view returns (uint256); - - function withdrawalRequests(address provider) external view returns (uint256); }