Skip to content

Commit

Permalink
feat(Profile): allow change consensus address (#236)
Browse files Browse the repository at this point in the history
* restructure

* add profile contract

* add storage log

* fix staking test

* fix fixture

* Revert "fix fixture"

This reverts commit f53277e.

* fix hardhat deploy path

* fix deploy script

* rollback initializerV1

* restructure profile contract

* fix fixture

* fix dependent test

* fix dependent test

* fix: profile execApply

* fix hardhat deploy src path

* rollback NON_VALIDATOR slash type

* follow new code convention

* feat: support change admin address

* fix: inheritance graph

* fix: fix test setup

* add dev comment

* fix rebase issue

* rename for convention

* add enum for custom error

* udvt TPoolId

* Revert "udvt TPoolId"

This reverts commit 0f2c107.

* distinguish poolId vs consensus

* declare TPoolId type

* remove mockup contract

* remove bridge operator change method

* rename interface param

* remove comment

* refactor

* revert casting in coinbase

* Remove TPoolId. Using TConsensus.

* fix test

* remove public vars

* remove more public vars

* remove redundant code

* wrap all external method to TConsensus type

* fix config

* fix test init

* fix mock

* fix test

* fix test

* add comment

* fix helper

* restructure

* fix edge case

* fix conventions

* add docs

* fix: foundry config

* chore: fix conventions

* fix: remove bridge voter

* fix: change inheritance tree

* Merge branch 'feat/fast-finality' into feat/profile

* fix: fix test setup

* Merge branch 'feat/bridge-admin-rebase' into feat/profile

* fix test after merging

* chore: add TODO tag

* tmp disable forge test

* fix fixture

* update ci

* Continue merge branch 'testnet' into feat/profile

* fix test setup

* fix more test setup

* fix test

* fix test & improve conf test

* refactor initializer

* apply initializer for test suites

* fix fast finality test

* fix initializers

* chore: resolve conflict

* feat(Profile): remove unused method, fix execApplyCandidate

* feat(Profile, Staking): require pubkey at apply candidate, fix init test

* test(Profile): fix other dependent tests

* chore: fix test

* feat(ValidatorSet): recover slot shifted

* fix(Profile): cherry-pick fix from 'test/feat/profile'

* fix(SlashFastFinality): fix wrapper for consensus

* chore: resolve low-level call warning

* temp(*): rename to cid, pid, _shadowed**

* feat(ValidatorSet): cached admin

* feat(Profile, ValidatorSet): handle execChangeAdminAddress

* feat(Staking): rename admin to `__shadowPoolAdmin`

* feat(Profile): handle change treasury, fix missing rename

* chore(Validator): rename to *ById suffix

* chore: rename `_convert*C2P`

* chore(Validator): remove old version contract

* chore(docs): write natspecs doc for struct

* chore(*): remove `_` for consistent var names

* chore(docs): NatSpecs for __css2cid

* chore: remove compiler warning

* feat(TrustedOrg): handle change consensus for Trusted Org

* feat(SlashIndicator): remove code related to bridge

* chore: clean up PR, remove unrelated files

* fix(Staking): fix inaccurate shifted gap

* chore(ValidatorSet): consist interface

* chore(ValidatorSet, Staking): move callbacks to separate files

* chore(ValidatorSet): refactor callbacks

* chore: remove log

* fix(TrustedOrg): remove onlyAdmin in initV2, fix test

* test: fix test after restrict not allowing rejoin in Profile

* test: fix more test

* feat(RoninTO): fix bug when change consensus in RoninTO

* chore: fix rebase issue

* fix(RoninTO): delete deprecated storage

* chore: rename consensus to cid

* fix(GovernanceAdmin): fix emergency exit typehash

* test(*): fix deprecated voter for test setup

* feat(RoninTO): return address(0) for bridge voter

* chore: fix typo

* chore: fix deprecatedVoter in test

* feat(RoninTO): rename for consistency

* feat(Validator): better handling emergency exit revert

* feat(EmergencyExit): revert to original typehash

* fix(Profile); rename check to require

* feat: migrate registry for renounced candidates

* feat(Profile): fix migration

* chore: fix test setup

* config: enable literal content for RoninValidatorSet deployment
  • Loading branch information
nxqbao authored Nov 27, 2023
1 parent e30e4f7 commit 1cafa6a
Show file tree
Hide file tree
Showing 114 changed files with 6,755 additions and 2,780 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unittest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- "release/**"
pull_request:
branches:
- main
- mainnet
- testnet
- "release/**"

Expand Down
34 changes: 17 additions & 17 deletions contracts/extensions/forwarder/Forwarder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@ contract Forwarder is AccessControlEnumerable {
/**
* @dev Initializes the forwarder with an initial target address and a contract admin.
*/
constructor(address[] memory _targets, address _admin, address _moderator) payable {
for (uint _i = 0; _i < _targets.length; ) {
_setupRole(TARGET_ROLE, _targets[_i]);
constructor(address[] memory targets, address admin, address moderator) payable {
for (uint i = 0; i < targets.length; ) {
_setupRole(TARGET_ROLE, targets[i]);

unchecked {
++_i;
++i;
}
}
_setupRole(DEFAULT_ADMIN_ROLE, _admin);
_setupRole(MODERATOR_ROLE, _moderator);
_setupRole(DEFAULT_ADMIN_ROLE, admin);
_setupRole(MODERATOR_ROLE, moderator);
}

modifier validTarget(address _target) {
_checkRole(TARGET_ROLE, _target);
modifier validTarget(address target) {
_checkRole(TARGET_ROLE, target);
_;
}

Expand All @@ -61,21 +61,21 @@ contract Forwarder is AccessControlEnumerable {
* - Only user with {MODERATOR_ROLE} can call this method.
*/
function functionCall(
address _target,
bytes memory _data,
uint256 _val
) external payable validTarget(_target) onlyRole(MODERATOR_ROLE) {
if (_val > address(this).balance) revert ErrInvalidForwardValue();
_call(_target, _data, _val);
address target,
bytes memory data,
uint256 val
) external payable validTarget(target) onlyRole(MODERATOR_ROLE) {
if (val > address(this).balance) revert ErrInvalidForwardValue();
_call(target, data, val);
}

/**
* @dev Forwards the current call to `target`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _call(address _target, bytes memory _data, uint256 _value) internal {
(bool _success, bytes memory _res) = _target.call{ value: _value }(_data);
_success.handleRevert(bytes4(_data), _res);
function _call(address target, bytes memory data, uint256 value) internal {
(bool success, bytes memory res) = target.call{ value: value }(data);
success.handleRevert(bytes4(data), res);
}
}
90 changes: 58 additions & 32 deletions contracts/interfaces/IMaintenance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

pragma solidity ^0.8.9;

import { TConsensus } from "../udvts/Types.sol";

interface IMaintenance {
/**
* @dev Error thrown when attempting to schedule an already scheduled event.
Expand Down Expand Up @@ -61,9 +63,9 @@ interface IMaintenance {
}

/// @dev Emitted when a maintenance is scheduled.
event MaintenanceScheduled(address indexed consensusAddr, Schedule);
event MaintenanceScheduled(TConsensus indexed consensusAddr, Schedule);
/// @dev Emitted when a schedule of maintenance is cancelled.
event MaintenanceScheduleCancelled(address indexed consensusAddr);
event MaintenanceScheduleCancelled(TConsensus indexed consensusAddr);
/// @dev Emitted when the maintenance config is updated.
event MaintenanceConfigUpdated(
uint256 minMaintenanceDurationInBlock,
Expand All @@ -75,52 +77,76 @@ interface IMaintenance {
);

/**
* @dev Returns whether the validator `_consensusAddr` maintained at the block number `_block`.
* @dev Returns whether the validator `consensusAddr` maintained at the block number `_block`.
*/
function checkMaintained(TConsensus consensusAddr, uint256 _block) external view returns (bool);

/**
* @dev Returns whether the validator whose id `validatorId` maintained at the block number `_block`.
*/
function checkMaintained(address _consensusAddr, uint256 _block) external view returns (bool);
function checkMaintainedById(address validatorId, uint256 _block) external view returns (bool);

/**
* @dev Returns whether the validator `_consensusAddr` maintained in the inclusive range [`_fromBlock`, `_toBlock`] of blocks.
* @dev Returns whether the validator `consensusAddr` maintained in the inclusive range [`_fromBlock`, `_toBlock`] of blocks.
*/
function checkMaintainedInBlockRange(
address _consensusAddr,
TConsensus consensusAddr,
uint256 _fromBlock,
uint256 _toBlock
) external view returns (bool);

/**
* @dev Returns the bool array indicating the validators maintained at block number `_block` or not.
* @dev Returns the bool array indicating the validators maintained at block number `k` or not.
*/
function checkManyMaintained(address[] calldata _addrList, uint256 _block) external view returns (bool[] memory);
function checkManyMaintained(
TConsensus[] calldata consensusAddrList,
uint256 atBlock
) external view returns (bool[] memory);

function checkManyMaintainedById(
address[] calldata candidateIdList,
uint256 atBlock
) external view returns (bool[] memory);

/**
* @dev Returns a bool array indicating the validators maintained in the inclusive range [`_fromBlock`, `_toBlock`] of blocks or not.
*/
function checkManyMaintainedInBlockRange(
address[] calldata _addrList,
TConsensus[] calldata _consensusAddrList,
uint256 _fromBlock,
uint256 _toBlock
) external view returns (bool[] memory);

function checkManyMaintainedInBlockRangeById(
address[] calldata idList,
uint256 fromBlock,
uint256 toBlock
) external view returns (bool[] memory);

/**
* @dev Returns whether the validator `_consensusAddr` has scheduled.
* @dev Returns whether the validator `consensusAddr` has finished cooldown.
*/
function checkScheduled(address _consensusAddr) external view returns (bool);
function checkCooldownEnded(TConsensus consensusAddr) external view returns (bool);

/**
* @dev Returns whether the validator `_consensusAddr`
* @dev Returns whether the validator `consensusAddr` has schedule.
*/
function checkCooldownEnded(address _consensusAddr) external view returns (bool);
function checkScheduled(TConsensus consensusAddr) external view returns (bool);

/**
* @dev Returns the detailed schedule of the validator `_consensusAddr`.
* @dev Returns the detailed schedule of the validator `consensusAddr`.
*/
function getSchedule(address _consensusAddr) external view returns (Schedule memory);
function getSchedule(TConsensus consensusAddr) external view returns (Schedule memory);

/**
* @dev Returns the total of current schedules.
*/
function totalSchedule() external view returns (uint256 _count);
function totalSchedule() external view returns (uint256 count);

/**
* @dev Returns the cooldown to maintain in seconds.
*/
function cooldownSecsToMaintain() external view returns (uint256);

/**
* @dev Sets the duration restriction, start time restriction, and max allowed for maintenance.
Expand All @@ -134,12 +160,12 @@ interface IMaintenance {
*
*/
function setMaintenanceConfig(
uint256 _minMaintenanceDurationInBlock,
uint256 _maxMaintenanceDurationInBlock,
uint256 _minOffsetToStartSchedule,
uint256 _maxOffsetToStartSchedule,
uint256 _maxSchedules,
uint256 _cooldownSecsToMaintain
uint256 minMaintenanceDurationInBlock_,
uint256 maxMaintenanceDurationInBlock_,
uint256 minOffsetToStartSchedule_,
uint256 maxOffsetToStartSchedule_,
uint256 maxSchedules_,
uint256 cooldownSecsToMaintain_
) external;

/**
Expand Down Expand Up @@ -168,12 +194,12 @@ interface IMaintenance {
function maxSchedule() external view returns (uint256);

/**
* @dev Schedules for maintenance from `_startedAtBlock` to `_startedAtBlock`.
* @dev Schedules for maintenance from `startedAtBlock` to `endedAtBlock`.
*
* Requirements:
* - The candidate `_consensusAddr` is the block producer.
* - The method caller is candidate admin of the candidate `_consensusAddr`.
* - The candidate `_consensusAddr` has no schedule yet or the previous is done.
* - The candidate `consensusAddr` is the block producer.
* - The method caller is candidate admin of the candidate `consensusAddr`.
* - The candidate `consensusAddr` has no schedule yet or the previous is done.
* - The total number of schedules is not larger than `maxSchedules()`.
* - The start block must be at least `minOffsetToStartSchedule()` and at most `maxOffsetToStartSchedule()` blocks from the current block.
* - The end block is larger than the start block.
Expand All @@ -184,17 +210,17 @@ interface IMaintenance {
* Emits the event `MaintenanceScheduled`.
*
*/
function schedule(address _consensusAddr, uint256 _startedAtBlock, uint256 _endedAtBlock) external;
function schedule(TConsensus consensusAddr, uint256 startedAtBlock, uint256 endedAtBlock) external;

/**
* @dev Cancel the schedule of maintenance for the `_consensusAddr`.
* @dev Cancel the schedule of maintenance for the `consensusAddr`.
*
* Requirements:
* - The candidate `_consensusAddr` is the block producer.
* - The method caller is candidate admin of the candidate `_consensusAddr`.
* - A schedule for the `_consensusAddr` must be existent and not executed yet.
* - The candidate `consensusAddr` is the block producer.
* - The method caller is candidate admin of the candidate `consensusAddr`.
* - A schedule for the `consensusAddr` must be existent and not executed yet.
*
* Emits the event `MaintenanceScheduleCancelled`.
*/
function cancelSchedule(address _consensusAddr) external;
function cancelSchedule(TConsensus consensusAddr) external;
}
44 changes: 37 additions & 7 deletions contracts/interfaces/IProfile.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

pragma solidity ^0.8.9;

import { TPoolId, TConsensus } from "../udvts/Types.sol";
import "../utils/RoleAccess.sol";

interface IProfile {
Expand All @@ -15,13 +16,13 @@ interface IProfile {
*/
address id;
/// @dev Consensus address.
address consensus;
TConsensus consensus;
/// @dev Pool admin address.
address admin;
/// @dev Treasury address.
address payable treasury;
/// @dev Address to voting proposal.
address governor;
address __reservedGovernor;
/// @dev Public key for fast finality.
bytes pubkey;
}
Expand Down Expand Up @@ -51,6 +52,15 @@ interface IProfile {
/// @dev Getter to query full `profile` from `id` address.
function getId2Profile(address id) external view returns (CandidateProfile memory profile);

/// @dev Getter to batch query from `id` to `consensus`, return address(0) if the profile not exist.
function getManyId2Consensus(address[] calldata idList) external view returns (TConsensus[] memory consensusList);

/// @dev Getter to backward query from `consensus` address to `id` address.
function getConsensus2Id(TConsensus consensus) external view returns (address id);

/// @dev Getter to backward batch query from `consensus` address to `id` address.
function getManyConsensus2Id(TConsensus[] memory consensus) external view returns (address[] memory);

/**
* @notice Add a new profile.
*
Expand All @@ -61,14 +71,34 @@ interface IProfile {
function addNewProfile(CandidateProfile memory profile) external;

/**
* @notice The candidate admin registers a new profile.
* @dev Cross-contract function to add/update new profile of a validator candidate when they
* applying for candidate role.
*
* @dev Requirements:
* - The profile must not be existent before.
* - Only user with candidate admin role can call this method.
* Requirements:
* - Only `stakingContract` can call this method.
*/
function execApplyValidatorCandidate(address admin, address id, address treasury, bytes calldata pubkey) external;

function registerProfile(CandidateProfile memory profile) external;
/**
* @dev Updated the treasury address of candidate id `id` immediately without waiting time.
*
* Emit an {ProfileAddressChanged}.
*/
function requestChangeAdminAddress(address id, address newAdminAddr) external;

/**
* @dev Updated the treasury address of candidate id `id` immediately without waiting time.
*
* Emit an {ProfileAddressChanged}.
*/
function requestChangeConsensusAddr(address id, TConsensus newConsensusAddr) external;

/**
* @dev Updated the treasury address of candidate id `id` immediately without waiting time.
*
* Emit an {ProfileAddressChanged}.
*/
function requestChangeTreasuryAddr(address id, address payable newTreasury) external;

/**
* @notice The candidate admin changes the public key.
Expand Down
24 changes: 12 additions & 12 deletions contracts/interfaces/IRoninGovernanceAdmin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ import "../utils/CommonErrors.sol";
interface IRoninGovernanceAdmin {
/// @dev Emitted when an emergency exit poll is created.
event EmergencyExitPollCreated(
bytes32 _voteHash,
address _consensusAddr,
address _recipientAfterUnlockedFund,
uint256 _requestedAt,
uint256 _expiredAt
bytes32 voteHash,
address validatorId,
address recipientAfterUnlockedFund,
uint256 requestedAt,
uint256 expiredAt
);
/// @dev Emitted when an emergency exit poll is approved.
event EmergencyExitPollApproved(bytes32 _voteHash);
event EmergencyExitPollApproved(bytes32 voteHash);
/// @dev Emitted when an emergency exit poll is expired.
event EmergencyExitPollExpired(bytes32 _voteHash);
event EmergencyExitPollExpired(bytes32 voteHash);
/// @dev Emitted when an emergency exit poll is voted.
event EmergencyExitPollVoted(bytes32 indexed _voteHash, address indexed _voter);
event EmergencyExitPollVoted(bytes32 indexed voteHash, address indexed voter);

/**
* @dev Create a vote to agree that an emergency exit is valid and should return the locked funds back.a
Expand All @@ -27,9 +27,9 @@ interface IRoninGovernanceAdmin {
*
*/
function createEmergencyExitPoll(
address _consensusAddr,
address _recipientAfterUnlockedFund,
uint256 _requestedAt,
uint256 _expiredAt
address validatorId,
address recipientAfterUnlockedFund,
uint256 requestedAt,
uint256 expiredAt
) external;
}
Loading

0 comments on commit 1cafa6a

Please sign in to comment.