Skip to content

Commit

Permalink
Merge branch 'main' into dkg-cost
Browse files Browse the repository at this point in the history
  • Loading branch information
pdyraga committed Nov 30, 2021
2 parents d88c763 + c1b4274 commit 77b66ee
Show file tree
Hide file tree
Showing 5 changed files with 356 additions and 326 deletions.
107 changes: 72 additions & 35 deletions solidity/random-beacon/contracts/RandomBeacon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,34 @@ contract RandomBeacon is Ownable {
/// operator affected.
uint256 public dkgMaliciousResultNotificationRewardMultiplier;

// External dependencies

SortitionPool public sortitionPool;
IERC20 public tToken;
IRandomBeaconStaking public staking;

// Token bookkeeping

/// @notice Rewards pool for DKG actions. This pool is funded from relay
/// request fees and external donates. Funds are used to cover
/// rewards for actors approving DKG result or notifying about
/// DKG timeout.
uint256 public dkgRewardsPool;
/// @notice Rewards pool for heartbeat notifiers. This pool is funded from
/// external donates. Funds are used to cover rewards for actors
/// notifying about failed heartbeats.
uint256 public heartbeatNotifierRewardsPool;

// Libraries data storages

Authorization.Data internal authorization;
DKG.Data internal dkg;
Groups.Data internal groups;
Relay.Data internal relay;
Callback.Data internal callback;

// Events

event AuthorizationParametersUpdated(
uint96 minimumAuthorization,
uint64 authorizationDecreaseDelay
Expand Down Expand Up @@ -174,8 +191,6 @@ contract RandomBeacon is Ownable {
uint256 maliciousDkgResultSlashingAmount
);

// Events copied from library to workaround issue https://github.com/ethereum/solidity/issues/9765

event DkgStarted(uint256 indexed seed);

event DkgResultSubmitted(
Expand Down Expand Up @@ -251,8 +266,6 @@ contract RandomBeacon is Ownable {

event CallbackFailed(uint256 entry, uint256 entrySubmittedBlock);

event BanRewardsFailed(uint32[] ids);

/// @dev Assigns initial values to parameters to make the beacon work
/// safely. These parameters are just proposed defaults and they might
/// be updated with `update*` functions after the contract deployment
Expand Down Expand Up @@ -550,8 +563,9 @@ contract RandomBeacon is Ownable {
/// reward to the notifier.
function notifyDkgTimeout() external {
dkg.notifyTimeout();
// Pay the sortition pool unlocking reward.
tToken.safeTransfer(msg.sender, sortitionPoolUnlockingReward);

transferDkgRewards(msg.sender, sortitionPoolUnlockingReward);

dkg.complete();
}

Expand All @@ -568,15 +582,13 @@ contract RandomBeacon is Ownable {
function approveDkgResult(DKG.Result calldata dkgResult) external {
uint32[] memory misbehavedMembers = dkg.approveResult(dkgResult);

uint256 maintenancePoolBalance = tToken.balanceOf(address(this));
uint256 rewardToPay = Math.min(
maintenancePoolBalance,
dkgResultSubmissionReward
);
tToken.safeTransfer(msg.sender, rewardToPay);
transferDkgRewards(msg.sender, dkgResultSubmissionReward);

if (misbehavedMembers.length > 0) {
banFromRewards(misbehavedMembers, sortitionPoolRewardsBanDuration);
sortitionPool.banRewards(
misbehavedMembers,
sortitionPoolRewardsBanDuration
);
}

groups.activateCandidateGroup();
Expand Down Expand Up @@ -665,11 +677,7 @@ contract RandomBeacon is Ownable {

relay.requestEntry(groupId);

tToken.safeTransferFrom(
msg.sender,
address(this),
relay.relayRequestFee
);
fundDkgRewardsPool(msg.sender, relay.relayRequestFee);

callback.setCallbackContract(callbackContract);

Expand Down Expand Up @@ -697,12 +705,12 @@ contract RandomBeacon is Ownable {
relay.currentRequest.groupId
);

(uint32[] memory inactiveMembers, uint256 slashingAmount) = relay
.submitEntry(sortitionPool, submitterIndex, entry, group);

if (inactiveMembers.length > 0) {
banFromRewards(inactiveMembers, sortitionPoolRewardsBanDuration);
}
uint256 slashingAmount = relay.submitEntry(
sortitionPool,
submitterIndex,
entry,
group
);

if (slashingAmount > 0) {
address[] memory groupMembers = sortitionPool.getIDOperators(
Expand Down Expand Up @@ -778,17 +786,46 @@ contract RandomBeacon is Ownable {
}
}

/// @notice Ban given operators from sortition pool rewards.
/// @param ids IDs of banned operators.
/// @param banDuration Duration of the ban period in seconds.
function banFromRewards(uint32[] memory ids, uint256 banDuration) internal {
try sortitionPool.banRewards(ids, banDuration) {} catch {
// Should never happen but we want to ensure a non-critical path
// failure from an external contract does not stop group members
// from submitting a valid relay entry.
// slither-disable-next-line reentrancy-events
emit BanRewardsFailed(ids);
}
/// @notice Funds the DKG rewards pool.
/// @param from Address of the funder. The funder must give a sufficient
/// allowance for this contract to make a successful call.
/// @param value Token value transferred by the funder.
function fundDkgRewardsPool(address from, uint256 value) public {
dkgRewardsPool += value;
tToken.safeTransferFrom(from, address(this), value);
}

/// @notice Funds the heartbeat notifier rewards pool.
/// @param from Address of the funder. The funder must give a sufficient
/// allowance for this contract to make a successful call.
/// @param value Token value transferred by the funder.
function fundHeartbeatNotifierRewardsPool(address from, uint256 value)
external
{
heartbeatNotifierRewardsPool += value;
tToken.safeTransferFrom(from, address(this), value);
}

/// @notice Makes a transfer using DKG rewards pool.
/// @param to Address of the recipient.
/// @param value Token value transferred to the recipient.
function transferDkgRewards(address to, uint256 value) internal {
uint256 actualValue = Math.min(dkgRewardsPool, value);
dkgRewardsPool -= actualValue;
tToken.safeTransfer(to, actualValue);
}

/// @notice Makes a transfer using heartbeat notifier rewards pool.
/// @param to Address of the recipient.
/// @param value Token value transferred to the recipient.
// TODO: Remove Slither ignore condition once this function is used.
// slither-disable-next-line dead-code
function transferHeartbeatNotifierRewards(address to, uint256 value)
internal
{
uint256 actualValue = Math.min(heartbeatNotifierRewardsPool, value);
heartbeatNotifierRewardsPool -= actualValue;
tToken.safeTransfer(to, actualValue);
}

/// @notice Locks the state of group creation.
Expand Down
36 changes: 2 additions & 34 deletions solidity/random-beacon/contracts/libraries/Relay.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,6 @@ library Relay {
/// @param submitterIndex Index of the entry submitter.
/// @param entry Group BLS signature over the previous entry.
/// @param group Group data.
/// @return inactiveMembers Array of members IDs which should be considered
/// inactive for not submitting relay entry on their turn.
/// The array is empty if none of the members missed their turn.
/// @return slashingAmount Amount by which group members should be slashed
/// in case the relay entry was submitted after the soft timeout.
/// The value is zero if entry was submitted on time.
Expand All @@ -125,10 +122,7 @@ library Relay {
uint256 submitterIndex,
bytes calldata entry,
Groups.Group memory group
)
internal
returns (uint32[] memory inactiveMembers, uint256 slashingAmount)
{
) internal returns (uint256 slashingAmount) {
require(isRequestInProgress(self), "No relay request in progress");
require(!hasRequestTimedOut(self), "Relay request timed out");

Expand All @@ -144,37 +138,11 @@ library Relay {
"Unexpected submitter index"
);

(uint256 firstEligibleIndex, uint256 lastEligibleIndex) = Submission
.getEligibilityRange(
uint256(keccak256(entry)),
block.number,
self.currentRequest.startBlock,
self.relayEntrySubmissionEligibilityDelay,
groupSize
);

require(
Submission.isEligible(
submitterIndex,
firstEligibleIndex,
lastEligibleIndex
),
"Submitter is not eligible"
);

require(
BLS.verify(group.groupPubKey, self.previousEntry, entry),
"Invalid entry"
);

// Get the list of members IDs which should be considered inactive due
// to not submitting the entry on their turn.
inactiveMembers = Submission.getInactiveMembers(
submitterIndex,
firstEligibleIndex,
group.members
);

// If the soft timeout has been exceeded apply stake slashing for
// all group members. Note that `getSlashingFactor` returns the
// factor multiplied by 1e18 to avoid precision loss. In that case
Expand All @@ -189,7 +157,7 @@ library Relay {

emit RelayEntrySubmitted(self.requestCount, entry);

return (inactiveMembers, slashingAmount);
return slashingAmount;
}

/// @notice Set relayRequestFee parameter.
Expand Down
2 changes: 1 addition & 1 deletion solidity/random-beacon/contracts/libraries/Submission.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ library Submission {
/// @param submitterIndex Index of the submitter.
/// @param firstEligibleIndex First index of the given eligibility range.
/// @param groupMembers IDs of the group members.
/// @return An array of members IDs which should be inactive due
/// @return An array of members IDs which should be considered inactive due
/// to not submitting on their turn.
function getInactiveMembers(
uint256 submitterIndex,
Expand Down
Loading

0 comments on commit 77b66ee

Please sign in to comment.