diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index c2e86d2a4..ada766f5d 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -4,12 +4,12 @@ on: branches: - mainnet - testnet - - 'release/**' + - "release/**" pull_request: branches: - mainnet - testnet - - 'release/**' + - "release/**" permissions: packages: read diff --git a/contracts/interfaces/IProfile.sol b/contracts/interfaces/IProfile.sol index 420eeeb92..5aae00536 100644 --- a/contracts/interfaces/IProfile.sol +++ b/contracts/interfaces/IProfile.sol @@ -77,4 +77,13 @@ interface IProfile { * Emit an {ProfileAddressChanged}. */ function requestChangeConsensusAddr(address id, TConsensus newConsensusAddr) external; + + /** + * @notice The candidate admin registers a new profile. + * + * @dev Requirements: + * - The profile must not be existent before. + * - Only user with candidate admin role can call this method. + */ + function registerProfile(CandidateProfile memory profile) external; } diff --git a/contracts/ronin/profile/Profile.sol b/contracts/ronin/profile/Profile.sol index c767d58f4..85f8c46a3 100644 --- a/contracts/ronin/profile/Profile.sol +++ b/contracts/ronin/profile/Profile.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import "../../interfaces/validator/IRoninValidatorSet.sol"; import "../../interfaces/staking/IStaking.sol"; import "../../interfaces/IProfile.sol"; import "./ProfileXComponents.sol"; +import { ErrUnauthorized, RoleAccess } from "../../utils/CommonErrors.sol"; import "./ProfileStorage.sol"; pragma solidity ^0.8.9; @@ -13,6 +15,10 @@ contract Profile is IProfile, ProfileStorage, ProfileXComponents, Initializable _disableInitializers(); } + function initialize(address validatorContract) external initializer { + _setContract(ContractType.VALIDATOR, validatorContract); + } + /** * @dev Initializes the contract storage. */ @@ -97,4 +103,18 @@ contract Profile is IProfile, ProfileStorage, ProfileXComponents, Initializable emit ProfileAddressChanged(id, RoleAccess.CONSENSUS); } + + /** + * @inheritdoc IProfile + */ + function registerProfile(CandidateProfile memory profile) external { + CandidateProfile storage _profile = _id2Profile[profile.id]; + if (_profile.id != address(0)) revert ErrExistentProfile(); + if ( + msg.sender != profile.admin || + !IRoninValidatorSet(getContract(ContractType.VALIDATOR)).isCandidateAdmin(profile.consensus, profile.admin) + ) revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN); + + _addNewProfile(_profile, profile); + } } diff --git a/contracts/ronin/validator/CoinbaseExecution.sol b/contracts/ronin/validator/CoinbaseExecution.sol index 222f911da..cfd330f28 100644 --- a/contracts/ronin/validator/CoinbaseExecution.sol +++ b/contracts/ronin/validator/CoinbaseExecution.sol @@ -150,7 +150,7 @@ abstract contract CoinbaseExecution is * - This method is only called once each epoch. */ function _syncFastFinalityReward(uint256 epoch, address[] memory validators) private { - uint256[] memory voteCounts = IFastFinalityTracking(getContract(ContractType.FAST_FINALTIY_TRACKING)) + uint256[] memory voteCounts = IFastFinalityTracking(getContract(ContractType.FAST_FINALITY_TRACKING)) .getManyFinalityVoteCounts(epoch, validators); uint256 divisor = _numberOfBlocksInEpoch * validators.length; uint256 iReward; diff --git a/contracts/ronin/validator/RoninValidatorSet.sol b/contracts/ronin/validator/RoninValidatorSet.sol index f9c743a0a..700be6bda 100644 --- a/contracts/ronin/validator/RoninValidatorSet.sol +++ b/contracts/ronin/validator/RoninValidatorSet.sol @@ -70,7 +70,7 @@ contract RoninValidatorSet is Initializable, CoinbaseExecution, SlashingExecutio } function initializeV3(address fastFinalityTrackingContract) external reinitializer(3) { - _setContract(ContractType.FAST_FINALTIY_TRACKING, fastFinalityTrackingContract); + _setContract(ContractType.FAST_FINALITY_TRACKING, fastFinalityTrackingContract); } function initializeV4(address profileContract) external reinitializer(4) { diff --git a/contracts/utils/ContractType.sol b/contracts/utils/ContractType.sol index b9ccddd20..2fcb32f69 100644 --- a/contracts/utils/ContractType.sol +++ b/contracts/utils/ContractType.sol @@ -16,6 +16,6 @@ enum ContractType { /* 11 */ BRIDGE_MANAGER, /* 12 */ BRIDGE_SLASH, /* 13 */ BRIDGE_REWARD, - /* 14 */ FAST_FINALTIY_TRACKING, + /* 14 */ FAST_FINALITY_TRACKING, /* 15 */ PROFILE } diff --git a/deployments/ronin-testnet/ProfileLogic.json b/deployments/ronin-testnet/ProfileLogic.json index c7abe5f58..1070cbdf2 100644 --- a/deployments/ronin-testnet/ProfileLogic.json +++ b/deployments/ronin-testnet/ProfileLogic.json @@ -1,5 +1,5 @@ { - "address": "0x4137D21D98f668d1c06E56B8C1b3C1550272deb7", + "address": "0x6f30C78143E62C3C113BDF79CE662F2290A8d929", "abi": [ { "inputs": [], @@ -233,6 +233,64 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorContract", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "id", + "type": "address" + }, + { + "internalType": "address", + "name": "consensus", + "type": "address" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address payable", + "name": "treasury", + "type": "address" + }, + { + "internalType": "address", + "name": "governor", + "type": "address" + }, + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + } + ], + "internalType": "struct IProfile.CandidateProfile", + "name": "profile", + "type": "tuple" + } + ], + "name": "registerProfile", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -252,41 +310,41 @@ "type": "function" } ], - "transactionHash": "0x10af20e0be4f5e93c7a7ed402645eac2b962ac9ab46a6bf17ab7e83067f9a64d", + "transactionHash": "0x28e9259814c36e701cc32eb66728b92549be5c45c91d302469897a19688f6699", "receipt": { "to": null, "from": "0x968D0Cd7343f711216817E617d3f92a23dC91c07", - "contractAddress": "0x4137D21D98f668d1c06E56B8C1b3C1550272deb7", + "contractAddress": "0x6f30C78143E62C3C113BDF79CE662F2290A8d929", "transactionIndex": 0, - "gasUsed": "602986", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000001000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000", - "blockHash": "0x735ac32bf7c366bb066012bc4dc3189d7170ef348f3900f4c06705b49b37a42b", - "transactionHash": "0x10af20e0be4f5e93c7a7ed402645eac2b962ac9ab46a6bf17ab7e83067f9a64d", + "gasUsed": "742553", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000400000000000000004000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xfd3d654a95573637fdf143e7d752062d7c91d2efe8db93c9dd15a2d776bf1f34", + "transactionHash": "0x28e9259814c36e701cc32eb66728b92549be5c45c91d302469897a19688f6699", "logs": [ { "transactionIndex": 0, - "blockNumber": 20127749, - "transactionHash": "0x10af20e0be4f5e93c7a7ed402645eac2b962ac9ab46a6bf17ab7e83067f9a64d", - "address": "0x4137D21D98f668d1c06E56B8C1b3C1550272deb7", + "blockNumber": 20639147, + "transactionHash": "0x28e9259814c36e701cc32eb66728b92549be5c45c91d302469897a19688f6699", + "address": "0x6f30C78143E62C3C113BDF79CE662F2290A8d929", "topics": [ "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", "logIndex": 0, - "blockHash": "0x735ac32bf7c366bb066012bc4dc3189d7170ef348f3900f4c06705b49b37a42b" + "blockHash": "0xfd3d654a95573637fdf143e7d752062d7c91d2efe8db93c9dd15a2d776bf1f34" } ], - "blockNumber": 20127749, - "cumulativeGasUsed": "602986", + "blockNumber": 20639147, + "cumulativeGasUsed": "742553", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "a9bab0335465d2e01ea22d5aa6e9c8ee", - "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"enum ContractType\",\"name\":\"contractType\",\"type\":\"uint8\"}],\"name\":\"ErrContractTypeNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ErrExistentProfile\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ErrNonExistentProfile\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"msgSig\",\"type\":\"bytes4\"},{\"internalType\":\"enum RoleAccess\",\"name\":\"expectedRole\",\"type\":\"uint8\"}],\"name\":\"ErrUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"ErrZeroCodeContract\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enum ContractType\",\"name\":\"contractType\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"ContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"ProfileAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"enum RoleAccess\",\"name\":\"addressType\",\"type\":\"uint8\"}],\"name\":\"ProfileAddressChanged\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"consensus\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"treasury\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"pubkey\",\"type\":\"bytes\"}],\"internalType\":\"struct IProfile.CandidateProfile\",\"name\":\"profile\",\"type\":\"tuple\"}],\"name\":\"addNewProfile\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum ContractType\",\"name\":\"contractType\",\"type\":\"uint8\"}],\"name\":\"getContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"contract_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"getId2Profile\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"consensus\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"treasury\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"pubkey\",\"type\":\"bytes\"}],\"internalType\":\"struct IProfile.CandidateProfile\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum ContractType\",\"name\":\"contractType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ErrContractTypeNotFound(uint8)\":[{\"details\":\"Error of invalid role.\"}],\"ErrExistentProfile()\":[{\"details\":\"Error of already existed profile.\"}],\"ErrNonExistentProfile()\":[{\"details\":\"Error of non existed profile.\"}],\"ErrUnauthorized(bytes4,uint8)\":[{\"details\":\"Error indicating that the caller is unauthorized to perform a specific function.\",\"params\":{\"expectedRole\":\"The role required to perform the function.\",\"msgSig\":\"The function signature (bytes4) that the caller is unauthorized to perform.\"}}],\"ErrZeroCodeContract(address)\":[{\"details\":\"Error of set to non-contract.\"}]},\"kind\":\"dev\",\"methods\":{\"addNewProfile((address,address,address,address,address,bytes))\":{\"details\":\"Requirements: - The profile must not be existent before. - Only contract admin can call this method.\"},\"getContract(uint8)\":{\"details\":\"Returns the address of a contract with a specific role. Throws an error if no contract is set for the specified role.\",\"params\":{\"contractType\":\"The role of the contract to retrieve.\"},\"returns\":{\"contract_\":\"The address of the contract with the specified role.\"}},\"getId2Profile(address)\":{\"details\":\"Getter to query full `profile` from `id` address.\"},\"setContract(uint8,address)\":{\"details\":\"Sets the address of a contract with a specific role. Emits the event {ContractUpdated}.\",\"params\":{\"addr\":\"The address of the contract to set.\",\"contractType\":\"The role of the contract to set.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addNewProfile((address,address,address,address,address,bytes))\":{\"notice\":\"Add a new profile.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ronin/profile/Profile.sol\":\"Profile\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0xa2b22da3032e50b55f95ec1d13336102d675f341167aa76db571ef7f8bb7975d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(\\n Address.isContract(IBeacon(newBeacon).implementation()),\\n \\\"ERC1967: beacon implementation is not a contract\\\"\\n );\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xabf3f59bc0e5423eae45e459dbe92e7052c6983628d39008590edc852a62f94a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overridden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0xa6a787e7a901af6511e19aa53e1a00352db215a011d2c7a438d0582dd5da76f9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd5c50c54bf02740ebd122ff06832546cb5fa84486d52695a9ccfd11666e0c81d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/extensions/TransparentUpgradeableProxyV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol\\\";\\n\\ncontract TransparentUpgradeableProxyV2 is TransparentUpgradeableProxy {\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable TransparentUpgradeableProxy(_logic, admin_, _data) {}\\n\\n /**\\n * @dev Calls a function from the current implementation as specified by `_data`, which should be an encoded function call.\\n *\\n * Requirements:\\n * - Only the admin can call this function.\\n *\\n * Note: The proxy admin is not allowed to interact with the proxy logic through the fallback function to avoid\\n * triggering some unexpected logic. This is to allow the administrator to explicitly call the proxy, please consider\\n * reviewing the encoded data `_data` and the method which is called before using this.\\n *\\n */\\n function functionDelegateCall(bytes memory _data) public payable ifAdmin {\\n address _addr = _implementation();\\n assembly {\\n let _result := delegatecall(gas(), _addr, add(_data, 32), mload(_data), 0, 0)\\n returndatacopy(0, 0, returndatasize())\\n switch _result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6609392ea7d3174439b5715100bee82528fe6e4aff28927d48c27db8475e88c5\",\"license\":\"MIT\"},\"contracts/extensions/collections/HasContracts.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { HasProxyAdmin } from \\\"./HasProxyAdmin.sol\\\";\\nimport \\\"../../interfaces/collections/IHasContracts.sol\\\";\\nimport { IdentityGuard } from \\\"../../utils/IdentityGuard.sol\\\";\\nimport { ErrUnexpectedInternalCall } from \\\"../../utils/CommonErrors.sol\\\";\\n\\n/**\\n * @title HasContracts\\n * @dev A contract that provides functionality to manage multiple contracts with different roles.\\n */\\nabstract contract HasContracts is HasProxyAdmin, IHasContracts, IdentityGuard {\\n /// @dev value is equal to keccak256(\\\"@ronin.dpos.collections.HasContracts.slot\\\") - 1\\n bytes32 private constant _STORAGE_SLOT = 0xdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb;\\n\\n /**\\n * @dev Modifier to restrict access to functions only to contracts with a specific role.\\n * @param contractType The contract type that allowed to call\\n */\\n modifier onlyContract(ContractType contractType) virtual {\\n _requireContract(contractType);\\n _;\\n }\\n\\n /**\\n * @inheritdoc IHasContracts\\n */\\n function setContract(ContractType contractType, address addr) external virtual onlyAdmin {\\n _requireHasCode(addr);\\n _setContract(contractType, addr);\\n }\\n\\n /**\\n * @inheritdoc IHasContracts\\n */\\n function getContract(ContractType contractType) public view returns (address contract_) {\\n contract_ = _getContractMap()[uint8(contractType)];\\n if (contract_ == address(0)) revert ErrContractTypeNotFound(contractType);\\n }\\n\\n /**\\n * @dev Internal function to set the address of a contract with a specific role.\\n * @param contractType The contract type of the contract to set.\\n * @param addr The address of the contract to set.\\n */\\n function _setContract(ContractType contractType, address addr) internal virtual {\\n _getContractMap()[uint8(contractType)] = addr;\\n emit ContractUpdated(contractType, addr);\\n }\\n\\n /**\\n * @dev Internal function to access the mapping of contract addresses with roles.\\n * @return contracts_ The mapping of contract addresses with roles.\\n */\\n function _getContractMap() private pure returns (mapping(uint8 => address) storage contracts_) {\\n assembly {\\n contracts_.slot := _STORAGE_SLOT\\n }\\n }\\n\\n /**\\n * @dev Internal function to check if the calling contract has a specific role.\\n * @param contractType The contract type that the calling contract must have.\\n * @dev Throws an error if the calling contract does not have the specified role.\\n */\\n function _requireContract(ContractType contractType) private view {\\n if (msg.sender != getContract(contractType)) {\\n revert ErrUnexpectedInternalCall(msg.sig, contractType, msg.sender);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9e1dceb68827adfb8c8184662f29ab5fe14e292a632878150e3b0b6c61bc1dce\",\"license\":\"MIT\"},\"contracts/extensions/collections/HasProxyAdmin.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/StorageSlot.sol\\\";\\nimport \\\"../../utils/CommonErrors.sol\\\";\\n\\nabstract contract HasProxyAdmin {\\n // bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n modifier onlyAdmin() {\\n _requireAdmin();\\n _;\\n }\\n\\n /**\\n * @dev Returns proxy admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n function _requireAdmin() internal view {\\n if (msg.sender != _getAdmin()) revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN);\\n }\\n}\\n\",\"keccak256\":\"0x0916021d04ea0c93c54978dc2fd46575fd2bd867369fbf9ce49f316939ddaf25\",\"license\":\"MIT\"},\"contracts/interfaces/IProfile.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"../utils/RoleAccess.sol\\\";\\n\\ninterface IProfile {\\n struct CandidateProfile {\\n /**\\n * @dev Primary key of the profile, use for backward querying.\\n *\\n * {Staking} Contract: index of pool\\n * {RoninValidatorSet} Contract: index of almost all data related to a validator\\n *\\n */\\n address id;\\n /// @dev Consensus address.\\n address consensus;\\n /// @dev Pool admin address.\\n address admin;\\n /// @dev Treasury address.\\n address payable treasury;\\n /// @dev Address to voting proposal.\\n address governor;\\n /// @dev Public key for fast finality.\\n bytes pubkey;\\n }\\n\\n /// @dev Event emitted when a profile with `id` is added.\\n event ProfileAdded(address indexed id);\\n /// @dev Event emitted when a address in a profile is changed.\\n event ProfileAddressChanged(address indexed id, RoleAccess indexed addressType);\\n\\n /// @dev Error of already existed profile.\\n error ErrExistentProfile();\\n /// @dev Error of non existed profile.\\n error ErrNonExistentProfile();\\n\\n /// @dev Getter to query full `profile` from `id` address.\\n function getId2Profile(address id) external view returns (CandidateProfile memory profile);\\n\\n /**\\n * @notice Add a new profile.\\n *\\n * @dev Requirements:\\n * - The profile must not be existent before.\\n * - Only contract admin can call this method.\\n */\\n function addNewProfile(CandidateProfile memory profile) external;\\n}\\n\",\"keccak256\":\"0x3d58574b5fdb760a69f9225ec87a8a96f192cc3d006badfd363a338122cd5867\",\"license\":\"MIT\"},\"contracts/interfaces/collections/IHasContracts.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport { ContractType } from \\\"../../utils/ContractType.sol\\\";\\n\\ninterface IHasContracts {\\n /// @dev Error of invalid role.\\n error ErrContractTypeNotFound(ContractType contractType);\\n\\n /// @dev Emitted when a contract is updated.\\n event ContractUpdated(ContractType indexed contractType, address indexed addr);\\n\\n /**\\n * @dev Returns the address of a contract with a specific role.\\n * Throws an error if no contract is set for the specified role.\\n *\\n * @param contractType The role of the contract to retrieve.\\n * @return contract_ The address of the contract with the specified role.\\n */\\n function getContract(ContractType contractType) external view returns (address contract_);\\n\\n /**\\n * @dev Sets the address of a contract with a specific role.\\n * Emits the event {ContractUpdated}.\\n * @param contractType The role of the contract to set.\\n * @param addr The address of the contract to set.\\n */\\n function setContract(ContractType contractType, address addr) external;\\n}\\n\",\"keccak256\":\"0x99d8213d857e30d367155abd15dc42730afdfbbac3a22dfb3b95ffea2083a92e\",\"license\":\"MIT\"},\"contracts/interfaces/consumers/PeriodWrapperConsumer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface PeriodWrapperConsumer {\\n struct PeriodWrapper {\\n // Inner value.\\n uint256 inner;\\n // Last period number that the info updated.\\n uint256 lastPeriod;\\n }\\n}\\n\",\"keccak256\":\"0xb6777e3c364306eb8d5355583c1aca44de9d351cb40ddf1cea832206d4aad272\",\"license\":\"MIT\"},\"contracts/interfaces/staking/IBaseStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\ninterface IBaseStaking {\\n struct PoolDetail {\\n // Address of the pool i.e. consensus address of the validator\\n address addr;\\n // Pool admin address\\n address admin;\\n // Self-staking amount\\n uint256 stakingAmount;\\n // Total number of RON staking for the pool\\n uint256 stakingTotal;\\n // Mapping from delegator => delegating amount\\n mapping(address => uint256) delegatingAmount;\\n // Mapping from delegator => the last timestamp that delegator staked\\n mapping(address => uint256) lastDelegatingTimestamp;\\n }\\n\\n /// @dev Emitted when the minium number of seconds to undelegate is updated.\\n event CooldownSecsToUndelegateUpdated(uint256 minSecs);\\n /// @dev Emitted when the number of seconds that a candidate must wait to be revoked.\\n event WaitingSecsToRevokeUpdated(uint256 secs);\\n\\n /// @dev Error of cannot transfer RON.\\n error ErrCannotTransferRON();\\n /// @dev Error of receiving zero message value.\\n error ErrZeroValue();\\n /// @dev Error of pool admin is not allowed to call.\\n error ErrPoolAdminForbidden();\\n /// @dev Error of no one is allowed to call but the pool's admin.\\n error ErrOnlyPoolAdminAllowed();\\n /// @dev Error of admin of any active pool cannot delegate.\\n error ErrAdminOfAnyActivePoolForbidden(address admin);\\n /// @dev Error of querying inactive pool.\\n error ErrInactivePool(address poolAddr);\\n /// @dev Error of length of input arrays are not of the same.\\n error ErrInvalidArrays();\\n\\n /**\\n * @dev Returns whether the `_poolAdminAddr` is currently active.\\n */\\n function isAdminOfActivePool(address _poolAdminAddr) external view returns (bool);\\n\\n /**\\n * @dev Returns the consensus address corresponding to the pool admin.\\n */\\n function getPoolAddressOf(address _poolAdminAddr) external view returns (address);\\n\\n /**\\n * @dev Returns the staking pool detail.\\n */\\n function getPoolDetail(address) external view returns (address _admin, uint256 _stakingAmount, uint256 _stakingTotal);\\n\\n /**\\n * @dev Returns the self-staking amounts of the pools.\\n */\\n function getManySelfStakings(address[] calldata) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Returns The cooldown time in seconds to undelegate from the last timestamp (s)he delegated.\\n */\\n function cooldownSecsToUndelegate() external view returns (uint256);\\n\\n /**\\n * @dev Returns the number of seconds that a candidate must wait for the renounce request gets affected.\\n */\\n function waitingSecsToRevoke() external view returns (uint256);\\n\\n /**\\n * @dev Sets the cooldown time in seconds to undelegate from the last timestamp (s)he delegated.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the event `CooldownSecsToUndelegateUpdated`.\\n *\\n */\\n function setCooldownSecsToUndelegate(uint256 _cooldownSecs) external;\\n\\n /**\\n * @dev Sets the number of seconds that a candidate must wait to be revoked.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the event `WaitingSecsToRevokeUpdated`.\\n *\\n */\\n function setWaitingSecsToRevoke(uint256 _secs) external;\\n}\\n\",\"keccak256\":\"0x90517268a0e31147d97772c9ae518caa5eb8c03efe3b369e3c6d5166422f5962\",\"license\":\"MIT\"},\"contracts/interfaces/staking/ICandidateStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"./IRewardPool.sol\\\";\\n\\ninterface ICandidateStaking is IRewardPool {\\n /// @dev Emitted when the minimum staking amount for being a validator is updated.\\n event MinValidatorStakingAmountUpdated(uint256 threshold);\\n /// @dev Emitted when the commission rate range is updated.\\n event CommissionRateRangeUpdated(uint256 minRate, uint256 maxRate);\\n\\n /// @dev Emitted when the pool admin staked for themself.\\n event Staked(address indexed consensuAddr, uint256 amount);\\n /// @dev Emitted when the pool admin unstaked the amount of RON from themself.\\n event Unstaked(address indexed consensuAddr, uint256 amount);\\n\\n /// @dev Emitted when the validator pool is approved.\\n event PoolApproved(address indexed validator, address indexed admin);\\n /// @dev Emitted when the validator pool is deprecated.\\n event PoolsDeprecated(address[] validator);\\n /// @dev Emitted when the staking amount transfer failed.\\n event StakingAmountTransferFailed(\\n address indexed validator,\\n address indexed admin,\\n uint256 amount,\\n uint256 contractBalance\\n );\\n /// @dev Emitted when the staking amount deducted failed, e.g. when the validator gets slashed.\\n event StakingAmountDeductFailed(\\n address indexed validator,\\n address indexed recipient,\\n uint256 amount,\\n uint256 contractBalance\\n );\\n\\n /// @dev Error of cannot transfer RON to specified target.\\n error ErrCannotInitTransferRON(address addr, string extraInfo);\\n /// @dev Error of three interaction addresses must be of the same in applying for validator candidate.\\n error ErrThreeInteractionAddrsNotEqual();\\n /// @dev Error of unstaking zero amount.\\n error ErrUnstakeZeroAmount();\\n /// @dev Error of invalid staking amount left after deducted.\\n error ErrStakingAmountLeft();\\n /// @dev Error of insufficient staking amount for unstaking.\\n error ErrInsufficientStakingAmount();\\n /// @dev Error of unstaking too early.\\n error ErrUnstakeTooEarly();\\n /// @dev Error of setting commission rate exceeds max allowed.\\n error ErrInvalidCommissionRate();\\n\\n /**\\n * @dev Returns the minimum threshold for being a validator candidate.\\n */\\n function minValidatorStakingAmount() external view returns (uint256);\\n\\n /**\\n * @dev Returns the commission rate range that the candidate can set.\\n */\\n function getCommissionRateRange() external view returns (uint256 _minRange, uint256 _maxRange);\\n\\n /**\\n * @dev Sets the minimum threshold for being a validator candidate.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the `MinValidatorStakingAmountUpdated` event.\\n *\\n */\\n function setMinValidatorStakingAmount(uint256) external;\\n\\n /**\\n * @dev Sets the commission rate range that a candidate can set.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the `CommissionRateRangeUpdated` event.\\n *\\n */\\n function setCommissionRateRange(uint256 _minRate, uint256 _maxRate) external;\\n\\n /**\\n * @dev Proposes a candidate to become a validator.\\n *\\n * Requirements:\\n * - The method caller is able to receive RON.\\n * - The treasury is able to receive RON.\\n * - The amount is larger than or equal to the minimum validator staking amount `minValidatorStakingAmount()`.\\n *\\n * Emits the event `PoolApproved`.\\n *\\n * @param _candidateAdmin the candidate admin will be stored in the validator contract, used for calling function that affects\\n * to its candidate, e.g. scheduling maintenance.\\n *\\n */\\n function applyValidatorCandidate(\\n address _candidateAdmin,\\n address _consensusAddr,\\n address payable _treasuryAddr,\\n uint256 _commissionRate\\n ) external payable;\\n\\n /**\\n * @dev Deprecates the pool.\\n * - Deduct self-staking amount of the pool admin to zero.\\n * - Transfer the deducted amount to the pool admin.\\n * - Deactivate the pool admin address in the mapping of active pool admins\\n *\\n * Requirements:\\n * - The method caller is validator contract.\\n *\\n * Emits the event `PoolsDeprecated` and `Unstaked` events.\\n * Emits the event `StakingAmountTransferFailed` if the contract cannot transfer RON back to the pool admin.\\n *\\n */\\n function execDeprecatePools(address[] calldata _pools, uint256 _period) external;\\n\\n /**\\n * @dev Self-delegates to the validator candidate `_consensusAddr`.\\n *\\n * Requirements:\\n * - The consensus address is a validator candidate.\\n * - The method caller is the pool admin.\\n * - The `msg.value` is larger than 0.\\n *\\n * Emits the event `Staked`.\\n *\\n */\\n function stake(address _consensusAddr) external payable;\\n\\n /**\\n * @dev Unstakes from the validator candidate `_consensusAddr` for `_amount`.\\n *\\n * Requirements:\\n * - The consensus address is a validator candidate.\\n * - The method caller is the pool admin.\\n *\\n * Emits the event `Unstaked`.\\n *\\n */\\n function unstake(address _consensusAddr, uint256 _amount) external;\\n\\n /**\\n * @dev Pool admin requests update validator commission rate. The request will be forwarded to the candidate manager\\n * contract, and the value is getting updated in {ICandidateManager-execRequestUpdateCommissionRate}.\\n *\\n * Requirements:\\n * - The consensus address is a validator candidate.\\n * - The method caller is the pool admin.\\n * - The `_effectiveDaysOnwards` must be equal to or larger than the {CandidateManager-_minEffectiveDaysOnwards}.\\n * - The `_rate` must be in range of [0_00; 100_00].\\n *\\n * Emits the event `CommissionRateUpdated`.\\n *\\n */\\n function requestUpdateCommissionRate(\\n address _consensusAddr,\\n uint256 _effectiveDaysOnwards,\\n uint256 _commissionRate\\n ) external;\\n\\n /**\\n * @dev Renounces being a validator candidate and takes back the delegating/staking amount.\\n *\\n * Requirements:\\n * - The consensus address is a validator candidate.\\n * - The method caller is the pool admin.\\n *\\n */\\n function requestRenounce(address _consensusAddr) external;\\n\\n /**\\n * @dev Renounces being a validator candidate and takes back the delegating/staking amount.\\n *\\n * Requirements:\\n * - The consensus address is a validator candidate.\\n * - The method caller is the pool admin.\\n *\\n */\\n function requestEmergencyExit(address _consensusAddr) external;\\n}\\n\",\"keccak256\":\"0x9bc6ba6d13f00d9928c0add35ee6406906e16ed86207d373460930c0a75e5938\",\"license\":\"MIT\"},\"contracts/interfaces/staking/IDelegatorStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"./IRewardPool.sol\\\";\\n\\ninterface IDelegatorStaking is IRewardPool {\\n /// @dev Emitted when the delegator staked for a validator candidate.\\n event Delegated(address indexed delegator, address indexed consensuAddr, uint256 amount);\\n /// @dev Emitted when the delegator unstaked from a validator candidate.\\n event Undelegated(address indexed delegator, address indexed consensuAddr, uint256 amount);\\n\\n /// @dev Error of undelegating zero amount.\\n error ErrUndelegateZeroAmount();\\n /// @dev Error of undelegating insufficient amount.\\n error ErrInsufficientDelegatingAmount();\\n /// @dev Error of undelegating too early.\\n error ErrUndelegateTooEarly();\\n\\n /**\\n * @dev Stakes for a validator candidate `_consensusAddr`.\\n *\\n * Requirements:\\n * - The consensus address is a validator candidate.\\n * - The method caller is not the pool admin.\\n *\\n * Emits the `Delegated` event.\\n *\\n */\\n function delegate(address _consensusAddr) external payable;\\n\\n /**\\n * @dev Unstakes from a validator candidate `_consensusAddr` for `_amount`.\\n *\\n * Requirements:\\n * - The method caller is not the pool admin.\\n *\\n * Emits the `Undelegated` event.\\n *\\n */\\n function undelegate(address _consensusAddr, uint256 _amount) external;\\n\\n /**\\n * @dev Bulk unstakes from a list of candidates.\\n *\\n * Requirements:\\n * - The method caller is not the pool admin.\\n *\\n * Emits the events `Undelegated`.\\n *\\n */\\n function bulkUndelegate(address[] calldata _consensusAddrs, uint256[] calldata _amounts) external;\\n\\n /**\\n * @dev Unstakes an amount of RON from the `_consensusAddrSrc` and stake for `_consensusAddrDst`.\\n *\\n * Requirements:\\n * - The method caller is not the pool admin.\\n * - The consensus address `_consensusAddrDst` is a validator candidate.\\n *\\n * Emits the `Undelegated` event and the `Delegated` event.\\n *\\n */\\n function redelegate(address _consensusAddrSrc, address _consensusAddrDst, uint256 _amount) external;\\n\\n /**\\n * @dev Returns the claimable reward of the user `_user`.\\n */\\n function getRewards(\\n address _user,\\n address[] calldata _poolAddrList\\n ) external view returns (uint256[] memory _rewards);\\n\\n /**\\n * @dev Claims the reward of method caller.\\n *\\n * Emits the `RewardClaimed` event.\\n *\\n */\\n function claimRewards(address[] calldata _consensusAddrList) external returns (uint256 _amount);\\n\\n /**\\n * @dev Claims the rewards and delegates them to the consensus address.\\n *\\n * Requirements:\\n * - The method caller is not the pool admin.\\n * - The consensus address `_consensusAddrDst` is a validator candidate.\\n *\\n * Emits the `RewardClaimed` event and the `Delegated` event.\\n *\\n */\\n function delegateRewards(\\n address[] calldata _consensusAddrList,\\n address _consensusAddrDst\\n ) external returns (uint256 _amount);\\n}\\n\",\"keccak256\":\"0x6dd71bf0c17a65da0dee49b98e4b038c1dd0e74f5473d03570421ceebd5b7084\",\"license\":\"MIT\"},\"contracts/interfaces/staking/IRewardPool.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"../../interfaces/consumers/PeriodWrapperConsumer.sol\\\";\\n\\ninterface IRewardPool is PeriodWrapperConsumer {\\n struct UserRewardFields {\\n // Recorded reward amount.\\n uint256 debited;\\n // The last accumulated of the amount rewards per share (one unit staking) that the info updated.\\n uint256 aRps;\\n // Lowest staking amount in the period.\\n uint256 lowestAmount;\\n // Last period number that the info updated.\\n uint256 lastPeriod;\\n }\\n\\n struct PoolFields {\\n // Accumulated of the amount rewards per share (one unit staking).\\n uint256 aRps;\\n // The staking total to share reward of the current period.\\n PeriodWrapper shares;\\n }\\n\\n /// @dev Emitted when the fields to calculate pending reward for the user is updated.\\n event UserRewardUpdated(address indexed poolAddr, address indexed user, uint256 debited);\\n /// @dev Emitted when the user claimed their reward\\n event RewardClaimed(address indexed poolAddr, address indexed user, uint256 amount);\\n\\n /// @dev Emitted when the pool shares are updated\\n event PoolSharesUpdated(uint256 indexed period, address indexed poolAddr, uint256 shares);\\n /// @dev Emitted when the pools are updated\\n event PoolsUpdated(uint256 indexed period, address[] poolAddrs, uint256[] aRps, uint256[] shares);\\n /// @dev Emitted when the contract fails when updating the pools\\n event PoolsUpdateFailed(uint256 indexed period, address[] poolAddrs, uint256[] rewards);\\n /// @dev Emitted when the contract fails when updating the pools that already set\\n event PoolsUpdateConflicted(uint256 indexed period, address[] poolAddrs);\\n\\n /// @dev Error of invalid pool share.\\n error ErrInvalidPoolShare();\\n\\n /**\\n * @dev Returns the reward amount that user claimable.\\n */\\n function getReward(address _poolAddr, address _user) external view returns (uint256);\\n\\n /**\\n * @dev Returns the staking amount of an user.\\n */\\n function getStakingAmount(address _poolAddr, address _user) external view returns (uint256);\\n\\n /**\\n * @dev Returns the staking amounts of the users.\\n */\\n function getManyStakingAmounts(\\n address[] calldata _poolAddrs,\\n address[] calldata _userList\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Returns the total staking amount of all users for a pool.\\n */\\n function getStakingTotal(address _poolAddr) external view returns (uint256);\\n\\n /**\\n * @dev Returns the total staking amounts of all users for the pools `_poolAddrs`.\\n */\\n function getManyStakingTotals(address[] calldata _poolAddrs) external view returns (uint256[] memory);\\n}\\n\",\"keccak256\":\"0x52349fecb897b3b8288d8732923551382822c0c5fb8db9c6b094d080a16a2129\",\"license\":\"MIT\"},\"contracts/interfaces/staking/IStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"./IBaseStaking.sol\\\";\\nimport \\\"./ICandidateStaking.sol\\\";\\nimport \\\"./IDelegatorStaking.sol\\\";\\n\\ninterface IStaking is IRewardPool, IBaseStaking, ICandidateStaking, IDelegatorStaking {\\n /**\\n * @dev Records the amount of rewards `_rewards` for the pools `_consensusAddrs`.\\n *\\n * Requirements:\\n * - The method caller must be validator contract.\\n *\\n * Emits the event `PoolsUpdated` once the contract recorded the rewards successfully.\\n * Emits the event `PoolsUpdateFailed` once the input array lengths are not equal.\\n * Emits the event `PoolsUpdateConflicted` when there are some pools which already updated in the period.\\n *\\n * Note: This method should be called once at the period ending.\\n *\\n */\\n function execRecordRewards(\\n address[] calldata _consensusAddrs,\\n uint256[] calldata _rewards,\\n uint256 _period\\n ) external payable;\\n\\n /**\\n * @dev Deducts from staking amount of the validator `_consensusAddr` for `_amount`.\\n *\\n * Requirements:\\n * - The method caller must be validator contract.\\n *\\n * Emits the event `Unstaked`.\\n *\\n */\\n function execDeductStakingAmount(\\n address _consensusAddr,\\n uint256 _amount\\n ) external returns (uint256 _actualDeductingAmount);\\n}\\n\",\"keccak256\":\"0xd302d4a78203e277fb95a89de7ae32a3102129d3fbd64fc75f92d18be0443408\",\"license\":\"MIT\"},\"contracts/libraries/AddressArrayUtils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.8.0;\\n\\nlibrary AddressArrayUtils {\\n /**\\n * @dev Error thrown when a duplicated element is detected in an array.\\n * @param msgSig The function signature that invoke the error.\\n */\\n error ErrDuplicated(bytes4 msgSig);\\n\\n /**\\n * @dev Returns whether or not there's a duplicate. Runs in O(n^2).\\n * @param A Array to search\\n * @return Returns true if duplicate, false otherwise\\n */\\n function hasDuplicate(address[] memory A) internal pure returns (bool) {\\n if (A.length == 0) {\\n return false;\\n }\\n unchecked {\\n for (uint256 i = 0; i < A.length - 1; i++) {\\n for (uint256 j = i + 1; j < A.length; j++) {\\n if (A[i] == A[j]) {\\n return true;\\n }\\n }\\n }\\n }\\n return false;\\n }\\n\\n /**\\n * @dev Returns whether two arrays of addresses are equal or not.\\n */\\n function isEqual(address[] memory _this, address[] memory _other) internal pure returns (bool yes_) {\\n // Hashing two arrays and compare their hash\\n assembly {\\n let _thisHash := keccak256(add(_this, 32), mul(mload(_this), 32))\\n let _otherHash := keccak256(add(_other, 32), mul(mload(_other), 32))\\n yes_ := eq(_thisHash, _otherHash)\\n }\\n }\\n\\n /**\\n * @dev Return the concatenated array from a and b.\\n */\\n function extend(address[] memory a, address[] memory b) internal pure returns (address[] memory c) {\\n uint256 lengthA = a.length;\\n uint256 lengthB = b.length;\\n unchecked {\\n c = new address[](lengthA + lengthB);\\n }\\n uint256 i;\\n for (; i < lengthA; ) {\\n c[i] = a[i];\\n unchecked {\\n ++i;\\n }\\n }\\n for (uint256 j; j < lengthB; ) {\\n c[i] = b[j];\\n unchecked {\\n ++i;\\n ++j;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaf760162653a85d6e1b24df4d33c74076f778470112f421a02050fb981242001\",\"license\":\"UNLICENSED\"},\"contracts/ronin/profile/Profile.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\nimport \\\"@openzeppelin/contracts/proxy/utils/Initializable.sol\\\";\\nimport \\\"../../interfaces/staking/IStaking.sol\\\";\\nimport \\\"../../interfaces/IProfile.sol\\\";\\nimport \\\"./ProfileStorage.sol\\\";\\n\\npragma solidity ^0.8.9;\\n\\ncontract Profile is IProfile, ProfileStorage, Initializable {\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @inheritdoc IProfile\\n */\\n function getId2Profile(address id) external view returns (CandidateProfile memory) {\\n return _id2Profile[id];\\n }\\n\\n /**\\n * @inheritdoc IProfile\\n */\\n function addNewProfile(CandidateProfile memory profile) external onlyAdmin {\\n CandidateProfile storage _profile = _id2Profile[profile.id];\\n if (_profile.id != address(0)) revert ErrExistentProfile();\\n _addNewProfile(_profile, profile);\\n }\\n}\\n\",\"keccak256\":\"0x9e6204af22d11a8f66bc8378fce19bdef7c0078576e3e7625ca0dddd22fb68a4\",\"license\":\"MIT\"},\"contracts/ronin/profile/ProfileStorage.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"../../extensions/collections/HasContracts.sol\\\";\\nimport { IProfile } from \\\"../../interfaces/IProfile.sol\\\";\\n\\nabstract contract ProfileStorage is IProfile, HasContracts {\\n /// @dev Mapping from id address => candidate profile.\\n mapping(address => CandidateProfile) internal _id2Profile;\\n /// @dev Upgradeable gap.\\n bytes32[50] __gap;\\n\\n /**\\n * @dev Add a profile from memory to storage.\\n */\\n function _addNewProfile(CandidateProfile storage _profile, CandidateProfile memory newProfile) internal {\\n _profile.id = newProfile.id;\\n _profile.consensus = newProfile.consensus;\\n _profile.admin = newProfile.admin;\\n _profile.treasury = newProfile.treasury;\\n _profile.governor = newProfile.governor;\\n _profile.pubkey = newProfile.pubkey;\\n\\n emit ProfileAdded(newProfile.id);\\n }\\n\\n /**\\n * @dev Get an existed profile struct from id. Revert if the profile does not exists.\\n */\\n function _getId2ProfileHelper(address id) internal view returns (CandidateProfile storage _profile) {\\n _profile = _id2Profile[id];\\n if (_profile.id == address(0)) revert ErrNonExistentProfile();\\n }\\n}\\n\",\"keccak256\":\"0x212a824f8f86eb566ea74c1fa9147043f0d8f27b1ddff2e167c073949d784581\",\"license\":\"MIT\"},\"contracts/utils/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { ContractType } from \\\"./ContractType.sol\\\";\\nimport { RoleAccess } from \\\"./RoleAccess.sol\\\";\\n\\nerror ErrSyncTooFarPeriod(uint256 period, uint256 latestRewardedPeriod);\\n/**\\n * @dev Error thrown when an address is expected to be an already created externally owned account (EOA).\\n * This error indicates that the provided address is invalid for certain contract operations that require already created EOA.\\n */\\nerror ErrAddressIsNotCreatedEOA(address addr, bytes32 codehash);\\n/**\\n * @dev Error raised when a bridge operator update operation fails.\\n * @param bridgeOperator The address of the bridge operator that failed to update.\\n */\\nerror ErrBridgeOperatorUpdateFailed(address bridgeOperator);\\n/**\\n * @dev Error thrown when attempting to add a bridge operator that already exists in the contract.\\n * This error indicates that the provided bridge operator address is already registered as a bridge operator in the contract.\\n */\\nerror ErrBridgeOperatorAlreadyExisted(address bridgeOperator);\\n/**\\n * @dev The error indicating an unsupported interface.\\n * @param interfaceId The bytes4 interface identifier that is not supported.\\n * @param addr The address where the unsupported interface was encountered.\\n */\\nerror ErrUnsupportedInterface(bytes4 interfaceId, address addr);\\n/**\\n * @dev Error thrown when the return data from a callback function is invalid.\\n * @param callbackFnSig The signature of the callback function that returned invalid data.\\n * @param register The address of the register where the callback function was invoked.\\n * @param returnData The invalid return data received from the callback function.\\n */\\nerror ErrInvalidReturnData(bytes4 callbackFnSig, address register, bytes returnData);\\n/**\\n * @dev Error of set to non-contract.\\n */\\nerror ErrZeroCodeContract(address addr);\\n/**\\n * @dev Error indicating that arguments are invalid.\\n */\\nerror ErrInvalidArguments(bytes4 msgSig);\\n/**\\n * @dev Error indicating that given address is null when it should not.\\n */\\nerror ErrZeroAddress(bytes4 msgSig);\\n/**\\n * @dev Error indicating that the provided threshold is invalid for a specific function signature.\\n * @param msgSig The function signature (bytes4) that the invalid threshold applies to.\\n */\\nerror ErrInvalidThreshold(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a function can only be called by the contract itself.\\n * @param msgSig The function signature (bytes4) that can only be called by the contract itself.\\n */\\nerror ErrOnlySelfCall(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\\n * @param msgSig The function signature (bytes4) that the caller is unauthorized to perform.\\n * @param expectedRole The role required to perform the function.\\n */\\nerror ErrUnauthorized(bytes4 msgSig, RoleAccess expectedRole);\\n\\n/**\\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\\n * @param msgSig The function signature (bytes4) that the caller is unauthorized to perform.\\n */\\nerror ErrUnauthorizedCall(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\\n * @param msgSig The function signature (bytes4).\\n * @param expectedContractType The contract type required to perform the function.\\n * @param actual The actual address that called to the function.\\n */\\nerror ErrUnexpectedInternalCall(bytes4 msgSig, ContractType expectedContractType, address actual);\\n\\n/**\\n * @dev Error indicating that an array is empty when it should contain elements.\\n */\\nerror ErrEmptyArray();\\n\\n/**\\n * @dev Error indicating a mismatch in the length of input parameters or arrays for a specific function.\\n * @param msgSig The function signature (bytes4) that has a length mismatch.\\n */\\nerror ErrLengthMismatch(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a proxy call to an external contract has failed.\\n * @param msgSig The function signature (bytes4) of the proxy call that failed.\\n * @param extCallSig The function signature (bytes4) of the external contract call that failed.\\n */\\nerror ErrProxyCallFailed(bytes4 msgSig, bytes4 extCallSig);\\n\\n/**\\n * @dev Error indicating that a function tried to call a precompiled contract that is not allowed.\\n * @param msgSig The function signature (bytes4) that attempted to call a precompiled contract.\\n */\\nerror ErrCallPrecompiled(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a native token transfer has failed.\\n * @param msgSig The function signature (bytes4) of the token transfer that failed.\\n */\\nerror ErrNativeTransferFailed(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that an order is invalid.\\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid order.\\n */\\nerror ErrInvalidOrder(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that the chain ID is invalid.\\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid chain ID.\\n * @param actual Current chain ID that executing function.\\n * @param expected Expected chain ID required for the tx to success.\\n */\\nerror ErrInvalidChainId(bytes4 msgSig, uint256 actual, uint256 expected);\\n\\n/**\\n * @dev Error indicating that a vote type is not supported.\\n * @param msgSig The function signature (bytes4) of the operation that encountered an unsupported vote type.\\n */\\nerror ErrUnsupportedVoteType(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that the proposal nonce is invalid.\\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid proposal nonce.\\n */\\nerror ErrInvalidProposalNonce(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a voter has already voted.\\n * @param voter The address of the voter who has already voted.\\n */\\nerror ErrAlreadyVoted(address voter);\\n\\n/**\\n * @dev Error indicating that a signature is invalid for a specific function signature.\\n * @param msgSig The function signature (bytes4) that encountered an invalid signature.\\n */\\nerror ErrInvalidSignatures(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a relay call has failed.\\n * @param msgSig The function signature (bytes4) of the relay call that failed.\\n */\\nerror ErrRelayFailed(bytes4 msgSig);\\n/**\\n * @dev Error indicating that a vote weight is invalid for a specific function signature.\\n * @param msgSig The function signature (bytes4) that encountered an invalid vote weight.\\n */\\nerror ErrInvalidVoteWeight(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a query was made for an outdated bridge operator set.\\n */\\nerror ErrQueryForOutdatedBridgeOperatorSet();\\n\\n/**\\n * @dev Error indicating that a request is invalid.\\n */\\nerror ErrInvalidRequest();\\n\\n/**\\n * @dev Error indicating that a token standard is invalid.\\n */\\nerror ErrInvalidTokenStandard();\\n\\n/**\\n * @dev Error indicating that a token is not supported.\\n */\\nerror ErrUnsupportedToken();\\n\\n/**\\n * @dev Error indicating that a receipt kind is invalid.\\n */\\nerror ErrInvalidReceiptKind();\\n\\n/**\\n * @dev Error indicating that a receipt is invalid.\\n */\\nerror ErrInvalidReceipt();\\n\\n/**\\n * @dev Error indicating that an address is not payable.\\n */\\nerror ErrNonpayableAddress(address);\\n\\n/**\\n * @dev Error indicating that the period is already processed, i.e. scattered reward.\\n */\\nerror ErrPeriodAlreadyProcessed(uint256 requestingPeriod, uint256 latestPeriod);\\n\\n/**\\n * @dev Error thrown when an invalid vote hash is provided.\\n */\\nerror ErrInvalidVoteHash();\\n\\n/**\\n * @dev Error thrown when querying for an empty vote.\\n */\\nerror ErrQueryForEmptyVote();\\n\\n/**\\n * @dev Error thrown when querying for an expired vote.\\n */\\nerror ErrQueryForExpiredVote();\\n\\n/**\\n * @dev Error thrown when querying for a non-existent vote.\\n */\\nerror ErrQueryForNonExistentVote();\\n\\n/**\\n * @dev Error indicating that the method is only called once per block.\\n */\\nerror ErrOncePerBlock();\\n\\n/**\\n * @dev Error of method caller must be coinbase\\n */\\nerror ErrCallerMustBeCoinbase();\\n\",\"keccak256\":\"0x22942c8fea2d1ca863ac1f9c1662d714b8ac0856684e36f8aaf19508648c1053\",\"license\":\"MIT\"},\"contracts/utils/ContractType.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum ContractType {\\n /* 0 */ UNKNOWN,\\n /* 1 */ PAUSE_ENFORCER,\\n /* 2 */ BRIDGE,\\n /* 3 */ BRIDGE_TRACKING,\\n /* 4 */ GOVERNANCE_ADMIN,\\n /* 5 */ MAINTENANCE,\\n /* 6 */ SLASH_INDICATOR,\\n /* 7 */ STAKING_VESTING,\\n /* 8 */ VALIDATOR,\\n /* 9 */ STAKING,\\n /* 10 */ RONIN_TRUSTED_ORGANIZATION,\\n /* 11 */ BRIDGE_MANAGER,\\n /* 12 */ BRIDGE_SLASH,\\n /* 13 */ BRIDGE_REWARD,\\n /* 14 */ FAST_FINALTIY_TRACKING,\\n /* 15 */ PROFILE\\n}\\n\",\"keccak256\":\"0x57e684dc2640b237ea5eaa29234a3b640b18ceb5d16c74d0c3f13fa0c28e533a\",\"license\":\"MIT\"},\"contracts/utils/IdentityGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { AddressArrayUtils } from \\\"../libraries/AddressArrayUtils.sol\\\";\\nimport { IERC165 } from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport { TransparentUpgradeableProxyV2 } from \\\"../extensions/TransparentUpgradeableProxyV2.sol\\\";\\nimport { ErrAddressIsNotCreatedEOA, ErrZeroAddress, ErrOnlySelfCall, ErrZeroCodeContract, ErrUnsupportedInterface } from \\\"./CommonErrors.sol\\\";\\n\\nabstract contract IdentityGuard {\\n using AddressArrayUtils for address[];\\n\\n /// @dev value is equal to keccak256(abi.encode())\\n /// @dev see: https://eips.ethereum.org/EIPS/eip-1052\\n bytes32 internal constant CREATED_ACCOUNT_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n\\n /**\\n * @dev Modifier to restrict functions to only be called by this contract.\\n * @dev Reverts if the caller is not this contract.\\n */\\n modifier onlySelfCall() virtual {\\n _requireSelfCall();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to ensure that the elements in the `arr` array are non-duplicates.\\n * It calls the internal `_checkDuplicate` function to perform the duplicate check.\\n *\\n * Requirements:\\n * - The elements in the `arr` array must not contain any duplicates.\\n */\\n modifier nonDuplicate(address[] memory arr) virtual {\\n _requireNonDuplicate(arr);\\n _;\\n }\\n\\n /**\\n * @dev Internal method to check the method caller.\\n * @dev Reverts if the method caller is not this contract.\\n */\\n function _requireSelfCall() internal view virtual {\\n if (msg.sender != address(this)) revert ErrOnlySelfCall(msg.sig);\\n }\\n\\n /**\\n * @dev Internal function to check if a contract address has code.\\n * @param addr The address of the contract to check.\\n * @dev Throws an error if the contract address has no code.\\n */\\n function _requireHasCode(address addr) internal view {\\n if (addr.code.length == 0) revert ErrZeroCodeContract(addr);\\n }\\n\\n /**\\n * @dev Checks if an address is zero and reverts if it is.\\n * @param addr The address to check.\\n */\\n function _requireNonZeroAddress(address addr) internal pure {\\n if (addr == address(0)) revert ErrZeroAddress(msg.sig);\\n }\\n\\n /**\\n * @dev Check if arr is empty and revert if it is.\\n * Checks if an array contains any duplicate addresses and reverts if duplicates are found.\\n * @param arr The array of addresses to check.\\n */\\n function _requireNonDuplicate(address[] memory arr) internal pure {\\n if (arr.hasDuplicate()) revert AddressArrayUtils.ErrDuplicated(msg.sig);\\n }\\n\\n /**\\n * @dev Internal function to require that the provided address is a created externally owned account (EOA).\\n * This internal function is used to ensure that the provided address is a valid externally owned account (EOA).\\n * It checks the codehash of the address against a predefined constant to confirm that the address is a created EOA.\\n * @notice This method only works with non-state EOA accounts\\n */\\n function _requireCreatedEOA(address addr) internal view {\\n _requireNonZeroAddress(addr);\\n bytes32 codehash = addr.codehash;\\n if (codehash != CREATED_ACCOUNT_HASH) revert ErrAddressIsNotCreatedEOA(addr, codehash);\\n }\\n\\n /**\\n * @dev Internal function to require that the specified contract supports the given interface. This method handle in\\n * both case that the callee is either or not the proxy admin of the caller. If the contract does not support the\\n * interface `interfaceId` or EIP165, a revert with the corresponding error message is triggered.\\n *\\n * @param contractAddr The address of the contract to check for interface support.\\n * @param interfaceId The interface ID to check for support.\\n */\\n function _requireSupportsInterface(address contractAddr, bytes4 interfaceId) internal view {\\n bytes memory supportsInterfaceParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n (bool success, bytes memory returnOrRevertData) = contractAddr.staticcall(supportsInterfaceParams);\\n if (!success) {\\n (success, returnOrRevertData) = contractAddr.staticcall(\\n abi.encodeCall(TransparentUpgradeableProxyV2.functionDelegateCall, (supportsInterfaceParams))\\n );\\n if (!success) revert ErrUnsupportedInterface(interfaceId, contractAddr);\\n }\\n if (!abi.decode(returnOrRevertData, (bool))) revert ErrUnsupportedInterface(interfaceId, contractAddr);\\n }\\n}\\n\",\"keccak256\":\"0x2d0dfcef3636945bc1785c1fa5a05f5203c79cbb81b2eee92a3ac6a2378c2ce5\",\"license\":\"MIT\"},\"contracts/utils/RoleAccess.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum RoleAccess {\\n /* 0 */ UNKNOWN,\\n /* 1 */ ADMIN,\\n /* 2 */ COINBASE,\\n /* 3 */ GOVERNOR,\\n /* 4 */ CANDIDATE_ADMIN,\\n /* 5 */ WITHDRAWAL_MIGRATOR,\\n /* 6 */ __DEPRECATED_BRIDGE_OPERATOR,\\n /* 7 */ BLOCK_PRODUCER,\\n /* 8 */ VALIDATOR_CANDIDATE\\n}\\n\",\"keccak256\":\"0xa98cec38c640c4e37f475debbcd366226f1188c3f5ea6e29de768bd33e021873\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061001961001e565b6100de565b603354610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60335460ff90811610156100dc576033805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b610976806100ed6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063865e6fd31461005157806392d4875614610066578063de981f1b14610079578063f4660940146100a9575b600080fd5b61006461005f36600461051a565b6100c9565b005b61006461007436600461061d565b6100e8565b61008c6100873660046106e5565b610138565b6040516001600160a01b0390911681526020015b60405180910390f35b6100bc6100b7366004610707565b6101bc565b6040516100a09190610724565b6100d16102ec565b6100da81610348565b6100e48282610381565b5050565b6100f06102ec565b80516001600160a01b03908116600090815260208190526040902080549091161561012e5760405163249b38f960e01b815260040160405180910390fd5b6100e48183610425565b60007fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600083600f81111561016f5761016f6107c2565b60ff1681526020810191909152604001600020546001600160a01b03169050806101b7578160405163409140df60e11b81526004016101ae91906107d8565b60405180910390fd5b919050565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082019290925260a08101919091526001600160a01b0380831660009081526020818152604091829020825160c081018452815485168152600182015485169281019290925260028101548416928201929092526003820154831660608201526004820154909216608083015260058101805460a084019190610263906107f2565b80601f016020809104026020016040519081016040528092919081815260200182805461028f906107f2565b80156102dc5780601f106102b1576101008083540402835291602001916102dc565b820191906000526020600020905b8154815290600101906020018083116102bf57829003601f168201915b5050505050815250509050919050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103546001600160a01b03163314610346576000356001600160e01b0319166001604051620f948f60ea1b81526004016101ae92919061082c565b565b806001600160a01b03163b60000361037e57604051630bfc64a360e21b81526001600160a01b03821660048201526024016101ae565b50565b807fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600084600f8111156103b7576103b76107c2565b60ff168152602081019190915260400160002080546001600160a01b0319166001600160a01b03928316179055811682600f8111156103f8576103f86107c2565b6040517f865d1c228a8ea13709cfe61f346f7ff67f1bbd4a18ff31ad3e7147350d317c5990600090a35050565b805182546001600160a01b03199081166001600160a01b039283161784556020830151600185018054831691841691909117905560408301516002850180548316918416919091179055606083015160038501805483169184169190911790556080830151600485018054909216921691909117905560a081015160058301906104af90826108a9565b5080516040516001600160a01b03909116907fc9da0ae38bd4761b72da1045c9b2618f0cd991dcac01e1f9bbf68474025f074390600090a25050565b8035601081106101b757600080fd5b6001600160a01b038116811461037e57600080fd5b80356101b7816104fa565b6000806040838503121561052d57600080fd5b610536836104eb565b91506020830135610546816104fa565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561058a5761058a610551565b60405290565b600082601f8301126105a157600080fd5b813567ffffffffffffffff808211156105bc576105bc610551565b604051601f8301601f19908116603f011681019082821181831017156105e4576105e4610551565b816040528381528660208588010111156105fd57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561062f57600080fd5b813567ffffffffffffffff8082111561064757600080fd5b9083019060c0828603121561065b57600080fd5b610663610567565b823561066e816104fa565b8152602083013561067e816104fa565b60208201526040830135610691816104fa565b60408201526106a26060840161050f565b60608201526106b36080840161050f565b608082015260a0830135828111156106ca57600080fd5b6106d687828601610590565b60a08301525095945050505050565b6000602082840312156106f757600080fd5b610700826104eb565b9392505050565b60006020828403121561071957600080fd5b8135610700816104fa565b6000602080835260018060a01b03808551168285015280828601511660408501528060408601511660608501528060608601511660808501528060808601511660a08501525060a084015160c08085015280518060e086015260005b8181101561079d5782810184015186820161010001528301610780565b506101009250600083828701015282601f19601f830116860101935050505092915050565b634e487b7160e01b600052602160045260246000fd5b60208101601083106107ec576107ec6107c2565b91905290565b600181811c9082168061080657607f821691505b60208210810361082657634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160e01b031983168152604081016009831061084d5761084d6107c2565b8260208301529392505050565b601f8211156108a457600081815260208120601f850160051c810160208610156108815750805b601f850160051c820191505b818110156108a05782815560010161088d565b5050505b505050565b815167ffffffffffffffff8111156108c3576108c3610551565b6108d7816108d184546107f2565b8461085a565b602080601f83116001811461090c57600084156108f45750858301515b600019600386901b1c1916600185901b1785556108a0565b600085815260208120601f198616915b8281101561093b5788860151825594840194600190910190840161091c565b50858210156109595787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000811000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c8063865e6fd31461005157806392d4875614610066578063de981f1b14610079578063f4660940146100a9575b600080fd5b61006461005f36600461051a565b6100c9565b005b61006461007436600461061d565b6100e8565b61008c6100873660046106e5565b610138565b6040516001600160a01b0390911681526020015b60405180910390f35b6100bc6100b7366004610707565b6101bc565b6040516100a09190610724565b6100d16102ec565b6100da81610348565b6100e48282610381565b5050565b6100f06102ec565b80516001600160a01b03908116600090815260208190526040902080549091161561012e5760405163249b38f960e01b815260040160405180910390fd5b6100e48183610425565b60007fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600083600f81111561016f5761016f6107c2565b60ff1681526020810191909152604001600020546001600160a01b03169050806101b7578160405163409140df60e11b81526004016101ae91906107d8565b60405180910390fd5b919050565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082019290925260a08101919091526001600160a01b0380831660009081526020818152604091829020825160c081018452815485168152600182015485169281019290925260028101548416928201929092526003820154831660608201526004820154909216608083015260058101805460a084019190610263906107f2565b80601f016020809104026020016040519081016040528092919081815260200182805461028f906107f2565b80156102dc5780601f106102b1576101008083540402835291602001916102dc565b820191906000526020600020905b8154815290600101906020018083116102bf57829003601f168201915b5050505050815250509050919050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103546001600160a01b03163314610346576000356001600160e01b0319166001604051620f948f60ea1b81526004016101ae92919061082c565b565b806001600160a01b03163b60000361037e57604051630bfc64a360e21b81526001600160a01b03821660048201526024016101ae565b50565b807fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600084600f8111156103b7576103b76107c2565b60ff168152602081019190915260400160002080546001600160a01b0319166001600160a01b03928316179055811682600f8111156103f8576103f86107c2565b6040517f865d1c228a8ea13709cfe61f346f7ff67f1bbd4a18ff31ad3e7147350d317c5990600090a35050565b805182546001600160a01b03199081166001600160a01b039283161784556020830151600185018054831691841691909117905560408301516002850180548316918416919091179055606083015160038501805483169184169190911790556080830151600485018054909216921691909117905560a081015160058301906104af90826108a9565b5080516040516001600160a01b03909116907fc9da0ae38bd4761b72da1045c9b2618f0cd991dcac01e1f9bbf68474025f074390600090a25050565b8035601081106101b757600080fd5b6001600160a01b038116811461037e57600080fd5b80356101b7816104fa565b6000806040838503121561052d57600080fd5b610536836104eb565b91506020830135610546816104fa565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561058a5761058a610551565b60405290565b600082601f8301126105a157600080fd5b813567ffffffffffffffff808211156105bc576105bc610551565b604051601f8301601f19908116603f011681019082821181831017156105e4576105e4610551565b816040528381528660208588010111156105fd57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561062f57600080fd5b813567ffffffffffffffff8082111561064757600080fd5b9083019060c0828603121561065b57600080fd5b610663610567565b823561066e816104fa565b8152602083013561067e816104fa565b60208201526040830135610691816104fa565b60408201526106a26060840161050f565b60608201526106b36080840161050f565b608082015260a0830135828111156106ca57600080fd5b6106d687828601610590565b60a08301525095945050505050565b6000602082840312156106f757600080fd5b610700826104eb565b9392505050565b60006020828403121561071957600080fd5b8135610700816104fa565b6000602080835260018060a01b03808551168285015280828601511660408501528060408601511660608501528060608601511660808501528060808601511660a08501525060a084015160c08085015280518060e086015260005b8181101561079d5782810184015186820161010001528301610780565b506101009250600083828701015282601f19601f830116860101935050505092915050565b634e487b7160e01b600052602160045260246000fd5b60208101601083106107ec576107ec6107c2565b91905290565b600181811c9082168061080657607f821691505b60208210810361082657634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160e01b031983168152604081016009831061084d5761084d6107c2565b8260208301529392505050565b601f8211156108a457600081815260208120601f850160051c810160208610156108815750805b601f850160051c820191505b818110156108a05782815560010161088d565b5050505b505050565b815167ffffffffffffffff8111156108c3576108c3610551565b6108d7816108d184546107f2565b8461085a565b602080601f83116001811461090c57600084156108f45750858301515b600019600386901b1c1916600185901b1785556108a0565b600085815260208120601f198616915b8281101561093b5788860151825594840194600190910190840161091c565b50858210156109595787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000811000a", + "numDeployments": 2, + "solcInputHash": "6d67256db1844d3deb1c932d686229ba", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"enum ContractType\",\"name\":\"contractType\",\"type\":\"uint8\"}],\"name\":\"ErrContractTypeNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ErrExistentProfile\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ErrNonExistentProfile\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"msgSig\",\"type\":\"bytes4\"},{\"internalType\":\"enum RoleAccess\",\"name\":\"expectedRole\",\"type\":\"uint8\"}],\"name\":\"ErrUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"ErrZeroCodeContract\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enum ContractType\",\"name\":\"contractType\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"ContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"ProfileAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"enum RoleAccess\",\"name\":\"addressType\",\"type\":\"uint8\"}],\"name\":\"ProfileAddressChanged\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"consensus\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"treasury\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"pubkey\",\"type\":\"bytes\"}],\"internalType\":\"struct IProfile.CandidateProfile\",\"name\":\"profile\",\"type\":\"tuple\"}],\"name\":\"addNewProfile\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum ContractType\",\"name\":\"contractType\",\"type\":\"uint8\"}],\"name\":\"getContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"contract_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"}],\"name\":\"getId2Profile\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"consensus\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"treasury\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"pubkey\",\"type\":\"bytes\"}],\"internalType\":\"struct IProfile.CandidateProfile\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"validatorContract\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"id\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"consensus\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"treasury\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"pubkey\",\"type\":\"bytes\"}],\"internalType\":\"struct IProfile.CandidateProfile\",\"name\":\"profile\",\"type\":\"tuple\"}],\"name\":\"registerProfile\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum ContractType\",\"name\":\"contractType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ErrContractTypeNotFound(uint8)\":[{\"details\":\"Error of invalid role.\"}],\"ErrExistentProfile()\":[{\"details\":\"Error of already existed profile.\"}],\"ErrNonExistentProfile()\":[{\"details\":\"Error of non existed profile.\"}],\"ErrUnauthorized(bytes4,uint8)\":[{\"details\":\"Error indicating that the caller is unauthorized to perform a specific function.\",\"params\":{\"expectedRole\":\"The role required to perform the function.\",\"msgSig\":\"The function signature (bytes4) that the caller is unauthorized to perform.\"}}],\"ErrZeroCodeContract(address)\":[{\"details\":\"Error of set to non-contract.\"}]},\"kind\":\"dev\",\"methods\":{\"addNewProfile((address,address,address,address,address,bytes))\":{\"details\":\"Requirements: - The profile must not be existent before. - Only contract admin can call this method.\"},\"getContract(uint8)\":{\"details\":\"Returns the address of a contract with a specific role. Throws an error if no contract is set for the specified role.\",\"params\":{\"contractType\":\"The role of the contract to retrieve.\"},\"returns\":{\"contract_\":\"The address of the contract with the specified role.\"}},\"getId2Profile(address)\":{\"details\":\"Getter to query full `profile` from `id` address.\"},\"registerProfile((address,address,address,address,address,bytes))\":{\"details\":\"Requirements: - The profile must not be existent before. - Only user with candidate admin role can call this method.\"},\"setContract(uint8,address)\":{\"details\":\"Sets the address of a contract with a specific role. Emits the event {ContractUpdated}.\",\"params\":{\"addr\":\"The address of the contract to set.\",\"contractType\":\"The role of the contract to set.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addNewProfile((address,address,address,address,address,bytes))\":{\"notice\":\"Add a new profile.\"},\"registerProfile((address,address,address,address,address,bytes))\":{\"notice\":\"The candidate admin registers a new profile.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ronin/profile/Profile.sol\":\"Profile\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0xa2b22da3032e50b55f95ec1d13336102d675f341167aa76db571ef7f8bb7975d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(\\n Address.isContract(IBeacon(newBeacon).implementation()),\\n \\\"ERC1967: beacon implementation is not a contract\\\"\\n );\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xabf3f59bc0e5423eae45e459dbe92e7052c6983628d39008590edc852a62f94a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overridden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0xa6a787e7a901af6511e19aa53e1a00352db215a011d2c7a438d0582dd5da76f9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\\n * initialization step. This is essential to configure modules that are added through upgrades and that require\\n * initialization.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd5c50c54bf02740ebd122ff06832546cb5fa84486d52695a9ccfd11666e0c81d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/extensions/TransparentUpgradeableProxyV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol\\\";\\n\\ncontract TransparentUpgradeableProxyV2 is TransparentUpgradeableProxy {\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable TransparentUpgradeableProxy(_logic, admin_, _data) {}\\n\\n /**\\n * @dev Calls a function from the current implementation as specified by `_data`, which should be an encoded function call.\\n *\\n * Requirements:\\n * - Only the admin can call this function.\\n *\\n * Note: The proxy admin is not allowed to interact with the proxy logic through the fallback function to avoid\\n * triggering some unexpected logic. This is to allow the administrator to explicitly call the proxy, please consider\\n * reviewing the encoded data `_data` and the method which is called before using this.\\n *\\n */\\n function functionDelegateCall(bytes memory _data) public payable ifAdmin {\\n address _addr = _implementation();\\n assembly {\\n let _result := delegatecall(gas(), _addr, add(_data, 32), mload(_data), 0, 0)\\n returndatacopy(0, 0, returndatasize())\\n switch _result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6609392ea7d3174439b5715100bee82528fe6e4aff28927d48c27db8475e88c5\",\"license\":\"MIT\"},\"contracts/extensions/collections/HasContracts.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { HasProxyAdmin } from \\\"./HasProxyAdmin.sol\\\";\\nimport \\\"../../interfaces/collections/IHasContracts.sol\\\";\\nimport { IdentityGuard } from \\\"../../utils/IdentityGuard.sol\\\";\\nimport { ErrUnexpectedInternalCall } from \\\"../../utils/CommonErrors.sol\\\";\\n\\n/**\\n * @title HasContracts\\n * @dev A contract that provides functionality to manage multiple contracts with different roles.\\n */\\nabstract contract HasContracts is HasProxyAdmin, IHasContracts, IdentityGuard {\\n /// @dev value is equal to keccak256(\\\"@ronin.dpos.collections.HasContracts.slot\\\") - 1\\n bytes32 private constant _STORAGE_SLOT = 0xdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb;\\n\\n /**\\n * @dev Modifier to restrict access to functions only to contracts with a specific role.\\n * @param contractType The contract type that allowed to call\\n */\\n modifier onlyContract(ContractType contractType) virtual {\\n _requireContract(contractType);\\n _;\\n }\\n\\n /**\\n * @inheritdoc IHasContracts\\n */\\n function setContract(ContractType contractType, address addr) external virtual onlyAdmin {\\n _requireHasCode(addr);\\n _setContract(contractType, addr);\\n }\\n\\n /**\\n * @inheritdoc IHasContracts\\n */\\n function getContract(ContractType contractType) public view returns (address contract_) {\\n contract_ = _getContractMap()[uint8(contractType)];\\n if (contract_ == address(0)) revert ErrContractTypeNotFound(contractType);\\n }\\n\\n /**\\n * @dev Internal function to set the address of a contract with a specific role.\\n * @param contractType The contract type of the contract to set.\\n * @param addr The address of the contract to set.\\n */\\n function _setContract(ContractType contractType, address addr) internal virtual {\\n _getContractMap()[uint8(contractType)] = addr;\\n emit ContractUpdated(contractType, addr);\\n }\\n\\n /**\\n * @dev Internal function to access the mapping of contract addresses with roles.\\n * @return contracts_ The mapping of contract addresses with roles.\\n */\\n function _getContractMap() private pure returns (mapping(uint8 => address) storage contracts_) {\\n assembly {\\n contracts_.slot := _STORAGE_SLOT\\n }\\n }\\n\\n /**\\n * @dev Internal function to check if the calling contract has a specific role.\\n * @param contractType The contract type that the calling contract must have.\\n * @dev Throws an error if the calling contract does not have the specified role.\\n */\\n function _requireContract(ContractType contractType) private view {\\n if (msg.sender != getContract(contractType)) {\\n revert ErrUnexpectedInternalCall(msg.sig, contractType, msg.sender);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9e1dceb68827adfb8c8184662f29ab5fe14e292a632878150e3b0b6c61bc1dce\",\"license\":\"MIT\"},\"contracts/extensions/collections/HasProxyAdmin.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/StorageSlot.sol\\\";\\nimport \\\"../../utils/CommonErrors.sol\\\";\\n\\nabstract contract HasProxyAdmin {\\n // bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n modifier onlyAdmin() {\\n _requireAdmin();\\n _;\\n }\\n\\n /**\\n * @dev Returns proxy admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n function _requireAdmin() internal view {\\n if (msg.sender != _getAdmin()) revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN);\\n }\\n}\\n\",\"keccak256\":\"0x0916021d04ea0c93c54978dc2fd46575fd2bd867369fbf9ce49f316939ddaf25\",\"license\":\"MIT\"},\"contracts/interfaces/IProfile.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"../utils/RoleAccess.sol\\\";\\n\\ninterface IProfile {\\n struct CandidateProfile {\\n /**\\n * @dev Primary key of the profile, use for backward querying.\\n *\\n * {Staking} Contract: index of pool\\n * {RoninValidatorSet} Contract: index of almost all data related to a validator\\n *\\n */\\n address id;\\n /// @dev Consensus address.\\n address consensus;\\n /// @dev Pool admin address.\\n address admin;\\n /// @dev Treasury address.\\n address payable treasury;\\n /// @dev Address to voting proposal.\\n address governor;\\n /// @dev Public key for fast finality.\\n bytes pubkey;\\n }\\n\\n /// @dev Event emitted when a profile with `id` is added.\\n event ProfileAdded(address indexed id);\\n /// @dev Event emitted when a address in a profile is changed.\\n event ProfileAddressChanged(address indexed id, RoleAccess indexed addressType);\\n\\n /// @dev Error of already existed profile.\\n error ErrExistentProfile();\\n /// @dev Error of non existed profile.\\n error ErrNonExistentProfile();\\n\\n /// @dev Getter to query full `profile` from `id` address.\\n function getId2Profile(address id) external view returns (CandidateProfile memory profile);\\n\\n /**\\n * @notice Add a new profile.\\n *\\n * @dev Requirements:\\n * - The profile must not be existent before.\\n * - Only contract admin can call this method.\\n */\\n function addNewProfile(CandidateProfile memory profile) external;\\n\\n /**\\n * @notice The candidate admin registers a new profile.\\n *\\n * @dev Requirements:\\n * - The profile must not be existent before.\\n * - Only user with candidate admin role can call this method.\\n */\\n\\n function registerProfile(CandidateProfile memory profile) external;\\n}\\n\",\"keccak256\":\"0x2bc0c3ae35a3de7a028b58ffa47d929b74e1e9eef402db81fd9c76540ff5a4d3\",\"license\":\"MIT\"},\"contracts/interfaces/collections/IHasContracts.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport { ContractType } from \\\"../../utils/ContractType.sol\\\";\\n\\ninterface IHasContracts {\\n /// @dev Error of invalid role.\\n error ErrContractTypeNotFound(ContractType contractType);\\n\\n /// @dev Emitted when a contract is updated.\\n event ContractUpdated(ContractType indexed contractType, address indexed addr);\\n\\n /**\\n * @dev Returns the address of a contract with a specific role.\\n * Throws an error if no contract is set for the specified role.\\n *\\n * @param contractType The role of the contract to retrieve.\\n * @return contract_ The address of the contract with the specified role.\\n */\\n function getContract(ContractType contractType) external view returns (address contract_);\\n\\n /**\\n * @dev Sets the address of a contract with a specific role.\\n * Emits the event {ContractUpdated}.\\n * @param contractType The role of the contract to set.\\n * @param addr The address of the contract to set.\\n */\\n function setContract(ContractType contractType, address addr) external;\\n}\\n\",\"keccak256\":\"0x99d8213d857e30d367155abd15dc42730afdfbbac3a22dfb3b95ffea2083a92e\",\"license\":\"MIT\"},\"contracts/interfaces/validator/ICandidateManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\ninterface ICandidateManager {\\n struct ValidatorCandidate {\\n // Admin of the candidate\\n address admin;\\n // Address of the validator that produces block, e.g. block.coinbase. This is so-called validator address.\\n address consensusAddr;\\n // Address that receives mining reward of the validator\\n address payable treasuryAddr;\\n // Address of the bridge operator corresponding to the candidate\\n address ______deprecatedbridgeOperatorAddr;\\n // The percentage of reward that validators can be received, the rest goes to the delegators.\\n // Values in range [0; 100_00] stands for 0-100%\\n uint256 commissionRate;\\n // The timestamp that scheduled to revoke the candidate (no schedule=0)\\n uint256 revokingTimestamp;\\n // The deadline that the candidate must top up staking amount to keep it larger than or equal to the threshold (no deadline=0)\\n uint256 topupDeadline;\\n }\\n\\n struct CommissionSchedule {\\n // The timestamp that the commission schedule gets affected (no schedule=0).\\n uint256 effectiveTimestamp;\\n // The new commission rate. Value is in range [0; 100_00], stands for 0-100%\\n uint256 commissionRate;\\n }\\n\\n /// @dev Emitted when the maximum number of validator candidates is updated.\\n event MaxValidatorCandidateUpdated(uint256 threshold);\\n /// @dev Emitted when the min offset to the effective date of commission rate change is updated.\\n event MinEffectiveDaysOnwardsUpdated(uint256 numOfDays);\\n /// @dev Emitted when the validator candidate is granted.\\n event CandidateGranted(address indexed consensusAddr, address indexed treasuryAddr, address indexed admin);\\n /// @dev Emitted when the revoking timestamp of a candidate is updated.\\n event CandidateRevokingTimestampUpdated(address indexed consensusAddr, uint256 revokingTimestamp);\\n /// @dev Emitted when the topup deadline of a candidate is updated.\\n event CandidateTopupDeadlineUpdated(address indexed consensusAddr, uint256 topupDeadline);\\n /// @dev Emitted when the validator candidate is revoked.\\n event CandidatesRevoked(address[] consensusAddrs);\\n\\n /// @dev Emitted when a schedule for updating commission rate is set.\\n event CommissionRateUpdateScheduled(address indexed consensusAddr, uint256 effectiveTimestamp, uint256 rate);\\n /// @dev Emitted when the commission rate of a validator is updated.\\n event CommissionRateUpdated(address indexed consensusAddr, uint256 rate);\\n\\n /// @dev Error of exceeding maximum number of candidates.\\n error ErrExceedsMaxNumberOfCandidate();\\n /// @dev Error of querying for already existent candidate.\\n error ErrExistentCandidate();\\n /// @dev Error of querying for non-existent candidate.\\n error ErrNonExistentCandidate();\\n /// @dev Error of candidate admin already exists.\\n error ErrExistentCandidateAdmin(address _candidateAdminAddr);\\n /// @dev Error of treasury already exists.\\n error ErrExistentTreasury(address _treasuryAddr);\\n /// @dev Error of invalid commission rate.\\n error ErrInvalidCommissionRate();\\n /// @dev Error of invalid effective days onwards.\\n error ErrInvalidEffectiveDaysOnwards();\\n /// @dev Error of invalid min effective days onwards.\\n error ErrInvalidMinEffectiveDaysOnwards();\\n /// @dev Error of already requested revoking candidate before.\\n error ErrAlreadyRequestedRevokingCandidate();\\n /// @dev Error of commission change schedule exists.\\n error ErrAlreadyRequestedUpdatingCommissionRate();\\n /// @dev Error of trusted org cannot renounce.\\n error ErrTrustedOrgCannotRenounce();\\n\\n /**\\n * @dev Returns the maximum number of validator candidate.\\n */\\n function maxValidatorCandidate() external view returns (uint256);\\n\\n /**\\n * @dev Returns the minimum number of days to the effective date of commission rate change.\\n */\\n function minEffectiveDaysOnward() external view returns (uint256);\\n\\n /**\\n * @dev Sets the maximum number of validator candidate.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the `MaxValidatorCandidateUpdated` event.\\n *\\n */\\n function setMaxValidatorCandidate(uint256) external;\\n\\n /**\\n * @dev Sets the minimum number of days to the effective date of commision rate change.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the `MinEffectiveDaysOnwardsUpdated` event.\\n *\\n */\\n function setMinEffectiveDaysOnwards(uint256 _numOfDays) external;\\n\\n /**\\n * @dev Grants a validator candidate.\\n *\\n * Requirements:\\n * - The method caller is staking contract.\\n *\\n * Emits the event `CandidateGranted`.\\n *\\n */\\n function execApplyValidatorCandidate(\\n address _admin,\\n address _consensusAddr,\\n address payable _treasuryAddr,\\n uint256 _commissionRate\\n ) external;\\n\\n /**\\n * @dev Requests to revoke a validator candidate in next `_secsLeft` seconds.\\n *\\n * Requirements:\\n * - The method caller is staking contract.\\n *\\n * Emits the event `CandidateRevokingTimestampUpdated`.\\n *\\n */\\n function execRequestRenounceCandidate(address, uint256 _secsLeft) external;\\n\\n /**\\n * @dev Fallback function of `CandidateStaking-requestUpdateCommissionRate`.\\n *\\n * Requirements:\\n * - The method caller is the staking contract.\\n * - The `_effectiveTimestamp` must be the beginning of a UTC day, and at least from 7 days onwards\\n * - The `_rate` must be in range of [0_00; 100_00].\\n *\\n * Emits the event `CommissionRateUpdateScheduled`.\\n *\\n */\\n function execRequestUpdateCommissionRate(address _consensusAddr, uint256 _effectiveTimestamp, uint256 _rate) external;\\n\\n /**\\n * @dev Returns whether the address is a validator (candidate).\\n */\\n function isValidatorCandidate(address _addr) external view returns (bool);\\n\\n /**\\n * @dev Returns the validator candidate.\\n */\\n function getValidatorCandidates() external view returns (address[] memory);\\n\\n /**\\n * @dev Returns all candidate info.\\n */\\n function getCandidateInfos() external view returns (ValidatorCandidate[] memory);\\n\\n /**\\n * @dev Returns the info of a candidate.\\n */\\n function getCandidateInfo(address _candidate) external view returns (ValidatorCandidate memory);\\n\\n /**\\n * @dev Returns whether the address is the candidate admin.\\n */\\n function isCandidateAdmin(address _candidate, address _admin) external view returns (bool);\\n\\n /**\\n * @dev Returns the schedule of changing commission rate of a candidate address.\\n */\\n function getCommissionChangeSchedule(address _candidate) external view returns (CommissionSchedule memory);\\n}\\n\",\"keccak256\":\"0x97dae7e2ed43c21c48200581501bfa065c7836299306ba2e7f39896c3a22ef2d\",\"license\":\"MIT\"},\"contracts/interfaces/validator/ICoinbaseExecution.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"./ISlashingExecution.sol\\\";\\n\\ninterface ICoinbaseExecution is ISlashingExecution {\\n enum BlockRewardDeprecatedType {\\n UNKNOWN,\\n UNAVAILABILITY,\\n AFTER_BAILOUT\\n }\\n\\n /// @dev Emitted when the validator set is updated\\n event ValidatorSetUpdated(uint256 indexed period, address[] consensusAddrs);\\n /// @dev Emitted when the bridge operator set is updated, to mirror the in-jail and maintaining status of the validator.\\n event BlockProducerSetUpdated(uint256 indexed period, uint256 indexed epoch, address[] consensusAddrs);\\n /// @dev Emitted when the bridge operator set is updated.\\n event BridgeOperatorSetUpdated(uint256 indexed period, uint256 indexed epoch, address[] bridgeOperators);\\n\\n /// @dev Emitted when the reward of the block producer is deprecated.\\n event BlockRewardDeprecated(\\n address indexed coinbaseAddr,\\n uint256 rewardAmount,\\n BlockRewardDeprecatedType deprecatedType\\n );\\n /// @dev Emitted when the block reward is submitted.\\n event BlockRewardSubmitted(address indexed coinbaseAddr, uint256 submittedAmount, uint256 bonusAmount);\\n\\n /// @dev Emitted when the block producer reward is distributed.\\n event MiningRewardDistributed(address indexed consensusAddr, address indexed recipient, uint256 amount);\\n /// @dev Emitted when the contract fails when distributing the block producer reward.\\n event MiningRewardDistributionFailed(\\n address indexed consensusAddr,\\n address indexed recipient,\\n uint256 amount,\\n uint256 contractBalance\\n );\\n\\n /// @dev Emitted when the bridge operator reward is distributed.\\n event BridgeOperatorRewardDistributed(\\n address indexed consensusAddr,\\n address indexed bridgeOperator,\\n address indexed recipientAddr,\\n uint256 amount\\n );\\n /// @dev Emitted when the contract fails when distributing the bridge operator reward.\\n event BridgeOperatorRewardDistributionFailed(\\n address indexed consensusAddr,\\n address indexed bridgeOperator,\\n address indexed recipient,\\n uint256 amount,\\n uint256 contractBalance\\n );\\n\\n /// @dev Emitted when the fast finality reward is distributed.\\n event FastFinalityRewardDistributed(address indexed consensusAddr, address indexed recipient, uint256 amount);\\n /// @dev Emitted when the contract fails when distributing the fast finality reward.\\n event FastFinalityRewardDistributionFailed(\\n address indexed consensusAddr,\\n address indexed recipient,\\n uint256 amount,\\n uint256 contractBalance\\n );\\n\\n /// @dev Emitted when the amount of RON reward is distributed to staking contract.\\n event StakingRewardDistributed(uint256 totalAmount, address[] consensusAddrs, uint256[] amounts);\\n /// @dev Emitted when the contracts fails when distributing the amount of RON to the staking contract.\\n event StakingRewardDistributionFailed(\\n uint256 totalAmount,\\n address[] consensusAddrs,\\n uint256[] amounts,\\n uint256 contractBalance\\n );\\n\\n /// @dev Emitted when the epoch is wrapped up.\\n event WrappedUpEpoch(uint256 indexed periodNumber, uint256 indexed epochNumber, bool periodEnding);\\n\\n /// @dev Error of only allowed at the end of epoch\\n error ErrAtEndOfEpochOnly();\\n /// @dev Error of query for already wrapped up epoch\\n error ErrAlreadyWrappedEpoch();\\n\\n /**\\n * @dev Submits reward of the current block.\\n *\\n * Requirements:\\n * - The method caller is coinbase.\\n *\\n * Emits the event `MiningRewardDeprecated` if the coinbase is slashed or no longer be a block producer.\\n * Emits the event `BlockRewardSubmitted` for the valid call.\\n *\\n */\\n function submitBlockReward() external payable;\\n\\n /**\\n * @dev Wraps up the current epoch.\\n *\\n * Requirements:\\n * - The method must be called when the current epoch is ending.\\n * - The epoch is not wrapped yet.\\n * - The method caller is coinbase.\\n *\\n * Emits the event `MiningRewardDistributed` when some validator has reward distributed.\\n * Emits the event `StakingRewardDistributed` when some staking pool has reward distributed.\\n * Emits the event `BlockProducerSetUpdated` when the epoch is wrapped up.\\n * Emits the event `BridgeOperatorSetUpdated` when the epoch is wrapped up at period ending.\\n * Emits the event `ValidatorSetUpdated` when the epoch is wrapped up at period ending, and the validator set gets updated.\\n * Emits the event `WrappedUpEpoch`.\\n *\\n */\\n function wrapUpEpoch() external payable;\\n}\\n\",\"keccak256\":\"0x22f546add63b1b6e62929bdd4052fa032af55ebf50981dc22d208fe53ad1b0a3\",\"license\":\"MIT\"},\"contracts/interfaces/validator/IEmergencyExit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\ninterface IEmergencyExit {\\n /// @dev Emitted when the fund is locked from an emergency exit request\\n event EmergencyExitRequested(address indexed consensusAddr, uint256 lockedAmount);\\n /// @dev Emitted when the fund that locked from an emergency exit request is transferred to the recipient.\\n event EmergencyExitLockedFundReleased(\\n address indexed consensusAddr,\\n address indexed recipient,\\n uint256 unlockedAmount\\n );\\n /// @dev Emitted when the fund that locked from an emergency exit request is failed to transferred back.\\n event EmergencyExitLockedFundReleasingFailed(\\n address indexed consensusAddr,\\n address indexed recipient,\\n uint256 unlockedAmount,\\n uint256 contractBalance\\n );\\n\\n /// @dev Emitted when the emergency exit locked amount is updated.\\n event EmergencyExitLockedAmountUpdated(uint256 amount);\\n /// @dev Emitted when the emergency expiry duration is updated.\\n event EmergencyExpiryDurationUpdated(uint256 amount);\\n\\n /// @dev Error of already requested emergency exit before.\\n error ErrAlreadyRequestedEmergencyExit();\\n\\n /**\\n * @dev Returns the amount of RON to lock from a consensus address.\\n */\\n function emergencyExitLockedAmount() external returns (uint256);\\n\\n /**\\n * @dev Returns the duration that an emergency request is expired and the fund will be recycled.\\n */\\n function emergencyExpiryDuration() external returns (uint256);\\n\\n /**\\n * @dev Sets the amount of RON to lock from a consensus address.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the event `EmergencyExitLockedAmountUpdated`.\\n *\\n */\\n function setEmergencyExitLockedAmount(uint256 _emergencyExitLockedAmount) external;\\n\\n /**\\n * @dev Sets the duration that an emergency request is expired and the fund will be recycled.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the event `EmergencyExpiryDurationUpdated`.\\n *\\n */\\n function setEmergencyExpiryDuration(uint256 _emergencyExpiryDuration) external;\\n\\n /**\\n * @dev Unlocks fund for emergency exit request.\\n *\\n * Requirements:\\n * - The method caller is admin.\\n *\\n * Emits the event `EmergencyExitLockedFundReleased` if the fund is successfully unlocked.\\n * Emits the event `EmergencyExitLockedFundReleasingFailed` if the fund is failed to unlock.\\n *\\n */\\n function execReleaseLockedFundForEmergencyExitRequest(address _consensusAddr, address payable _recipient) external;\\n\\n /**\\n * @dev Fallback function of `IStaking-requestEmergencyExit`.\\n *\\n * Requirements:\\n * - The method caller is staking contract.\\n *\\n */\\n function execEmergencyExit(address _consensusAddr, uint256 _secLeftToRevoke) external;\\n}\\n\",\"keccak256\":\"0x45161abd1e3db83052a06889a0e3a7a5e7ee3306478601d58ac4ed32ccaa75ad\",\"license\":\"MIT\"},\"contracts/interfaces/validator/IRoninValidatorSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"./ICandidateManager.sol\\\";\\nimport \\\"./info-fragments/ICommonInfo.sol\\\";\\nimport \\\"./ICoinbaseExecution.sol\\\";\\nimport \\\"./ISlashingExecution.sol\\\";\\nimport \\\"./IEmergencyExit.sol\\\";\\n\\ninterface IRoninValidatorSet is\\n ICandidateManager,\\n ICommonInfo,\\n ISlashingExecution,\\n ICoinbaseExecution,\\n IEmergencyExit\\n{}\\n\",\"keccak256\":\"0x813f34747aea4dfb53bbc147abf8dbe5999ce73111c2db99bcb3efb4cf75bb3d\",\"license\":\"MIT\"},\"contracts/interfaces/validator/ISlashingExecution.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\ninterface ISlashingExecution {\\n /// @dev Emitted when the validator is punished.\\n event ValidatorPunished(\\n address indexed consensusAddr,\\n uint256 indexed period,\\n uint256 jailedUntil,\\n uint256 deductedStakingAmount,\\n bool blockProducerRewardDeprecated,\\n bool bridgeOperatorRewardDeprecated\\n );\\n /// @dev Emitted when the validator get out of jail by bailout.\\n event ValidatorUnjailed(address indexed validator, uint256 period);\\n\\n /// @dev Error of cannot bailout due to high tier slash.\\n error ErrCannotBailout(address validator);\\n\\n /**\\n * @dev Finalize the slash request from slash indicator contract.\\n *\\n * Requirements:\\n * - The method caller is slash indicator contract.\\n *\\n * Emits the event `ValidatorPunished`.\\n *\\n */\\n function execSlash(address validatorAddr, uint256 newJailedUntil, uint256 slashAmount, bool cannotBailout) external;\\n\\n /**\\n * @dev Finalize the bailout request from slash indicator contract.\\n *\\n * Requirements:\\n * - The method caller is slash indicator contract.\\n *\\n * Emits the event `ValidatorUnjailed`.\\n *\\n */\\n function execBailOut(address _validatorAddr, uint256 _period) external;\\n}\\n\",\"keccak256\":\"0xac0b772f2fca9dafd7cc6742f91b442f9f545bf9472185b8d817fe045b680193\",\"license\":\"MIT\"},\"contracts/interfaces/validator/info-fragments/ICommonInfo.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"./IJailingInfo.sol\\\";\\nimport \\\"./ITimingInfo.sol\\\";\\nimport \\\"./IValidatorInfoV2.sol\\\";\\n\\ninterface ICommonInfo is ITimingInfo, IJailingInfo, IValidatorInfoV2 {\\n struct EmergencyExitInfo {\\n uint256 lockedAmount;\\n // The timestamp that this locked amount will be recycled to staking vesting contract\\n uint256 recyclingAt;\\n }\\n\\n /// @dev Emitted when the deprecated reward is withdrawn.\\n event DeprecatedRewardRecycled(address indexed recipientAddr, uint256 amount);\\n /// @dev Emitted when the deprecated reward withdrawal is failed\\n event DeprecatedRewardRecycleFailed(address indexed recipientAddr, uint256 amount, uint256 balance);\\n\\n /// @dev Error thrown when receives RON from neither staking vesting contract nor staking contract\\n error ErrUnauthorizedReceiveRON();\\n /// @dev Error thrown when queries for a non existent info.\\n error NonExistentRecyclingInfo();\\n\\n /**\\n * @dev Returns the total deprecated reward, which includes reward that is not sent for slashed validators and unsastified bridge operators\\n */\\n function totalDeprecatedReward() external view returns (uint256);\\n\\n /**\\n * @dev Returns the emergency exit request.\\n */\\n function getEmergencyExitInfo(address _consensusAddr) external view returns (EmergencyExitInfo memory);\\n}\\n\",\"keccak256\":\"0x3fdfa86da33b889e5153075ffc028d6b0c607480a96b532fbbbc48ac7bbf27c9\",\"license\":\"MIT\"},\"contracts/interfaces/validator/info-fragments/IJailingInfo.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\ninterface IJailingInfo {\\n /**\\n * @dev Returns whether the validator are put in jail (cannot join the set of validators) during the current period.\\n */\\n function checkJailed(address) external view returns (bool);\\n\\n /**\\n * @dev Returns whether the validator are put in jail and the number of block and epoch that he still is in the jail.\\n */\\n function getJailedTimeLeft(\\n address _addr\\n ) external view returns (bool isJailed_, uint256 blockLeft_, uint256 epochLeft_);\\n\\n /**\\n * @dev Returns whether the validator are put in jail (cannot join the set of validators) at a specific block.\\n */\\n function checkJailedAtBlock(address _addr, uint256 _blockNum) external view returns (bool);\\n\\n /**\\n * @dev Returns whether the validator are put in jail at a specific block and the number of block and epoch that he still is in the jail.\\n */\\n function getJailedTimeLeftAtBlock(\\n address _addr,\\n uint256 _blockNum\\n ) external view returns (bool isJailed_, uint256 blockLeft_, uint256 epochLeft_);\\n\\n /**\\n * @dev Returns whether the validators are put in jail (cannot join the set of validators) during the current period.\\n */\\n function checkManyJailed(address[] calldata) external view returns (bool[] memory);\\n\\n /**\\n * @dev Returns whether the incoming reward of the block producer is deprecated during the current period.\\n */\\n function checkMiningRewardDeprecated(address _blockProducer) external view returns (bool);\\n\\n /**\\n * @dev Returns whether the incoming reward of the block producer is deprecated during a specific period.\\n */\\n function checkMiningRewardDeprecatedAtPeriod(address _blockProducer, uint256 _period) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2b1846b05ca1d636299fb929c1bd7b392b236f5e3f7aa3e7eea2c6d57b8836fb\",\"license\":\"MIT\"},\"contracts/interfaces/validator/info-fragments/ITimingInfo.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\ninterface ITimingInfo {\\n /**\\n * @dev Returns the block that validator set was updated.\\n */\\n function getLastUpdatedBlock() external view returns (uint256);\\n\\n /**\\n * @dev Returns the number of blocks in a epoch.\\n */\\n function numberOfBlocksInEpoch() external view returns (uint256 _numberOfBlocks);\\n\\n /**\\n * @dev Returns the epoch index from the block number.\\n */\\n function epochOf(uint256 _block) external view returns (uint256);\\n\\n /**\\n * @dev Returns whether the epoch ending is at the block number `_block`.\\n */\\n function epochEndingAt(uint256 _block) external view returns (bool);\\n\\n /**\\n * @dev Tries to get the period index from the epoch number.\\n */\\n function tryGetPeriodOfEpoch(uint256 _epoch) external view returns (bool _filled, uint256 _periodNumber);\\n\\n /**\\n * @dev Returns whether the period ending at the current block number.\\n */\\n function isPeriodEnding() external view returns (bool);\\n\\n /**\\n * @dev Returns the period index from the current block.\\n */\\n function currentPeriod() external view returns (uint256);\\n\\n /**\\n * @dev Returns the block number that the current period starts at.\\n */\\n function currentPeriodStartAtBlock() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x77b86a68149389fed0eb0c5b8d56f278d3bd103ba64f504697d709b24c3212d5\",\"license\":\"MIT\"},\"contracts/interfaces/validator/info-fragments/IValidatorInfoV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"../../../libraries/EnumFlags.sol\\\";\\n\\ninterface IValidatorInfoV2 {\\n /**\\n * @dev Error thrown when an invalid maximum prioritized validator number is provided.\\n */\\n error ErrInvalidMaxPrioritizedValidatorNumber();\\n\\n /// @dev Emitted when the number of max validator is updated.\\n event MaxValidatorNumberUpdated(uint256);\\n /// @dev Emitted when the number of reserved slots for prioritized validators is updated.\\n event MaxPrioritizedValidatorNumberUpdated(uint256);\\n\\n /**\\n * @dev Returns the maximum number of validators in the epoch.\\n */\\n function maxValidatorNumber() external view returns (uint256 _maximumValidatorNumber);\\n\\n /**\\n * @dev Returns the number of reserved slots for prioritized validators.\\n */\\n function maxPrioritizedValidatorNumber() external view returns (uint256 _maximumPrioritizedValidatorNumber);\\n\\n /**\\n * @dev Returns the current validator list.\\n */\\n function getValidators() external view returns (address[] memory _validatorList);\\n\\n /**\\n * @dev Returns the current block producer list.\\n */\\n function getBlockProducers() external view returns (address[] memory);\\n\\n /**\\n * @dev Returns whether the address is block producer or not.\\n */\\n function isBlockProducer(address _addr) external view returns (bool);\\n\\n /**\\n * @dev Returns total numbers of the block producers.\\n */\\n function totalBlockProducer() external view returns (uint256);\\n\\n /**\\n * @dev Updates the max validator number\\n *\\n * Requirements:\\n * - The method caller is admin\\n *\\n * Emits the event `MaxValidatorNumberUpdated`\\n *\\n */\\n function setMaxValidatorNumber(uint256 _maxValidatorNumber) external;\\n\\n /**\\n * @dev Updates the number of reserved slots for prioritized validators\\n *\\n * Requirements:\\n * - The method caller is admin\\n *\\n * Emits the event `MaxPrioritizedValidatorNumberUpdated`\\n *\\n */\\n function setMaxPrioritizedValidatorNumber(uint256 _maxPrioritizedValidatorNumber) external;\\n}\\n\",\"keccak256\":\"0x6823181ac93ea3320e6ebfb456624afda59ac2acb480de5c774783983c8f4749\",\"license\":\"MIT\"},\"contracts/libraries/AddressArrayUtils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.8.0;\\n\\nlibrary AddressArrayUtils {\\n /**\\n * @dev Error thrown when a duplicated element is detected in an array.\\n * @param msgSig The function signature that invoke the error.\\n */\\n error ErrDuplicated(bytes4 msgSig);\\n\\n /**\\n * @dev Returns whether or not there's a duplicate. Runs in O(n^2).\\n * @param A Array to search\\n * @return Returns true if duplicate, false otherwise\\n */\\n function hasDuplicate(address[] memory A) internal pure returns (bool) {\\n if (A.length == 0) {\\n return false;\\n }\\n unchecked {\\n for (uint256 i = 0; i < A.length - 1; i++) {\\n for (uint256 j = i + 1; j < A.length; j++) {\\n if (A[i] == A[j]) {\\n return true;\\n }\\n }\\n }\\n }\\n return false;\\n }\\n\\n /**\\n * @dev Returns whether two arrays of addresses are equal or not.\\n */\\n function isEqual(address[] memory _this, address[] memory _other) internal pure returns (bool yes_) {\\n // Hashing two arrays and compare their hash\\n assembly {\\n let _thisHash := keccak256(add(_this, 32), mul(mload(_this), 32))\\n let _otherHash := keccak256(add(_other, 32), mul(mload(_other), 32))\\n yes_ := eq(_thisHash, _otherHash)\\n }\\n }\\n\\n /**\\n * @dev Return the concatenated array from a and b.\\n */\\n function extend(address[] memory a, address[] memory b) internal pure returns (address[] memory c) {\\n uint256 lengthA = a.length;\\n uint256 lengthB = b.length;\\n unchecked {\\n c = new address[](lengthA + lengthB);\\n }\\n uint256 i;\\n for (; i < lengthA; ) {\\n c[i] = a[i];\\n unchecked {\\n ++i;\\n }\\n }\\n for (uint256 j; j < lengthB; ) {\\n c[i] = b[j];\\n unchecked {\\n ++i;\\n ++j;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaf760162653a85d6e1b24df4d33c74076f778470112f421a02050fb981242001\",\"license\":\"UNLICENSED\"},\"contracts/libraries/EnumFlags.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This library implements checking flag of an enumerated value.\\n * The originated idea is inherited from [Enum.HashFlag(Enum)](https://learn.microsoft.com/en-us/dotnet/api/system.enum.hasflag?view=net-6.0) method of C#.\\n */\\nlibrary EnumFlags {\\n enum ValidatorFlag {\\n None, // bit(00)\\n BlockProducer, // bit(01)\\n DeprecatedBridgeOperator, // bit(10)\\n Both // bit(11)\\n }\\n\\n function isNone(ValidatorFlag _value) internal pure returns (bool) {\\n return uint8(_value) == 0;\\n }\\n\\n /**\\n * @dev Checks if `_value` has `_flag`.\\n */\\n function hasFlag(ValidatorFlag _value, ValidatorFlag _flag) internal pure returns (bool) {\\n return (uint8(_value) & uint8(_flag)) != 0;\\n }\\n\\n /**\\n * @dev Calculate new value of `_value` after adding `_flag`.\\n */\\n function addFlag(ValidatorFlag _value, ValidatorFlag _flag) internal pure returns (ValidatorFlag) {\\n return ValidatorFlag(uint8(_value) | uint8(_flag));\\n }\\n\\n /**\\n * @dev Calculate new value of `_value` after remove `_flag`.\\n */\\n function removeFlag(ValidatorFlag _value, ValidatorFlag _flag) internal pure returns (ValidatorFlag) {\\n return ValidatorFlag(uint8(_value) & ~uint8(_flag));\\n }\\n}\\n\",\"keccak256\":\"0xa712f0d1a323ee39f23eb3ee3278b4ec25fe2e536b1ccc629578c66f277c088d\",\"license\":\"UNLICENSED\"},\"contracts/ronin/profile/Profile.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\nimport \\\"@openzeppelin/contracts/proxy/utils/Initializable.sol\\\";\\nimport \\\"../../interfaces/validator/IRoninValidatorSet.sol\\\";\\nimport \\\"../../interfaces/IProfile.sol\\\";\\nimport { ErrUnauthorized, RoleAccess } from \\\"../../utils/CommonErrors.sol\\\";\\nimport \\\"./ProfileStorage.sol\\\";\\n\\npragma solidity ^0.8.9;\\n\\ncontract Profile is IProfile, ProfileStorage, Initializable {\\n constructor() {\\n _disableInitializers();\\n }\\n\\n function initialize(address validatorContract) external initializer {\\n _setContract(ContractType.VALIDATOR, validatorContract);\\n }\\n\\n /**\\n * @inheritdoc IProfile\\n */\\n function getId2Profile(address id) external view returns (CandidateProfile memory) {\\n return _id2Profile[id];\\n }\\n\\n /**\\n * @inheritdoc IProfile\\n */\\n function addNewProfile(CandidateProfile memory profile) external onlyAdmin {\\n CandidateProfile storage _profile = _id2Profile[profile.id];\\n if (_profile.id != address(0)) revert ErrExistentProfile();\\n _addNewProfile(_profile, profile);\\n }\\n\\n /**\\n * @inheritdoc IProfile\\n */\\n function registerProfile(CandidateProfile memory profile) external {\\n CandidateProfile storage _profile = _id2Profile[profile.id];\\n if (_profile.id != address(0)) revert ErrExistentProfile();\\n if (\\n msg.sender != profile.admin ||\\n !IRoninValidatorSet(getContract(ContractType.VALIDATOR)).isCandidateAdmin(profile.consensus, profile.admin)\\n ) revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN);\\n\\n _addNewProfile(_profile, profile);\\n }\\n}\\n\",\"keccak256\":\"0xaf351686bba10b243ce53644815d390a606cbb1df119239b273f2f28c7e91bc9\",\"license\":\"MIT\"},\"contracts/ronin/profile/ProfileStorage.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.9;\\n\\nimport \\\"../../extensions/collections/HasContracts.sol\\\";\\nimport { IProfile } from \\\"../../interfaces/IProfile.sol\\\";\\n\\nabstract contract ProfileStorage is IProfile, HasContracts {\\n /// @dev Mapping from id address => candidate profile.\\n mapping(address => CandidateProfile) internal _id2Profile;\\n /// @dev Upgradeable gap.\\n bytes32[50] __gap;\\n\\n /**\\n * @dev Add a profile from memory to storage.\\n */\\n function _addNewProfile(CandidateProfile storage _profile, CandidateProfile memory newProfile) internal {\\n _profile.id = newProfile.id;\\n _profile.consensus = newProfile.consensus;\\n _profile.admin = newProfile.admin;\\n _profile.treasury = newProfile.treasury;\\n _profile.governor = newProfile.governor;\\n _profile.pubkey = newProfile.pubkey;\\n\\n emit ProfileAdded(newProfile.id);\\n }\\n\\n /**\\n * @dev Get an existed profile struct from id. Revert if the profile does not exists.\\n */\\n function _getId2ProfileHelper(address id) internal view returns (CandidateProfile storage _profile) {\\n _profile = _id2Profile[id];\\n if (_profile.id == address(0)) revert ErrNonExistentProfile();\\n }\\n}\\n\",\"keccak256\":\"0x212a824f8f86eb566ea74c1fa9147043f0d8f27b1ddff2e167c073949d784581\",\"license\":\"MIT\"},\"contracts/utils/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { ContractType } from \\\"./ContractType.sol\\\";\\nimport { RoleAccess } from \\\"./RoleAccess.sol\\\";\\n\\nerror ErrSyncTooFarPeriod(uint256 period, uint256 latestRewardedPeriod);\\n/**\\n * @dev Error thrown when an address is expected to be an already created externally owned account (EOA).\\n * This error indicates that the provided address is invalid for certain contract operations that require already created EOA.\\n */\\nerror ErrAddressIsNotCreatedEOA(address addr, bytes32 codehash);\\n/**\\n * @dev Error raised when a bridge operator update operation fails.\\n * @param bridgeOperator The address of the bridge operator that failed to update.\\n */\\nerror ErrBridgeOperatorUpdateFailed(address bridgeOperator);\\n/**\\n * @dev Error thrown when attempting to add a bridge operator that already exists in the contract.\\n * This error indicates that the provided bridge operator address is already registered as a bridge operator in the contract.\\n */\\nerror ErrBridgeOperatorAlreadyExisted(address bridgeOperator);\\n/**\\n * @dev The error indicating an unsupported interface.\\n * @param interfaceId The bytes4 interface identifier that is not supported.\\n * @param addr The address where the unsupported interface was encountered.\\n */\\nerror ErrUnsupportedInterface(bytes4 interfaceId, address addr);\\n/**\\n * @dev Error thrown when the return data from a callback function is invalid.\\n * @param callbackFnSig The signature of the callback function that returned invalid data.\\n * @param register The address of the register where the callback function was invoked.\\n * @param returnData The invalid return data received from the callback function.\\n */\\nerror ErrInvalidReturnData(bytes4 callbackFnSig, address register, bytes returnData);\\n/**\\n * @dev Error of set to non-contract.\\n */\\nerror ErrZeroCodeContract(address addr);\\n/**\\n * @dev Error indicating that arguments are invalid.\\n */\\nerror ErrInvalidArguments(bytes4 msgSig);\\n/**\\n * @dev Error indicating that given address is null when it should not.\\n */\\nerror ErrZeroAddress(bytes4 msgSig);\\n/**\\n * @dev Error indicating that the provided threshold is invalid for a specific function signature.\\n * @param msgSig The function signature (bytes4) that the invalid threshold applies to.\\n */\\nerror ErrInvalidThreshold(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a function can only be called by the contract itself.\\n * @param msgSig The function signature (bytes4) that can only be called by the contract itself.\\n */\\nerror ErrOnlySelfCall(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\\n * @param msgSig The function signature (bytes4) that the caller is unauthorized to perform.\\n * @param expectedRole The role required to perform the function.\\n */\\nerror ErrUnauthorized(bytes4 msgSig, RoleAccess expectedRole);\\n\\n/**\\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\\n * @param msgSig The function signature (bytes4) that the caller is unauthorized to perform.\\n */\\nerror ErrUnauthorizedCall(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\\n * @param msgSig The function signature (bytes4).\\n * @param expectedContractType The contract type required to perform the function.\\n * @param actual The actual address that called to the function.\\n */\\nerror ErrUnexpectedInternalCall(bytes4 msgSig, ContractType expectedContractType, address actual);\\n\\n/**\\n * @dev Error indicating that an array is empty when it should contain elements.\\n */\\nerror ErrEmptyArray();\\n\\n/**\\n * @dev Error indicating a mismatch in the length of input parameters or arrays for a specific function.\\n * @param msgSig The function signature (bytes4) that has a length mismatch.\\n */\\nerror ErrLengthMismatch(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a proxy call to an external contract has failed.\\n * @param msgSig The function signature (bytes4) of the proxy call that failed.\\n * @param extCallSig The function signature (bytes4) of the external contract call that failed.\\n */\\nerror ErrProxyCallFailed(bytes4 msgSig, bytes4 extCallSig);\\n\\n/**\\n * @dev Error indicating that a function tried to call a precompiled contract that is not allowed.\\n * @param msgSig The function signature (bytes4) that attempted to call a precompiled contract.\\n */\\nerror ErrCallPrecompiled(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a native token transfer has failed.\\n * @param msgSig The function signature (bytes4) of the token transfer that failed.\\n */\\nerror ErrNativeTransferFailed(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that an order is invalid.\\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid order.\\n */\\nerror ErrInvalidOrder(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that the chain ID is invalid.\\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid chain ID.\\n * @param actual Current chain ID that executing function.\\n * @param expected Expected chain ID required for the tx to success.\\n */\\nerror ErrInvalidChainId(bytes4 msgSig, uint256 actual, uint256 expected);\\n\\n/**\\n * @dev Error indicating that a vote type is not supported.\\n * @param msgSig The function signature (bytes4) of the operation that encountered an unsupported vote type.\\n */\\nerror ErrUnsupportedVoteType(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that the proposal nonce is invalid.\\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid proposal nonce.\\n */\\nerror ErrInvalidProposalNonce(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a voter has already voted.\\n * @param voter The address of the voter who has already voted.\\n */\\nerror ErrAlreadyVoted(address voter);\\n\\n/**\\n * @dev Error indicating that a signature is invalid for a specific function signature.\\n * @param msgSig The function signature (bytes4) that encountered an invalid signature.\\n */\\nerror ErrInvalidSignatures(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a relay call has failed.\\n * @param msgSig The function signature (bytes4) of the relay call that failed.\\n */\\nerror ErrRelayFailed(bytes4 msgSig);\\n/**\\n * @dev Error indicating that a vote weight is invalid for a specific function signature.\\n * @param msgSig The function signature (bytes4) that encountered an invalid vote weight.\\n */\\nerror ErrInvalidVoteWeight(bytes4 msgSig);\\n\\n/**\\n * @dev Error indicating that a query was made for an outdated bridge operator set.\\n */\\nerror ErrQueryForOutdatedBridgeOperatorSet();\\n\\n/**\\n * @dev Error indicating that a request is invalid.\\n */\\nerror ErrInvalidRequest();\\n\\n/**\\n * @dev Error indicating that a token standard is invalid.\\n */\\nerror ErrInvalidTokenStandard();\\n\\n/**\\n * @dev Error indicating that a token is not supported.\\n */\\nerror ErrUnsupportedToken();\\n\\n/**\\n * @dev Error indicating that a receipt kind is invalid.\\n */\\nerror ErrInvalidReceiptKind();\\n\\n/**\\n * @dev Error indicating that a receipt is invalid.\\n */\\nerror ErrInvalidReceipt();\\n\\n/**\\n * @dev Error indicating that an address is not payable.\\n */\\nerror ErrNonpayableAddress(address);\\n\\n/**\\n * @dev Error indicating that the period is already processed, i.e. scattered reward.\\n */\\nerror ErrPeriodAlreadyProcessed(uint256 requestingPeriod, uint256 latestPeriod);\\n\\n/**\\n * @dev Error thrown when an invalid vote hash is provided.\\n */\\nerror ErrInvalidVoteHash();\\n\\n/**\\n * @dev Error thrown when querying for an empty vote.\\n */\\nerror ErrQueryForEmptyVote();\\n\\n/**\\n * @dev Error thrown when querying for an expired vote.\\n */\\nerror ErrQueryForExpiredVote();\\n\\n/**\\n * @dev Error thrown when querying for a non-existent vote.\\n */\\nerror ErrQueryForNonExistentVote();\\n\\n/**\\n * @dev Error indicating that the method is only called once per block.\\n */\\nerror ErrOncePerBlock();\\n\\n/**\\n * @dev Error of method caller must be coinbase\\n */\\nerror ErrCallerMustBeCoinbase();\\n\",\"keccak256\":\"0x22942c8fea2d1ca863ac1f9c1662d714b8ac0856684e36f8aaf19508648c1053\",\"license\":\"MIT\"},\"contracts/utils/ContractType.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum ContractType {\\n /* 0 */ UNKNOWN,\\n /* 1 */ PAUSE_ENFORCER,\\n /* 2 */ BRIDGE,\\n /* 3 */ BRIDGE_TRACKING,\\n /* 4 */ GOVERNANCE_ADMIN,\\n /* 5 */ MAINTENANCE,\\n /* 6 */ SLASH_INDICATOR,\\n /* 7 */ STAKING_VESTING,\\n /* 8 */ VALIDATOR,\\n /* 9 */ STAKING,\\n /* 10 */ RONIN_TRUSTED_ORGANIZATION,\\n /* 11 */ BRIDGE_MANAGER,\\n /* 12 */ BRIDGE_SLASH,\\n /* 13 */ BRIDGE_REWARD,\\n /* 14 */ FAST_FINALITY_TRACKING,\\n /* 15 */ PROFILE\\n}\\n\",\"keccak256\":\"0x7f547a44265f4c4b03d8971f7fc5eaa2e6064ea8cd509c1b761108f9800dab68\",\"license\":\"MIT\"},\"contracts/utils/IdentityGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport { AddressArrayUtils } from \\\"../libraries/AddressArrayUtils.sol\\\";\\nimport { IERC165 } from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport { TransparentUpgradeableProxyV2 } from \\\"../extensions/TransparentUpgradeableProxyV2.sol\\\";\\nimport { ErrAddressIsNotCreatedEOA, ErrZeroAddress, ErrOnlySelfCall, ErrZeroCodeContract, ErrUnsupportedInterface } from \\\"./CommonErrors.sol\\\";\\n\\nabstract contract IdentityGuard {\\n using AddressArrayUtils for address[];\\n\\n /// @dev value is equal to keccak256(abi.encode())\\n /// @dev see: https://eips.ethereum.org/EIPS/eip-1052\\n bytes32 internal constant CREATED_ACCOUNT_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n\\n /**\\n * @dev Modifier to restrict functions to only be called by this contract.\\n * @dev Reverts if the caller is not this contract.\\n */\\n modifier onlySelfCall() virtual {\\n _requireSelfCall();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to ensure that the elements in the `arr` array are non-duplicates.\\n * It calls the internal `_checkDuplicate` function to perform the duplicate check.\\n *\\n * Requirements:\\n * - The elements in the `arr` array must not contain any duplicates.\\n */\\n modifier nonDuplicate(address[] memory arr) virtual {\\n _requireNonDuplicate(arr);\\n _;\\n }\\n\\n /**\\n * @dev Internal method to check the method caller.\\n * @dev Reverts if the method caller is not this contract.\\n */\\n function _requireSelfCall() internal view virtual {\\n if (msg.sender != address(this)) revert ErrOnlySelfCall(msg.sig);\\n }\\n\\n /**\\n * @dev Internal function to check if a contract address has code.\\n * @param addr The address of the contract to check.\\n * @dev Throws an error if the contract address has no code.\\n */\\n function _requireHasCode(address addr) internal view {\\n if (addr.code.length == 0) revert ErrZeroCodeContract(addr);\\n }\\n\\n /**\\n * @dev Checks if an address is zero and reverts if it is.\\n * @param addr The address to check.\\n */\\n function _requireNonZeroAddress(address addr) internal pure {\\n if (addr == address(0)) revert ErrZeroAddress(msg.sig);\\n }\\n\\n /**\\n * @dev Check if arr is empty and revert if it is.\\n * Checks if an array contains any duplicate addresses and reverts if duplicates are found.\\n * @param arr The array of addresses to check.\\n */\\n function _requireNonDuplicate(address[] memory arr) internal pure {\\n if (arr.hasDuplicate()) revert AddressArrayUtils.ErrDuplicated(msg.sig);\\n }\\n\\n /**\\n * @dev Internal function to require that the provided address is a created externally owned account (EOA).\\n * This internal function is used to ensure that the provided address is a valid externally owned account (EOA).\\n * It checks the codehash of the address against a predefined constant to confirm that the address is a created EOA.\\n * @notice This method only works with non-state EOA accounts\\n */\\n function _requireCreatedEOA(address addr) internal view {\\n _requireNonZeroAddress(addr);\\n bytes32 codehash = addr.codehash;\\n if (codehash != CREATED_ACCOUNT_HASH) revert ErrAddressIsNotCreatedEOA(addr, codehash);\\n }\\n\\n /**\\n * @dev Internal function to require that the specified contract supports the given interface. This method handle in\\n * both case that the callee is either or not the proxy admin of the caller. If the contract does not support the\\n * interface `interfaceId` or EIP165, a revert with the corresponding error message is triggered.\\n *\\n * @param contractAddr The address of the contract to check for interface support.\\n * @param interfaceId The interface ID to check for support.\\n */\\n function _requireSupportsInterface(address contractAddr, bytes4 interfaceId) internal view {\\n bytes memory supportsInterfaceParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n (bool success, bytes memory returnOrRevertData) = contractAddr.staticcall(supportsInterfaceParams);\\n if (!success) {\\n (success, returnOrRevertData) = contractAddr.staticcall(\\n abi.encodeCall(TransparentUpgradeableProxyV2.functionDelegateCall, (supportsInterfaceParams))\\n );\\n if (!success) revert ErrUnsupportedInterface(interfaceId, contractAddr);\\n }\\n if (!abi.decode(returnOrRevertData, (bool))) revert ErrUnsupportedInterface(interfaceId, contractAddr);\\n }\\n}\\n\",\"keccak256\":\"0x2d0dfcef3636945bc1785c1fa5a05f5203c79cbb81b2eee92a3ac6a2378c2ce5\",\"license\":\"MIT\"},\"contracts/utils/RoleAccess.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum RoleAccess {\\n /* 0 */ UNKNOWN,\\n /* 1 */ ADMIN,\\n /* 2 */ COINBASE,\\n /* 3 */ GOVERNOR,\\n /* 4 */ CANDIDATE_ADMIN,\\n /* 5 */ WITHDRAWAL_MIGRATOR,\\n /* 6 */ __DEPRECATED_BRIDGE_OPERATOR,\\n /* 7 */ BLOCK_PRODUCER,\\n /* 8 */ VALIDATOR_CANDIDATE\\n}\\n\",\"keccak256\":\"0xa98cec38c640c4e37f475debbcd366226f1188c3f5ea6e29de768bd33e021873\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061001961001e565b6100de565b603354610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60335460ff90811610156100dc576033805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b610bfc806100ed6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063865e6fd3146100675780639029bc601461007c57806392d487561461008f578063c4d66de8146100a2578063de981f1b146100b5578063f4660940146100e5575b600080fd5b61007a61007536600461077e565b610105565b005b61007a61008a366004610881565b610124565b61007a61009d366004610881565b61024b565b61007a6100b0366004610949565b610291565b6100c86100c336600461096d565b6103a5565b6040516001600160a01b0390911681526020015b60405180910390f35b6100f86100f3366004610949565b610420565b6040516100dc9190610988565b61010d610550565b610116816105ac565b61012082826105e5565b5050565b80516001600160a01b0390811660009081526020819052604090208054909116156101625760405163249b38f960e01b815260040160405180910390fd5b81604001516001600160a01b0316336001600160a01b031614158061020a575061018c60086103a5565b602083015160408085015190516304d971ab60e01b81526001600160a01b03928316600482015290821660248201529116906304d971ab90604401602060405180830381865afa1580156101e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102089190610a26565b155b15610241576000356001600160e01b0319166001604051620f948f60ea1b8152600401610238929190610a5e565b60405180910390fd5b6101208183610689565b610253610550565b80516001600160a01b0390811660009081526020819052604090208054909116156102415760405163249b38f960e01b815260040160405180910390fd5b603354610100900460ff16158080156102b15750603354600160ff909116105b806102cb5750303b1580156102cb575060335460ff166001145b61032e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610238565b6033805460ff191660011790558015610351576033805461ff0019166101001790555b61035c6008836105e5565b8015610120576033805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b60007fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600083600f8111156103dc576103dc610a48565b60ff1681526020810191909152604001600020546001600160a01b031690508061041b578160405163409140df60e11b81526004016102389190610a8c565b919050565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082019290925260a08101919091526001600160a01b0380831660009081526020818152604091829020825160c081018452815485168152600182015485169281019290925260028101548416928201929092526003820154831660608201526004820154909216608083015260058101805460a0840191906104c790610aa6565b80601f01602080910402602001604051908101604052809291908181526020018280546104f390610aa6565b80156105405780601f1061051557610100808354040283529160200191610540565b820191906000526020600020905b81548152906001019060200180831161052357829003601f168201915b5050505050815250509050919050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103546001600160a01b031633146105aa576000356001600160e01b0319166001604051620f948f60ea1b8152600401610238929190610a5e565b565b806001600160a01b03163b6000036105e257604051630bfc64a360e21b81526001600160a01b0382166004820152602401610238565b50565b807fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600084600f81111561061b5761061b610a48565b60ff168152602081019190915260400160002080546001600160a01b0319166001600160a01b03928316179055811682600f81111561065c5761065c610a48565b6040517f865d1c228a8ea13709cfe61f346f7ff67f1bbd4a18ff31ad3e7147350d317c5990600090a35050565b805182546001600160a01b03199081166001600160a01b039283161784556020830151600185018054831691841691909117905560408301516002850180548316918416919091179055606083015160038501805483169184169190911790556080830151600485018054909216921691909117905560a081015160058301906107139082610b2f565b5080516040516001600160a01b03909116907fc9da0ae38bd4761b72da1045c9b2618f0cd991dcac01e1f9bbf68474025f074390600090a25050565b80356010811061041b57600080fd5b6001600160a01b03811681146105e257600080fd5b803561041b8161075e565b6000806040838503121561079157600080fd5b61079a8361074f565b915060208301356107aa8161075e565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156107ee576107ee6107b5565b60405290565b600082601f83011261080557600080fd5b813567ffffffffffffffff80821115610820576108206107b5565b604051601f8301601f19908116603f01168101908282118183101715610848576108486107b5565b8160405283815286602085880101111561086157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561089357600080fd5b813567ffffffffffffffff808211156108ab57600080fd5b9083019060c082860312156108bf57600080fd5b6108c76107cb565b82356108d28161075e565b815260208301356108e28161075e565b602082015260408301356108f58161075e565b604082015261090660608401610773565b606082015261091760808401610773565b608082015260a08301358281111561092e57600080fd5b61093a878286016107f4565b60a08301525095945050505050565b60006020828403121561095b57600080fd5b81356109668161075e565b9392505050565b60006020828403121561097f57600080fd5b6109668261074f565b6000602080835260018060a01b03808551168285015280828601511660408501528060408601511660608501528060608601511660808501528060808601511660a08501525060a084015160c08085015280518060e086015260005b81811015610a0157828101840151868201610100015283016109e4565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610a3857600080fd5b8151801515811461096657600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160e01b0319831681526040810160098310610a7f57610a7f610a48565b8260208301529392505050565b6020810160108310610aa057610aa0610a48565b91905290565b600181811c90821680610aba57607f821691505b602082108103610ada57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610b2a57600081815260208120601f850160051c81016020861015610b075750805b601f850160051c820191505b81811015610b2657828155600101610b13565b5050505b505050565b815167ffffffffffffffff811115610b4957610b496107b5565b610b5d81610b578454610aa6565b84610ae0565b602080601f831160018114610b925760008415610b7a5750858301515b600019600386901b1c1916600185901b178555610b26565b600085815260208120601f198616915b82811015610bc157888601518255948401946001909101908401610ba2565b5085821015610bdf5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000811000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c8063865e6fd3146100675780639029bc601461007c57806392d487561461008f578063c4d66de8146100a2578063de981f1b146100b5578063f4660940146100e5575b600080fd5b61007a61007536600461077e565b610105565b005b61007a61008a366004610881565b610124565b61007a61009d366004610881565b61024b565b61007a6100b0366004610949565b610291565b6100c86100c336600461096d565b6103a5565b6040516001600160a01b0390911681526020015b60405180910390f35b6100f86100f3366004610949565b610420565b6040516100dc9190610988565b61010d610550565b610116816105ac565b61012082826105e5565b5050565b80516001600160a01b0390811660009081526020819052604090208054909116156101625760405163249b38f960e01b815260040160405180910390fd5b81604001516001600160a01b0316336001600160a01b031614158061020a575061018c60086103a5565b602083015160408085015190516304d971ab60e01b81526001600160a01b03928316600482015290821660248201529116906304d971ab90604401602060405180830381865afa1580156101e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102089190610a26565b155b15610241576000356001600160e01b0319166001604051620f948f60ea1b8152600401610238929190610a5e565b60405180910390fd5b6101208183610689565b610253610550565b80516001600160a01b0390811660009081526020819052604090208054909116156102415760405163249b38f960e01b815260040160405180910390fd5b603354610100900460ff16158080156102b15750603354600160ff909116105b806102cb5750303b1580156102cb575060335460ff166001145b61032e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610238565b6033805460ff191660011790558015610351576033805461ff0019166101001790555b61035c6008836105e5565b8015610120576033805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b60007fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600083600f8111156103dc576103dc610a48565b60ff1681526020810191909152604001600020546001600160a01b031690508061041b578160405163409140df60e11b81526004016102389190610a8c565b919050565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082019290925260a08101919091526001600160a01b0380831660009081526020818152604091829020825160c081018452815485168152600182015485169281019290925260028101548416928201929092526003820154831660608201526004820154909216608083015260058101805460a0840191906104c790610aa6565b80601f01602080910402602001604051908101604052809291908181526020018280546104f390610aa6565b80156105405780601f1061051557610100808354040283529160200191610540565b820191906000526020600020905b81548152906001019060200180831161052357829003601f168201915b5050505050815250509050919050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103546001600160a01b031633146105aa576000356001600160e01b0319166001604051620f948f60ea1b8152600401610238929190610a5e565b565b806001600160a01b03163b6000036105e257604051630bfc64a360e21b81526001600160a01b0382166004820152602401610238565b50565b807fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600084600f81111561061b5761061b610a48565b60ff168152602081019190915260400160002080546001600160a01b0319166001600160a01b03928316179055811682600f81111561065c5761065c610a48565b6040517f865d1c228a8ea13709cfe61f346f7ff67f1bbd4a18ff31ad3e7147350d317c5990600090a35050565b805182546001600160a01b03199081166001600160a01b039283161784556020830151600185018054831691841691909117905560408301516002850180548316918416919091179055606083015160038501805483169184169190911790556080830151600485018054909216921691909117905560a081015160058301906107139082610b2f565b5080516040516001600160a01b03909116907fc9da0ae38bd4761b72da1045c9b2618f0cd991dcac01e1f9bbf68474025f074390600090a25050565b80356010811061041b57600080fd5b6001600160a01b03811681146105e257600080fd5b803561041b8161075e565b6000806040838503121561079157600080fd5b61079a8361074f565b915060208301356107aa8161075e565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156107ee576107ee6107b5565b60405290565b600082601f83011261080557600080fd5b813567ffffffffffffffff80821115610820576108206107b5565b604051601f8301601f19908116603f01168101908282118183101715610848576108486107b5565b8160405283815286602085880101111561086157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561089357600080fd5b813567ffffffffffffffff808211156108ab57600080fd5b9083019060c082860312156108bf57600080fd5b6108c76107cb565b82356108d28161075e565b815260208301356108e28161075e565b602082015260408301356108f58161075e565b604082015261090660608401610773565b606082015261091760808401610773565b608082015260a08301358281111561092e57600080fd5b61093a878286016107f4565b60a08301525095945050505050565b60006020828403121561095b57600080fd5b81356109668161075e565b9392505050565b60006020828403121561097f57600080fd5b6109668261074f565b6000602080835260018060a01b03808551168285015280828601511660408501528060408601511660608501528060608601511660808501528060808601511660a08501525060a084015160c08085015280518060e086015260005b81811015610a0157828101840151868201610100015283016109e4565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610a3857600080fd5b8151801515811461096657600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160e01b0319831681526040810160098310610a7f57610a7f610a48565b8260208301529392505050565b6020810160108310610aa057610aa0610a48565b91905290565b600181811c90821680610aba57607f821691505b602082108103610ada57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610b2a57600081815260208120601f850160051c81016020861015610b075750805b601f850160051c820191505b81811015610b2657828155600101610b13565b5050505b505050565b815167ffffffffffffffff811115610b4957610b496107b5565b610b5d81610b578454610aa6565b84610ae0565b602080601f831160018114610b925760008415610b7a5750858301515b600019600386901b1c1916600185901b178555610b26565b600085815260208120601f198616915b82811015610bc157888601518255948401946001909101908401610ba2565b5085821015610bdf5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000811000a", "devdoc": { "errors": { "ErrContractTypeNotFound(uint8)": [ @@ -336,6 +394,9 @@ "getId2Profile(address)": { "details": "Getter to query full `profile` from `id` address." }, + "registerProfile((address,address,address,address,address,bytes))": { + "details": "Requirements: - The profile must not be existent before. - Only user with candidate admin role can call this method." + }, "setContract(uint8,address)": { "details": "Sets the address of a contract with a specific role. Emits the event {ContractUpdated}.", "params": { @@ -351,6 +412,9 @@ "methods": { "addNewProfile((address,address,address,address,address,bytes))": { "notice": "Add a new profile." + }, + "registerProfile((address,address,address,address,address,bytes))": { + "notice": "The candidate admin registers a new profile." } }, "version": 1 @@ -358,15 +422,15 @@ "storageLayout": { "storage": [ { - "astId": 2229, + "astId": 31273, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "_id2Profile", "offset": 0, "slot": "0", - "type": "t_mapping(t_address,t_struct(CandidateProfile)1339_storage)" + "type": "t_mapping(t_address,t_struct(CandidateProfile)11502_storage)" }, { - "astId": 2234, + "astId": 31278, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "__gap", "offset": 0, @@ -374,7 +438,7 @@ "type": "t_array(t_bytes32)50_storage" }, { - "astId": 581, + "astId": 1373, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "_initialized", "offset": 0, @@ -382,7 +446,7 @@ "type": "t_uint8" }, { - "astId": 584, + "astId": 1376, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "_initializing", "offset": 1, @@ -422,19 +486,19 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_mapping(t_address,t_struct(CandidateProfile)1339_storage)": { + "t_mapping(t_address,t_struct(CandidateProfile)11502_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct IProfile.CandidateProfile)", "numberOfBytes": "32", - "value": "t_struct(CandidateProfile)1339_storage" + "value": "t_struct(CandidateProfile)11502_storage" }, - "t_struct(CandidateProfile)1339_storage": { + "t_struct(CandidateProfile)11502_storage": { "encoding": "inplace", "label": "struct IProfile.CandidateProfile", "members": [ { - "astId": 1323, + "astId": 11486, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "id", "offset": 0, @@ -442,7 +506,7 @@ "type": "t_address" }, { - "astId": 1326, + "astId": 11489, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "consensus", "offset": 0, @@ -450,7 +514,7 @@ "type": "t_address" }, { - "astId": 1329, + "astId": 11492, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "admin", "offset": 0, @@ -458,7 +522,7 @@ "type": "t_address" }, { - "astId": 1332, + "astId": 11495, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "treasury", "offset": 0, @@ -466,7 +530,7 @@ "type": "t_address_payable" }, { - "astId": 1335, + "astId": 11498, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "governor", "offset": 0, @@ -474,7 +538,7 @@ "type": "t_address" }, { - "astId": 1338, + "astId": 11501, "contract": "contracts/ronin/profile/Profile.sol:Profile", "label": "pubkey", "offset": 0, diff --git a/deployments/ronin-testnet/solcInputs/6d67256db1844d3deb1c932d686229ba.json b/deployments/ronin-testnet/solcInputs/6d67256db1844d3deb1c932d686229ba.json new file mode 100644 index 000000000..4a4b66096 --- /dev/null +++ b/deployments/ronin-testnet/solcInputs/6d67256db1844d3deb1c932d686229ba.json @@ -0,0 +1,634 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerable.sol\";\nimport \"./AccessControl.sol\";\nimport \"../utils/structs/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override {\n super._grantRole(role, account);\n _roleMembers[role].add(account);\n }\n\n /**\n * @dev Overload {_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override {\n super._revokeRole(role, account);\n _roleMembers[role].remove(account);\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/security/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n */\nabstract contract ERC20Pausable is ERC20, Pausable {\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../extensions/ERC20Burnable.sol\";\nimport \"../extensions/ERC20Pausable.sol\";\nimport \"../../../access/AccessControlEnumerable.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev {ERC20} token, including:\n *\n * - ability for holders to burn (destroy) their tokens\n * - a minter role that allows for token minting (creation)\n * - a pauser role that allows to stop all token transfers\n *\n * This contract uses {AccessControl} to lock permissioned functions using the\n * different roles - head to its documentation for details.\n *\n * The account that deploys the contract will be granted the minter and pauser\n * roles, as well as the default admin role, which will let it grant both minter\n * and pauser roles to other accounts.\n *\n * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._\n */\ncontract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /**\n * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the\n * account that deploys the contract.\n *\n * See {ERC20-constructor}.\n */\n constructor(string memory name, string memory symbol) ERC20(name, symbol) {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`.\n *\n * See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(address to, uint256 amount) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have minter role to mint\");\n _mint(to, amount);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to pause\");\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to unpause\");\n _unpause();\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20, ERC20Pausable) {\n super._beforeTokenTransfer(from, to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 && v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n return _values(set._inner);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "contracts/extensions/bridge-operator-governance/BridgeManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IBridgeManagerCallback, EnumerableSet, BridgeManagerCallbackRegister } from \"./BridgeManagerCallbackRegister.sol\";\nimport { IHasContracts, HasContracts } from \"../../extensions/collections/HasContracts.sol\";\nimport { IQuorum } from \"../../interfaces/IQuorum.sol\";\nimport { IBridgeManager } from \"../../interfaces/bridge/IBridgeManager.sol\";\nimport { AddressArrayUtils } from \"../../libraries/AddressArrayUtils.sol\";\nimport { ContractType } from \"../../utils/ContractType.sol\";\nimport { RoleAccess } from \"../../utils/RoleAccess.sol\";\nimport { TUint256Slot } from \"../../types/Types.sol\";\nimport \"../../utils/CommonErrors.sol\";\n\nabstract contract BridgeManager is IQuorum, IBridgeManager, BridgeManagerCallbackRegister, HasContracts {\n using AddressArrayUtils for address[];\n using EnumerableSet for EnumerableSet.AddressSet;\n\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.governorToBridgeOperatorInfo.slot\") - 1\n bytes32 private constant GOVERNOR_TO_BRIDGE_OPERATOR_INFO_SLOT =\n 0x88547008e60f5748911f2e59feb3093b7e4c2e87b2dd69d61f112fcc932de8e3;\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.govenorOf.slot\") - 1\n bytes32 private constant GOVENOR_OF_SLOT = 0x8400683eb2cb350596d73644c0c89fe45f108600003457374f4ab3e87b4f3aa3;\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.governors.slot\") - 1\n bytes32 private constant GOVERNOR_SET_SLOT = 0x546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c;\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.bridgeOperators.slot\") - 1\n bytes32 private constant BRIDGE_OPERATOR_SET_SLOT =\n 0xd38c234075fde25875da8a6b7e36b58b86681d483271a99eeeee1d78e258a24d;\n\n /**\n * @dev The numerator value used for calculations in the contract.\n * @notice value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.numerator.slot\") - 1\n */\n TUint256Slot internal constant NUMERATOR_SLOT =\n TUint256Slot.wrap(0xc55405a488814eaa0e2a685a0131142785b8d033d311c8c8244e34a7c12ca40f);\n\n /**\n * @dev The denominator value used for calculations in the contract.\n * @notice value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.denominator.slot\") - 1\n */\n TUint256Slot internal constant DENOMINATOR_SLOT =\n TUint256Slot.wrap(0xac1ff16a4f04f2a37a9ba5252a69baa100b460e517d1f8019c054a5ad698f9ff);\n\n /**\n * @dev The nonce value used for tracking nonces in the contract.\n * @notice value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.nonce.slot\") - 1\n */\n TUint256Slot internal constant NONCE_SLOT =\n TUint256Slot.wrap(0x92872d32822c9d44b36a2537d3e0d4c46fc4de1ce154ccfaed560a8a58445f1d);\n\n /**\n * @dev The total weight value used for storing the cumulative weight in the contract.\n * @notice value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.totalWeights.slot\") - 1\n */\n TUint256Slot internal constant TOTAL_WEIGHTS_SLOT =\n TUint256Slot.wrap(0x6924fe71b0c8b61aea02ca498b5f53b29bd95726278b1fe4eb791bb24a42644c);\n\n /**\n * @inheritdoc IBridgeManager\n */\n bytes32 public immutable DOMAIN_SEPARATOR;\n\n modifier onlyGovernor() virtual {\n _requireGovernor(msg.sender);\n _;\n }\n\n constructor(\n uint256 num,\n uint256 denom,\n uint256 roninChainId,\n address bridgeContract,\n address[] memory callbackRegisters,\n address[] memory bridgeOperators,\n address[] memory governors,\n uint96[] memory voteWeights\n ) payable BridgeManagerCallbackRegister(callbackRegisters) {\n NONCE_SLOT.store(1);\n\n _setThreshold(num, denom);\n _setContract(ContractType.BRIDGE, bridgeContract);\n\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,bytes32 salt)\"),\n keccak256(\"BridgeAdmin\"), // name hash\n keccak256(\"2\"), // version hash\n keccak256(abi.encode(\"BRIDGE_ADMIN\", roninChainId)) // salt\n )\n );\n\n _addBridgeOperators(voteWeights, governors, bridgeOperators);\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function addBridgeOperators(\n uint96[] calldata voteWeights,\n address[] calldata governors,\n address[] calldata bridgeOperators\n ) external onlySelfCall returns (bool[] memory addeds) {\n addeds = _addBridgeOperators(voteWeights, governors, bridgeOperators);\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function removeBridgeOperators(\n address[] calldata bridgeOperators\n ) external onlySelfCall returns (bool[] memory removeds) {\n removeds = _removeBridgeOperators(bridgeOperators);\n }\n\n /**\n * @inheritdoc IBridgeManager\n * @notice This method checks authorization by querying the corresponding operator of the msg.sender and then\n * attempts to remove it from the `_bridgeOperatorSet` for gas optimization. In case we allow a governor can leave\n * their operator address blank null `address(0)`, consider add authorization check.\n */\n function updateBridgeOperator(address newBridgeOperator) external onlyGovernor {\n _requireNonZeroAddress(newBridgeOperator);\n\n // Queries the previous bridge operator\n mapping(address => BridgeOperatorInfo) storage _gorvernorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo();\n address currentBridgeOperator = _gorvernorToBridgeOperatorInfo[msg.sender].addr;\n if (currentBridgeOperator == newBridgeOperator) {\n revert ErrBridgeOperatorAlreadyExisted(newBridgeOperator);\n }\n\n // Tries replace the bridge operator\n EnumerableSet.AddressSet storage _bridgeOperatorSet = _getBridgeOperatorSet();\n bool updated = _bridgeOperatorSet.remove(currentBridgeOperator) && _bridgeOperatorSet.add(newBridgeOperator);\n if (!updated) revert ErrBridgeOperatorUpdateFailed(newBridgeOperator);\n\n mapping(address => address) storage _governorOf = _getGovernorOf();\n delete _governorOf[currentBridgeOperator];\n _governorOf[newBridgeOperator] = msg.sender;\n _gorvernorToBridgeOperatorInfo[msg.sender].addr = newBridgeOperator;\n\n _notifyRegisters(\n IBridgeManagerCallback.onBridgeOperatorUpdated.selector,\n abi.encode(currentBridgeOperator, newBridgeOperator)\n );\n\n emit BridgeOperatorUpdated(msg.sender, currentBridgeOperator, newBridgeOperator);\n }\n\n /**\n * @inheritdoc IHasContracts\n */\n function setContract(ContractType contractType, address addr) external override onlySelfCall {\n _requireHasCode(addr);\n _setContract(contractType, addr);\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function setThreshold(\n uint256 numerator,\n uint256 denominator\n ) external override onlySelfCall returns (uint256, uint256) {\n return _setThreshold(numerator, denominator);\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getTotalWeight() public view returns (uint256) {\n return TOTAL_WEIGHTS_SLOT.load();\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getGovernorWeights(address[] calldata governors) external view returns (uint96[] memory weights) {\n weights = _getGovernorWeights(governors);\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getGovernorWeight(address governor) external view returns (uint96 weight) {\n weight = _getGovernorWeight(governor);\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function sumGovernorsWeight(\n address[] calldata governors\n ) external view nonDuplicate(governors) returns (uint256 sum) {\n sum = _sumGovernorsWeight(governors);\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function totalBridgeOperator() external view returns (uint256) {\n return _getBridgeOperatorSet().length();\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function isBridgeOperator(address addr) external view returns (bool) {\n return _getBridgeOperatorSet().contains(addr);\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getBridgeOperators() external view returns (address[] memory) {\n return _getBridgeOperators();\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getGovernors() external view returns (address[] memory) {\n return _getGovernors();\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getBridgeOperatorOf(address[] memory governors) public view returns (address[] memory bridgeOperators) {\n uint256 length = governors.length;\n bridgeOperators = new address[](length);\n\n mapping(address => BridgeOperatorInfo) storage _gorvernorToBridgeOperator = _getGovernorToBridgeOperatorInfo();\n for (uint256 i; i < length; ) {\n bridgeOperators[i] = _gorvernorToBridgeOperator[governors[i]].addr;\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getGovernorsOf(address[] calldata bridgeOperators) external view returns (address[] memory governors) {\n uint256 length = bridgeOperators.length;\n governors = new address[](length);\n mapping(address => address) storage _governorOf = _getGovernorOf();\n\n for (uint256 i; i < length; ) {\n governors[i] = _governorOf[bridgeOperators[i]];\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getFullBridgeOperatorInfos()\n external\n view\n returns (address[] memory governors, address[] memory bridgeOperators, uint96[] memory weights)\n {\n governors = _getGovernors();\n bridgeOperators = getBridgeOperatorOf(governors);\n weights = _getGovernorWeights(governors);\n }\n\n /**\n * @inheritdoc IBridgeManager\n */\n function getBridgeOperatorWeight(address bridgeOperator) external view returns (uint96 weight) {\n mapping(address => address) storage _governorOf = _getGovernorOf();\n mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo();\n weight = _governorToBridgeOperatorInfo[_governorOf[bridgeOperator]].voteWeight;\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function minimumVoteWeight() public view virtual returns (uint256) {\n return (NUMERATOR_SLOT.mul(TOTAL_WEIGHTS_SLOT.load()) + DENOMINATOR_SLOT.load() - 1) / DENOMINATOR_SLOT.load();\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function getThreshold() external view virtual returns (uint256 num_, uint256 denom_) {\n return (NUMERATOR_SLOT.load(), DENOMINATOR_SLOT.load());\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function checkThreshold(uint256 _voteWeight) external view virtual returns (bool) {\n return _voteWeight * DENOMINATOR_SLOT.load() >= NUMERATOR_SLOT.mul(TOTAL_WEIGHTS_SLOT.load());\n }\n\n /**\n * @dev Internal function to add bridge operators.\n *\n * This function adds the specified `bridgeOperators` to the bridge operator set and establishes the associated mappings.\n *\n * Requirements:\n * - The caller must have the necessary permission to add bridge operators.\n * - The lengths of `voteWeights`, `governors`, and `bridgeOperators` arrays must be equal.\n *\n * @param voteWeights An array of uint256 values representing the vote weights for each bridge operator.\n * @param governors An array of addresses representing the governors for each bridge operator.\n * @return addeds An array of boolean values indicating whether each bridge operator was successfully added.\n */\n function _addBridgeOperators(\n uint96[] memory voteWeights,\n address[] memory governors,\n address[] memory bridgeOperators\n ) internal nonDuplicate(governors.extend(bridgeOperators)) returns (bool[] memory addeds) {\n uint256 length = bridgeOperators.length;\n if (!(length == voteWeights.length && length == governors.length)) revert ErrLengthMismatch(msg.sig);\n addeds = new bool[](length);\n // simply skip add operations if inputs are empty.\n if (length == 0) return addeds;\n\n EnumerableSet.AddressSet storage _governorSet = _getGovernorsSet();\n mapping(address => address) storage _governorOf = _getGovernorOf();\n EnumerableSet.AddressSet storage _bridgeOperatorSet = _getBridgeOperatorSet();\n mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo();\n\n address governor;\n address bridgeOperator;\n uint256 accumulatedWeight;\n BridgeOperatorInfo memory bridgeOperatorInfo;\n\n for (uint256 i; i < length; ) {\n governor = governors[i];\n bridgeOperator = bridgeOperators[i];\n\n _requireNonZeroAddress(governor);\n _requireNonZeroAddress(bridgeOperator);\n if (voteWeights[i] == 0) revert ErrInvalidVoteWeight(msg.sig);\n\n addeds[i] = !(_governorSet.contains(governor) ||\n _governorSet.contains(bridgeOperator) ||\n _bridgeOperatorSet.contains(governor) ||\n _bridgeOperatorSet.contains(bridgeOperator));\n\n if (addeds[i]) {\n _governorSet.add(governor);\n _bridgeOperatorSet.add(bridgeOperator);\n _governorOf[bridgeOperator] = governor;\n bridgeOperatorInfo.addr = bridgeOperator;\n accumulatedWeight += bridgeOperatorInfo.voteWeight = voteWeights[i];\n _governorToBridgeOperatorInfo[governor] = bridgeOperatorInfo;\n }\n\n unchecked {\n ++i;\n }\n }\n\n TOTAL_WEIGHTS_SLOT.addAssign(accumulatedWeight);\n\n _notifyRegisters(IBridgeManagerCallback.onBridgeOperatorsAdded.selector, abi.encode(bridgeOperators, addeds));\n\n emit BridgeOperatorsAdded(addeds, voteWeights, governors, bridgeOperators);\n }\n\n /**\n * @dev Internal function to remove bridge operators.\n *\n * This function removes the specified `bridgeOperators` from the bridge operator set and related mappings.\n *\n * Requirements:\n * - The caller must have the necessary permission to remove bridge operators.\n *\n * @param bridgeOperators An array of addresses representing the bridge operators to be removed.\n * @return removeds An array of boolean values indicating whether each bridge operator was successfully removed.\n */\n function _removeBridgeOperators(\n address[] memory bridgeOperators\n ) internal nonDuplicate(bridgeOperators) returns (bool[] memory removeds) {\n uint256 length = bridgeOperators.length;\n removeds = new bool[](length);\n // simply skip remove operations if inputs are empty.\n if (length == 0) return removeds;\n\n mapping(address => address) storage _governorOf = _getGovernorOf();\n EnumerableSet.AddressSet storage _governorSet = _getGovernorsSet();\n EnumerableSet.AddressSet storage _bridgeOperatorSet = _getBridgeOperatorSet();\n mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo();\n\n address governor;\n address bridgeOperator;\n uint256 accumulatedWeight;\n BridgeOperatorInfo memory bridgeOperatorInfo;\n\n for (uint256 i; i < length; ) {\n bridgeOperator = bridgeOperators[i];\n governor = _governorOf[bridgeOperator];\n\n _requireNonZeroAddress(governor);\n _requireNonZeroAddress(bridgeOperator);\n\n bridgeOperatorInfo = _governorToBridgeOperatorInfo[governor];\n if (bridgeOperatorInfo.addr != bridgeOperator) revert ErrInvalidArguments(msg.sig);\n\n removeds[i] = _bridgeOperatorSet.contains(bridgeOperator) && _governorSet.contains(governor);\n if (removeds[i]) {\n _governorSet.remove(governor);\n _bridgeOperatorSet.remove(bridgeOperator);\n\n delete _governorOf[bridgeOperator];\n delete _governorToBridgeOperatorInfo[governor];\n accumulatedWeight += bridgeOperatorInfo.voteWeight;\n }\n\n unchecked {\n ++i;\n }\n }\n\n TOTAL_WEIGHTS_SLOT.subAssign(accumulatedWeight);\n\n _notifyRegisters(IBridgeManagerCallback.onBridgeOperatorsRemoved.selector, abi.encode(bridgeOperators, removeds));\n\n emit BridgeOperatorsRemoved(removeds, bridgeOperators);\n }\n\n /**\n * @dev Sets threshold and returns the old one.\n *\n * Emits the `ThresholdUpdated` event.\n *\n */\n function _setThreshold(\n uint256 numerator,\n uint256 denominator\n ) internal virtual returns (uint256 previousNum, uint256 previousDenom) {\n if (numerator > denominator) revert ErrInvalidThreshold(msg.sig);\n\n previousNum = NUMERATOR_SLOT.load();\n previousDenom = DENOMINATOR_SLOT.load();\n NUMERATOR_SLOT.store(numerator);\n DENOMINATOR_SLOT.store(denominator);\n\n emit ThresholdUpdated(NONCE_SLOT.postIncrement(), numerator, denominator, previousNum, previousDenom);\n }\n\n /**\n * @dev Internal function to get all bridge operators.\n * @return bridgeOperators An array containing all the registered bridge operator addresses.\n */\n function _getBridgeOperators() internal view returns (address[] memory) {\n return _getBridgeOperatorSet().values();\n }\n\n /**\n * @dev Internal function to get all governors.\n * @return governors An array containing all the registered governor addresses.\n */\n function _getGovernors() internal view returns (address[] memory) {\n return _getGovernorsSet().values();\n }\n\n /**\n * @dev Internal function to get the vote weights of a given array of governors.\n * @param governors An array containing the addresses of governors.\n * @return weights An array containing the vote weights of the corresponding governors.\n */\n function _getGovernorWeights(address[] memory governors) internal view returns (uint96[] memory weights) {\n uint256 length = governors.length;\n weights = new uint96[](length);\n mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo();\n for (uint256 i; i < length; ) {\n weights[i] = _governorToBridgeOperatorInfo[governors[i]].voteWeight;\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Internal function to calculate the sum of vote weights for a given array of governors.\n * @param governors An array containing the addresses of governors to calculate the sum of vote weights.\n * @return sum The total sum of vote weights for the provided governors.\n * @notice The input array `governors` must contain unique addresses to avoid duplicate calculations.\n */\n function _sumGovernorsWeight(address[] memory governors) internal view nonDuplicate(governors) returns (uint256 sum) {\n mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo();\n\n for (uint256 i; i < governors.length; ) {\n sum += _governorToBridgeOperatorInfo[governors[i]].voteWeight;\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Internal function to require that the caller has governor role access.\n * @param addr The address to check for governor role access.\n * @dev If the address does not have governor role access (vote weight is zero), a revert with the corresponding error message is triggered.\n */\n function _requireGovernor(address addr) internal view {\n if (_getGovernorWeight(addr) == 0) {\n revert ErrUnauthorized(msg.sig, RoleAccess.GOVERNOR);\n }\n }\n\n /**\n * @dev Internal function to retrieve the vote weight of a specific governor.\n * @param governor The address of the governor to get the vote weight for.\n * @return voteWeight The vote weight of the specified governor.\n */\n function _getGovernorWeight(address governor) internal view returns (uint96) {\n return _getGovernorToBridgeOperatorInfo()[governor].voteWeight;\n }\n\n /**\n * @dev Internal function to access the address set of bridge operators.\n * @return bridgeOperators the storage address set.\n */\n function _getBridgeOperatorSet() internal pure returns (EnumerableSet.AddressSet storage bridgeOperators) {\n assembly (\"memory-safe\") {\n bridgeOperators.slot := BRIDGE_OPERATOR_SET_SLOT\n }\n }\n\n /**\n * @dev Internal function to access the address set of bridge operators.\n * @return governors the storage address set.\n */\n function _getGovernorsSet() internal pure returns (EnumerableSet.AddressSet storage governors) {\n assembly (\"memory-safe\") {\n governors.slot := GOVERNOR_SET_SLOT\n }\n }\n\n /**\n * @dev Internal function to access the mapping from governor => BridgeOperatorInfo.\n * @return governorToBridgeOperatorInfo the mapping from governor => BridgeOperatorInfo.\n */\n function _getGovernorToBridgeOperatorInfo()\n internal\n pure\n returns (mapping(address => BridgeOperatorInfo) storage governorToBridgeOperatorInfo)\n {\n assembly (\"memory-safe\") {\n governorToBridgeOperatorInfo.slot := GOVERNOR_TO_BRIDGE_OPERATOR_INFO_SLOT\n }\n }\n\n /**\n * @dev Internal function to access the mapping from bridge operator => governor.\n * @return governorOf the mapping from bridge operator => governor.\n */\n function _getGovernorOf() internal pure returns (mapping(address => address) storage governorOf) {\n assembly (\"memory-safe\") {\n governorOf.slot := GOVENOR_OF_SLOT\n }\n }\n}\n" + }, + "contracts/extensions/bridge-operator-governance/BridgeManagerCallbackRegister.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { EnumerableSet } from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport { IBridgeManagerCallbackRegister } from \"../../interfaces/bridge/IBridgeManagerCallbackRegister.sol\";\nimport { IBridgeManagerCallback } from \"../../interfaces/bridge/IBridgeManagerCallback.sol\";\nimport { TransparentUpgradeableProxyV2, IdentityGuard } from \"../../utils/IdentityGuard.sol\";\n\n/**\n * @title BridgeManagerCallbackRegister\n * @dev A contract that manages callback registrations and execution for a bridge.\n */\nabstract contract BridgeManagerCallbackRegister is IdentityGuard, IBridgeManagerCallbackRegister {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n /**\n * @dev Storage slot for the address set of callback registers.\n * @dev Value is equal to keccak256(\"@ronin.dpos.gateway.BridgeAdmin.callbackRegisters.slot\") - 1.\n */\n bytes32 private constant CALLBACK_REGISTERS_SLOT = 0x5da136eb38f8d8e354915fc8a767c0dc81d49de5fb65d5477122a82ddd976240;\n\n constructor(address[] memory callbackRegisters) payable {\n _registerCallbacks(callbackRegisters);\n }\n\n /**\n * @inheritdoc IBridgeManagerCallbackRegister\n */\n function registerCallbacks(address[] calldata registers) external onlySelfCall returns (bool[] memory registereds) {\n registereds = _registerCallbacks(registers);\n }\n\n /**\n * @inheritdoc IBridgeManagerCallbackRegister\n */\n function unregisterCallbacks(\n address[] calldata registers\n ) external onlySelfCall returns (bool[] memory unregistereds) {\n unregistereds = _unregisterCallbacks(registers);\n }\n\n /**\n * @inheritdoc IBridgeManagerCallbackRegister\n */\n function getCallbackRegisters() external view returns (address[] memory registers) {\n registers = _getCallbackRegisters().values();\n }\n\n /**\n * @dev Internal function to register multiple callbacks with the bridge.\n * @param registers The array of callback addresses to register.\n * @return registereds An array indicating the success status of each registration.\n */\n function _registerCallbacks(\n address[] memory registers\n ) internal nonDuplicate(registers) returns (bool[] memory registereds) {\n uint256 length = registers.length;\n registereds = new bool[](length);\n if (length == 0) return registereds;\n\n EnumerableSet.AddressSet storage _callbackRegisters = _getCallbackRegisters();\n address register;\n bytes4 callbackInterface = type(IBridgeManagerCallback).interfaceId;\n\n for (uint256 i; i < length; ) {\n register = registers[i];\n\n _requireHasCode(register);\n _requireSupportsInterface(register, callbackInterface);\n\n registereds[i] = _callbackRegisters.add(register);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Internal function to unregister multiple callbacks from the bridge.\n * @param registers The array of callback addresses to unregister.\n * @return unregistereds An array indicating the success status of each unregistration.\n */\n function _unregisterCallbacks(\n address[] memory registers\n ) internal nonDuplicate(registers) returns (bool[] memory unregistereds) {\n uint256 length = registers.length;\n unregistereds = new bool[](length);\n EnumerableSet.AddressSet storage _callbackRegisters = _getCallbackRegisters();\n\n for (uint256 i; i < length; ) {\n unregistereds[i] = _callbackRegisters.remove(registers[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Internal function to notify all registered callbacks with the provided function signature and data.\n * @param callbackFnSig The function signature of the callback method.\n * @param inputs The data to pass to the callback method.\n */\n function _notifyRegisters(bytes4 callbackFnSig, bytes memory inputs) internal {\n address[] memory registers = _getCallbackRegisters().values();\n uint256 length = registers.length;\n if (length == 0) return;\n\n bool[] memory successes = new bool[](length);\n bytes[] memory returnDatas = new bytes[](length);\n bytes memory callData = abi.encodePacked(callbackFnSig, inputs);\n bytes memory proxyCallData = abi.encodeCall(TransparentUpgradeableProxyV2.functionDelegateCall, (callData));\n\n for (uint256 i; i < length; ) {\n (successes[i], returnDatas[i]) = registers[i].call(callData);\n if (!successes[i]) {\n (successes[i], returnDatas[i]) = registers[i].call(proxyCallData);\n }\n\n unchecked {\n ++i;\n }\n }\n\n emit Notified(callData, registers, successes, returnDatas);\n }\n\n /**\n * @dev Internal function to retrieve the address set of callback registers.\n * @return callbackRegisters The storage reference to the callback registers.\n */\n function _getCallbackRegisters() internal pure returns (EnumerableSet.AddressSet storage callbackRegisters) {\n assembly (\"memory-safe\") {\n callbackRegisters.slot := CALLBACK_REGISTERS_SLOT\n }\n }\n}\n" + }, + "contracts/extensions/bridge-operator-governance/BridgeTrackingHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nabstract contract BridgeTrackingHelper {\n /// @dev Event emited when the bridge tracking contract tracks the invalid data, cause malform in sharing bridge reward.\n event BridgeTrackingIncorrectlyResponded();\n\n /**\n * @dev Internal function to validate the bridge tracking response for a given set of ballots.\n * @param totalBallot The total number of ballots available for the tracking response.\n * @param totalVote The total number of votes recorded in the tracking response.\n * @param ballots An array containing the individual ballot counts in the tracking response.\n * @return valid A boolean indicating whether the bridge tracking response is valid or not.\n * @notice The function checks if each individual ballot count is not greater than the total votes recorded.\n * @notice It also verifies that the sum of all individual ballot counts does not exceed the total available ballots.\n */\n function _isValidBridgeTrackingResponse(\n uint256 totalBallot,\n uint256 totalVote,\n uint256[] memory ballots\n ) internal pure returns (bool valid) {\n valid = true;\n uint256 sumBallot;\n uint256 length = ballots.length;\n\n unchecked {\n for (uint256 i; i < length; ++i) {\n if (ballots[i] > totalVote) {\n valid = false;\n break;\n }\n\n sumBallot += ballots[i];\n }\n }\n\n valid = valid && (sumBallot <= totalBallot);\n }\n}\n" + }, + "contracts/extensions/collections/HasContracts.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { HasProxyAdmin } from \"./HasProxyAdmin.sol\";\nimport \"../../interfaces/collections/IHasContracts.sol\";\nimport { IdentityGuard } from \"../../utils/IdentityGuard.sol\";\nimport { ErrUnexpectedInternalCall } from \"../../utils/CommonErrors.sol\";\n\n/**\n * @title HasContracts\n * @dev A contract that provides functionality to manage multiple contracts with different roles.\n */\nabstract contract HasContracts is HasProxyAdmin, IHasContracts, IdentityGuard {\n /// @dev value is equal to keccak256(\"@ronin.dpos.collections.HasContracts.slot\") - 1\n bytes32 private constant _STORAGE_SLOT = 0xdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb;\n\n /**\n * @dev Modifier to restrict access to functions only to contracts with a specific role.\n * @param contractType The contract type that allowed to call\n */\n modifier onlyContract(ContractType contractType) virtual {\n _requireContract(contractType);\n _;\n }\n\n /**\n * @inheritdoc IHasContracts\n */\n function setContract(ContractType contractType, address addr) external virtual onlyAdmin {\n _requireHasCode(addr);\n _setContract(contractType, addr);\n }\n\n /**\n * @inheritdoc IHasContracts\n */\n function getContract(ContractType contractType) public view returns (address contract_) {\n contract_ = _getContractMap()[uint8(contractType)];\n if (contract_ == address(0)) revert ErrContractTypeNotFound(contractType);\n }\n\n /**\n * @dev Internal function to set the address of a contract with a specific role.\n * @param contractType The contract type of the contract to set.\n * @param addr The address of the contract to set.\n */\n function _setContract(ContractType contractType, address addr) internal virtual {\n _getContractMap()[uint8(contractType)] = addr;\n emit ContractUpdated(contractType, addr);\n }\n\n /**\n * @dev Internal function to access the mapping of contract addresses with roles.\n * @return contracts_ The mapping of contract addresses with roles.\n */\n function _getContractMap() private pure returns (mapping(uint8 => address) storage contracts_) {\n assembly {\n contracts_.slot := _STORAGE_SLOT\n }\n }\n\n /**\n * @dev Internal function to check if the calling contract has a specific role.\n * @param contractType The contract type that the calling contract must have.\n * @dev Throws an error if the calling contract does not have the specified role.\n */\n function _requireContract(ContractType contractType) private view {\n if (msg.sender != getContract(contractType)) {\n revert ErrUnexpectedInternalCall(msg.sig, contractType, msg.sender);\n }\n }\n}\n" + }, + "contracts/extensions/collections/HasProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/StorageSlot.sol\";\nimport \"../../utils/CommonErrors.sol\";\n\nabstract contract HasProxyAdmin {\n // bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n modifier onlyAdmin() {\n _requireAdmin();\n _;\n }\n\n /**\n * @dev Returns proxy admin.\n */\n function _getAdmin() internal view virtual returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n function _requireAdmin() internal view {\n if (msg.sender != _getAdmin()) revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN);\n }\n}\n" + }, + "contracts/extensions/consumers/GlobalConfigConsumer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nabstract contract GlobalConfigConsumer {\n /// @dev The addition amount of gas sending along in external calls. Total gas stipend is added with default 2300 gas.\n uint256 public constant DEFAULT_ADDITION_GAS = 1200;\n /// @dev The length of a period in second.\n uint256 public constant PERIOD_DURATION = 1 days;\n}\n" + }, + "contracts/extensions/consumers/PercentageConsumer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nabstract contract PercentageConsumer {\n uint256 internal constant _MAX_PERCENTAGE = 100_00;\n}\n" + }, + "contracts/extensions/forwarder/Forwarder.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/AccessControlEnumerable.sol\";\nimport { ErrorHandler } from \"../../libraries/ErrorHandler.sol\";\n\ncontract Forwarder is AccessControlEnumerable {\n using ErrorHandler for bool;\n\n /**\n * @dev Error thrown when an invalid forward value is provided.\n */\n error ErrInvalidForwardValue();\n\n /// @dev Only user with moderator role can invoke {functionCall} method to forward the call to the target.\n bytes32 public constant MODERATOR_ROLE = keccak256(\"MODERATOR_ROLE\");\n\n /**\n * @dev The target contracts must be registerred by the admin before called to. The admin can register the targets at\n * the contract construction or by assigning {TARGET_ROLE} to the target addresses.\n */\n bytes32 public constant TARGET_ROLE = keccak256(\"TARGET_ROLE\");\n\n /**\n * @dev Initializes the forwarder with an initial target address and a contract admin.\n */\n constructor(address[] memory _targets, address _admin, address _moderator) payable {\n for (uint _i = 0; _i < _targets.length; ) {\n _setupRole(TARGET_ROLE, _targets[_i]);\n\n unchecked {\n ++_i;\n }\n }\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n _setupRole(MODERATOR_ROLE, _moderator);\n }\n\n modifier validTarget(address _target) {\n _checkRole(TARGET_ROLE, _target);\n _;\n }\n\n /**\n * @dev Receives RON transfer from all addresses.\n */\n fallback() external payable {}\n\n /**\n * @dev Receives RON transfer from all addresses.\n */\n receive() external payable {}\n\n /**\n * @dev Forwards the encoded call specified by `_data` to the target. The forwarder attachs `_val` value\n * from the forwarder contract and sends along with the call.\n *\n * Requirements:\n * - Only target with {TARGET_ROLE} can be called to.\n * - Only user with {MODERATOR_ROLE} can call this method.\n */\n function functionCall(\n address _target,\n bytes memory _data,\n uint256 _val\n ) external payable validTarget(_target) onlyRole(MODERATOR_ROLE) {\n if (_val > address(this).balance) revert ErrInvalidForwardValue();\n _call(_target, _data, _val);\n }\n\n /**\n * @dev Forwards the current call to `target`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _call(address _target, bytes memory _data, uint256 _value) internal {\n (bool _success, bytes memory _res) = _target.call{ value: _value }(_data);\n _success.handleRevert(bytes4(_data), _res);\n }\n}\n" + }, + "contracts/extensions/GatewayV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/Pausable.sol\";\nimport \"../interfaces/IQuorum.sol\";\nimport \"./collections/HasProxyAdmin.sol\";\n\nabstract contract GatewayV2 is HasProxyAdmin, Pausable, IQuorum {\n uint256 internal _num;\n uint256 internal _denom;\n\n address private ______deprecated;\n uint256 public nonce;\n\n address public emergencyPauser;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[49] private ______gap;\n\n /**\n * @dev Grant emergency pauser role for `_addr`.\n */\n function setEmergencyPauser(address _addr) external onlyAdmin {\n emergencyPauser = _addr;\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function getThreshold() external view virtual returns (uint256 num_, uint256 denom_) {\n return (_num, _denom);\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function checkThreshold(uint256 _voteWeight) external view virtual returns (bool) {\n return _voteWeight * _denom >= _num * _getTotalWeight();\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function setThreshold(\n uint256 _numerator,\n uint256 _denominator\n ) external virtual onlyAdmin returns (uint256, uint256) {\n return _setThreshold(_numerator, _denominator);\n }\n\n /**\n * @dev Triggers paused state.\n */\n function pause() external {\n _requireAuth();\n _pause();\n }\n\n /**\n * @dev Triggers unpaused state.\n */\n function unpause() external {\n _requireAuth();\n _unpause();\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function minimumVoteWeight() public view virtual returns (uint256) {\n return _minimumVoteWeight(_getTotalWeight());\n }\n\n /**\n * @dev Sets threshold and returns the old one.\n *\n * Emits the `ThresholdUpdated` event.\n *\n */\n function _setThreshold(\n uint256 _numerator,\n uint256 _denominator\n ) internal virtual returns (uint256 _previousNum, uint256 _previousDenom) {\n if (_numerator > _denominator) revert ErrInvalidThreshold(msg.sig);\n _previousNum = _num;\n _previousDenom = _denom;\n _num = _numerator;\n _denom = _denominator;\n unchecked {\n emit ThresholdUpdated(nonce++, _numerator, _denominator, _previousNum, _previousDenom);\n }\n }\n\n /**\n * @dev Returns minimum vote weight.\n */\n function _minimumVoteWeight(uint256 _totalWeight) internal view virtual returns (uint256) {\n return (_num * _totalWeight + _denom - 1) / _denom;\n }\n\n /**\n * @dev Internal method to check method caller.\n *\n * Requirements:\n *\n * - The method caller must be admin or pauser.\n *\n */\n function _requireAuth() private view {\n if (!(msg.sender == _getAdmin() || msg.sender == emergencyPauser)) {\n revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN);\n }\n }\n\n /**\n * @dev Returns the total weight.\n */\n function _getTotalWeight() internal view virtual returns (uint256);\n}\n" + }, + "contracts/extensions/GovernanceAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../extensions/sequential-governance/CoreGovernance.sol\";\nimport \"../extensions/collections/HasContracts.sol\";\nimport \"../interfaces/IRoninTrustedOrganization.sol\";\nimport { ErrorHandler } from \"../libraries/ErrorHandler.sol\";\nimport { IdentityGuard } from \"../utils/IdentityGuard.sol\";\nimport { HasGovernanceAdminDeprecated, HasBridgeDeprecated } from \"../utils/DeprecatedSlots.sol\";\n\nabstract contract GovernanceAdmin is\n CoreGovernance,\n IdentityGuard,\n HasContracts,\n HasGovernanceAdminDeprecated,\n HasBridgeDeprecated\n{\n using ErrorHandler for bool;\n\n uint256 public roninChainId;\n /// @dev Domain separator\n bytes32 public DOMAIN_SEPARATOR;\n\n constructor(uint256 _roninChainId, address _roninTrustedOrganizationContract) {\n roninChainId = _roninChainId;\n\n /*\n * DOMAIN_SEPARATOR = keccak256(\n * abi.encode(\n * keccak256(\"EIP712Domain(string name,string version,bytes32 salt)\"),\n * keccak256(\"GovernanceAdmin\"), // name hash\n * keccak256(\"2\"), // version hash\n * keccak256(abi.encode(\"RONIN_GOVERNANCE_ADMIN\", _roninChainId)) // salt\n * )\n */\n assembly {\n let ptr := mload(0x40)\n\n // See abi.encode implementation: https://github.com/axieinfinity/ronin/blob/569ebd5a782da5601c6aba22799dc9b4afd39da9/accounts/abi/argument.go#L227-L267\n mstore(ptr, 0x40) // offset bytes\n mstore(add(ptr, 0x20), _roninChainId)\n mstore(add(ptr, 0x40), 0x16) // \"RONIN_GOVERNANCE_ADMIN\".length\n mstore(add(ptr, 0x60), 0x524f4e494e5f474f5645524e414e43455f41444d494e00000000000000000000) // bytes(\"RONIN_GOVERNANCE_ADMIN\")\n let salt := keccak256(ptr, 0x80) // keccak256(abi.encode(\"RONIN_GOVERNANCE_ADMIN\", _roninChainId))\n\n mstore(ptr, 0x599a80fcaa47b95e2323ab4d34d34e0cc9feda4b843edafcc30c7bdf60ea15bf) // keccak256(\"EIP712Domain(string name,string version,bytes32 salt)\")\n mstore(add(ptr, 0x20), 0x7e7935007966eb860f4a2ee3dcc9fd53fb3205ce2aa86b0126d4893d4d4c14b9) // keccak256(\"GovernanceAdmin\")\n mstore(add(ptr, 0x40), 0x2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de) // keccak256(\"3\")\n mstore(add(ptr, 0x60), salt)\n sstore(DOMAIN_SEPARATOR.slot, keccak256(ptr, 0x80))\n }\n\n _setContract(ContractType.RONIN_TRUSTED_ORGANIZATION, _roninTrustedOrganizationContract);\n }\n\n /**\n * @inheritdoc IHasContracts\n */\n function setContract(ContractType contractType, address addr) external virtual override onlySelfCall {\n _requireHasCode(addr);\n _setContract(contractType, addr);\n }\n\n /**\n * @dev Sets the expiry duration for a new proposal.\n *\n * Requirements:\n * - Only allowing self-call to this method, since this contract does not have admin.\n *\n */\n function setProposalExpiryDuration(uint256 _expiryDuration) external onlySelfCall {\n _setProposalExpiryDuration(_expiryDuration);\n }\n\n /**\n * @dev Returns the current implementation of `_proxy`.\n *\n * Requirements:\n * - This contract must be the admin of `_proxy`.\n *\n */\n function getProxyImplementation(address _proxy) external view returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n bytes4 _selector = 0x5c60da1b;\n (bool _success, bytes memory _returndata) = _proxy.staticcall(abi.encodeWithSelector(_selector));\n _success.handleRevert(_selector, _returndata);\n return abi.decode(_returndata, (address));\n }\n\n /**\n * @dev Returns the proposal expiry duration.\n */\n function getProposalExpiryDuration() external view returns (uint256) {\n return super._getProposalExpiryDuration();\n }\n\n /**\n * @dev Returns the current admin of `_proxy`.\n *\n * Requirements:\n * - This contract must be the admin of `_proxy`.\n *\n */\n function getProxyAdmin(address _proxy) external view returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n bytes4 _selector = 0xf851a440;\n (bool _success, bytes memory _returndata) = _proxy.staticcall(abi.encodeWithSelector(_selector));\n _success.handleRevert(_selector, _returndata);\n return abi.decode(_returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `_proxy` to `newAdmin`.\n *\n * Requirements:\n * - This contract must be the current admin of `_proxy`.\n *\n */\n function changeProxyAdmin(address _proxy, address _newAdmin) external onlySelfCall {\n // bytes4(keccak256(\"changeAdmin(address)\"))\n bytes4 _selector = 0x8f283970;\n (bool _success, bytes memory _returndata) = _proxy.call(abi.encodeWithSelector(_selector, _newAdmin));\n _success.handleRevert(_selector, _returndata);\n }\n\n /**\n * @dev Override `CoreGovernance-_getMinimumVoteWeight`.\n */\n function _getMinimumVoteWeight() internal view virtual override returns (uint256) {\n bytes4 _selector = IQuorum.minimumVoteWeight.selector;\n (bool _success, bytes memory _returndata) = getContract(ContractType.RONIN_TRUSTED_ORGANIZATION).staticcall(\n abi.encodeWithSelector(\n // TransparentUpgradeableProxyV2.functionDelegateCall.selector,\n 0x4bb5274a,\n abi.encodeWithSelector(_selector)\n )\n );\n _success.handleRevert(_selector, _returndata);\n return abi.decode(_returndata, (uint256));\n }\n\n /**\n * @dev Override `CoreGovernance-_getTotalWeights`.\n */\n function _getTotalWeight() internal view virtual override returns (uint256) {\n bytes4 _selector = IRoninTrustedOrganization.totalWeight.selector;\n (bool _success, bytes memory _returndata) = getContract(ContractType.RONIN_TRUSTED_ORGANIZATION).staticcall(\n abi.encodeWithSelector(\n // TransparentUpgradeableProxyV2.functionDelegateCall.selector,\n 0x4bb5274a,\n abi.encodeWithSelector(_selector)\n )\n );\n _success.handleRevert(_selector, _returndata);\n return abi.decode(_returndata, (uint256));\n }\n}\n" + }, + "contracts/extensions/MinimumWithdrawal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./collections/HasProxyAdmin.sol\";\nimport \"../libraries/Transfer.sol\";\n\nabstract contract MinimumWithdrawal is HasProxyAdmin {\n /// @dev Throwed when the ERC20 withdrawal quantity is less than the minimum threshold.\n error ErrQueryForTooSmallQuantity();\n\n /// @dev Emitted when the minimum thresholds are updated\n event MinimumThresholdsUpdated(address[] tokens, uint256[] threshold);\n\n /// @dev Mapping from token address => minimum thresholds\n mapping(address => uint256) public minimumThreshold;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @dev Sets the minimum thresholds to withdraw.\n *\n * Requirements:\n * - The method caller is admin.\n * - The arrays have the same length and its length larger than 0.\n *\n * Emits the `MinimumThresholdsUpdated` event.\n *\n */\n function setMinimumThresholds(address[] calldata _tokens, uint256[] calldata _thresholds) external virtual onlyAdmin {\n if (_tokens.length == 0) revert ErrEmptyArray();\n _setMinimumThresholds(_tokens, _thresholds);\n }\n\n /**\n * @dev Sets minimum thresholds.\n *\n * Requirements:\n * - The array lengths are equal.\n *\n * Emits the `MinimumThresholdsUpdated` event.\n *\n */\n function _setMinimumThresholds(address[] calldata _tokens, uint256[] calldata _thresholds) internal virtual {\n if (_tokens.length != _thresholds.length) revert ErrLengthMismatch(msg.sig);\n\n for (uint256 _i; _i < _tokens.length; ) {\n minimumThreshold[_tokens[_i]] = _thresholds[_i];\n\n unchecked {\n ++_i;\n }\n }\n emit MinimumThresholdsUpdated(_tokens, _thresholds);\n }\n\n /**\n * @dev Checks whether the request is larger than or equal to the minimum threshold.\n */\n function _checkWithdrawal(Transfer.Request calldata _request) internal view {\n if (_request.info.erc == Token.Standard.ERC20 && _request.info.quantity < minimumThreshold[_request.tokenAddr]) {\n revert ErrQueryForTooSmallQuantity();\n }\n }\n}\n" + }, + "contracts/extensions/RONTransferHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nabstract contract RONTransferHelper {\n /// @dev Error of sender has insufficient balance.\n error ErrInsufficientBalance(bytes4 msgSig, uint256 currentBalance, uint256 sendAmount);\n /// @dev Error of recipient not accepting RON when transfer RON.\n error ErrRecipientRevert(bytes4 msgSig);\n\n /**\n * @dev See `_sendRON`.\n * Reverts if the recipient does not receive RON.\n */\n function _transferRON(address payable recipient, uint256 amount) internal {\n if (!_sendRON(recipient, amount)) revert ErrRecipientRevert(msg.sig);\n }\n\n /**\n * @dev Send `amount` RON to the address `recipient`.\n * Returns whether the recipient receives RON or not.\n * Reverts once the contract balance is insufficient.\n *\n * Note: consider using `ReentrancyGuard` before calling this function.\n *\n */\n function _sendRON(address payable recipient, uint256 amount) internal returns (bool success) {\n if (address(this).balance < amount) revert ErrInsufficientBalance(msg.sig, address(this).balance, amount);\n return _unsafeSendRON(recipient, amount);\n }\n\n /**\n * @dev Unsafe send `amount` RON to the address `recipient`. If the sender's balance is insufficient,\n * the call does not revert.\n *\n * Note:\n * - Does not assert whether the balance of sender is sufficient.\n * - Does not assert whether the recipient accepts RON.\n * - Consider using `ReentrancyGuard` before calling this function.\n *\n */\n function _unsafeSendRON(address payable recipient, uint256 amount) internal returns (bool success) {\n (success, ) = recipient.call{ value: amount }(\"\");\n }\n\n /**\n * @dev Same purpose with {_unsafeSendRONLimitGas(address,uin256)} but containing gas limit stipend forwarded in the call.\n */\n function _unsafeSendRONLimitGas(\n address payable recipient,\n uint256 amount,\n uint256 gas\n ) internal returns (bool success) {\n (success, ) = recipient.call{ value: amount, gas: gas }(\"\");\n }\n}\n" + }, + "contracts/extensions/sequential-governance/CoreGovernance.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../../libraries/Proposal.sol\";\nimport \"../../libraries/GlobalProposal.sol\";\nimport \"../../utils/CommonErrors.sol\";\nimport \"../../libraries/Ballot.sol\";\nimport \"../../interfaces/consumers/ChainTypeConsumer.sol\";\nimport \"../../interfaces/consumers/SignatureConsumer.sol\";\nimport \"../../interfaces/consumers/VoteStatusConsumer.sol\";\n\nabstract contract CoreGovernance is SignatureConsumer, VoteStatusConsumer, ChainTypeConsumer {\n using Proposal for Proposal.ProposalDetail;\n\n /**\n * @dev Error thrown when attempting to interact with a finalized vote.\n */\n error ErrVoteIsFinalized();\n\n /**\n * @dev Error thrown when the current proposal is not completed.\n */\n error ErrCurrentProposalIsNotCompleted();\n\n struct ProposalVote {\n VoteStatus status;\n bytes32 hash;\n uint256 againstVoteWeight; // Total weight of against votes\n uint256 forVoteWeight; // Total weight of for votes\n address[] forVoteds; // Array of addresses voting for\n address[] againstVoteds; // Array of addresses voting against\n uint256 expiryTimestamp;\n mapping(address => Signature) sig;\n mapping(address => bool) voted;\n }\n\n /// @dev Emitted when a proposal is created\n event ProposalCreated(\n uint256 indexed chainId,\n uint256 indexed round,\n bytes32 indexed proposalHash,\n Proposal.ProposalDetail proposal,\n address creator\n );\n /// @dev Emitted when the proposal is voted\n event ProposalVoted(bytes32 indexed proposalHash, address indexed voter, Ballot.VoteType support, uint256 weight);\n /// @dev Emitted when the proposal is approved\n event ProposalApproved(bytes32 indexed proposalHash);\n /// @dev Emitted when the vote is reject\n event ProposalRejected(bytes32 indexed proposalHash);\n /// @dev Emitted when the vote is expired\n event ProposalExpired(bytes32 indexed proposalHash);\n /// @dev Emitted when the proposal is executed\n event ProposalExecuted(bytes32 indexed proposalHash, bool[] successCalls, bytes[] returnDatas);\n /// @dev Emitted when the proposal expiry duration is changed.\n event ProposalExpiryDurationChanged(uint256 indexed duration);\n\n /// @dev Mapping from chain id => vote round\n /// @notice chain id = 0 for global proposal\n mapping(uint256 => uint256) public round;\n /// @dev Mapping from chain id => vote round => proposal vote\n mapping(uint256 => mapping(uint256 => ProposalVote)) public vote;\n\n uint256 internal _proposalExpiryDuration;\n\n constructor(uint256 _expiryDuration) {\n _setProposalExpiryDuration(_expiryDuration);\n }\n\n /**\n * @dev Creates new voting round by calculating the `_round` number of chain `_chainId`.\n * Increases the `_round` number if the previous one is not expired. Delete the previous proposal\n * if it is expired and not increase the `_round`.\n */\n function _createVotingRound(uint256 _chainId) internal returns (uint256 _round) {\n _round = round[_chainId];\n // Skip checking for the first ever round\n if (_round == 0) {\n _round = round[_chainId] = 1;\n } else {\n ProposalVote storage _latestProposalVote = vote[_chainId][_round];\n bool _isExpired = _tryDeleteExpiredVotingRound(_latestProposalVote);\n // Skip increasing round number if the latest round is expired, allow the vote to be overridden\n if (!_isExpired) {\n if (_latestProposalVote.status == VoteStatus.Pending) revert ErrCurrentProposalIsNotCompleted();\n unchecked {\n _round = ++round[_chainId];\n }\n }\n }\n }\n\n /**\n * @dev Saves new round voting for the proposal `_proposalHash` of chain `_chainId`.\n */\n function _saveVotingRound(ProposalVote storage _vote, bytes32 _proposalHash, uint256 _expiryTimestamp) internal {\n _vote.hash = _proposalHash;\n _vote.expiryTimestamp = _expiryTimestamp;\n }\n\n /**\n * @dev Proposes for a new proposal.\n *\n * Requirements:\n * - The chain id is not equal to 0.\n *\n * Emits the `ProposalCreated` event.\n *\n */\n function _proposeProposal(\n uint256 chainId,\n uint256 expiryTimestamp,\n address[] memory targets,\n uint256[] memory values,\n bytes[] memory calldatas,\n uint256[] memory gasAmounts,\n address creator\n ) internal virtual returns (Proposal.ProposalDetail memory proposal) {\n if (chainId == 0) revert ErrInvalidChainId(msg.sig, 0, block.chainid);\n uint256 round_ = _createVotingRound(chainId);\n\n proposal = Proposal.ProposalDetail(round_, chainId, expiryTimestamp, targets, values, calldatas, gasAmounts);\n proposal.validate(_proposalExpiryDuration);\n\n bytes32 proposalHash = proposal.hash();\n _saveVotingRound(vote[chainId][round_], proposalHash, expiryTimestamp);\n emit ProposalCreated(chainId, round_, proposalHash, proposal, creator);\n }\n\n /**\n * @dev Proposes proposal struct.\n *\n * Requirements:\n * - The chain id is not equal to 0.\n * - The proposal nonce is equal to the new round.\n *\n * Emits the `ProposalCreated` event.\n *\n */\n function _proposeProposalStruct(\n Proposal.ProposalDetail memory proposal,\n address creator\n ) internal virtual returns (uint256 round_) {\n uint256 chainId = proposal.chainId;\n if (chainId == 0) revert ErrInvalidChainId(msg.sig, 0, block.chainid);\n proposal.validate(_proposalExpiryDuration);\n\n bytes32 proposalHash = proposal.hash();\n round_ = _createVotingRound(chainId);\n _saveVotingRound(vote[chainId][round_], proposalHash, proposal.expiryTimestamp);\n if (round_ != proposal.nonce) revert ErrInvalidProposalNonce(msg.sig);\n emit ProposalCreated(chainId, round_, proposalHash, proposal, creator);\n }\n\n /**\n * @dev Casts vote for the proposal with data and returns whether the voting is done.\n *\n * Requirements:\n * - The proposal nonce is equal to the round.\n * - The vote is not finalized.\n * - The voter has not voted for the round.\n *\n * Emits the `ProposalVoted` event. Emits the `ProposalApproved`, `ProposalExecuted` or `ProposalRejected` once the\n * proposal is approved, executed or rejected.\n *\n */\n function _castVote(\n Proposal.ProposalDetail memory proposal,\n Ballot.VoteType support,\n uint256 minimumForVoteWeight,\n uint256 minimumAgainstVoteWeight,\n address voter,\n Signature memory signature,\n uint256 voterWeight\n ) internal virtual returns (bool done) {\n uint256 chainId = proposal.chainId;\n uint256 round_ = proposal.nonce;\n ProposalVote storage _vote = vote[chainId][round_];\n\n if (_tryDeleteExpiredVotingRound(_vote)) {\n return true;\n }\n\n if (round[proposal.chainId] != round_) revert ErrInvalidProposalNonce(msg.sig);\n if (_vote.status != VoteStatus.Pending) revert ErrVoteIsFinalized();\n if (_voted(_vote, voter)) revert ErrAlreadyVoted(voter);\n\n _vote.voted[voter] = true;\n // Stores the signature if it is not empty\n if (signature.r > 0 || signature.s > 0 || signature.v > 0) {\n _vote.sig[voter] = signature;\n }\n emit ProposalVoted(_vote.hash, voter, support, voterWeight);\n\n uint256 _forVoteWeight;\n uint256 _againstVoteWeight;\n if (support == Ballot.VoteType.For) {\n _vote.forVoteds.push(voter);\n _forVoteWeight = _vote.forVoteWeight += voterWeight;\n } else if (support == Ballot.VoteType.Against) {\n _vote.againstVoteds.push(voter);\n _againstVoteWeight = _vote.againstVoteWeight += voterWeight;\n } else revert ErrUnsupportedVoteType(msg.sig);\n\n if (_forVoteWeight >= minimumForVoteWeight) {\n done = true;\n _vote.status = VoteStatus.Approved;\n emit ProposalApproved(_vote.hash);\n _tryExecute(_vote, proposal);\n } else if (_againstVoteWeight >= minimumAgainstVoteWeight) {\n done = true;\n _vote.status = VoteStatus.Rejected;\n emit ProposalRejected(_vote.hash);\n }\n }\n\n /**\n * @dev When the contract is on Ronin chain, checks whether the proposal is expired and delete it if is expired.\n *\n * Emits the event `ProposalExpired` if the vote is expired.\n *\n * Note: This function assumes the vote `_proposalVote` is already created, consider verifying the vote's existence\n * before or it will emit an unexpected event of `ProposalExpired`.\n */\n function _tryDeleteExpiredVotingRound(ProposalVote storage proposalVote) internal returns (bool isExpired) {\n isExpired =\n _getChainType() == ChainType.RoninChain &&\n proposalVote.status == VoteStatus.Pending &&\n proposalVote.expiryTimestamp <= block.timestamp;\n\n if (isExpired) {\n emit ProposalExpired(proposalVote.hash);\n\n for (uint256 _i; _i < proposalVote.forVoteds.length; ) {\n delete proposalVote.voted[proposalVote.forVoteds[_i]];\n delete proposalVote.sig[proposalVote.forVoteds[_i]];\n\n unchecked {\n ++_i;\n }\n }\n for (uint256 _i; _i < proposalVote.againstVoteds.length; ) {\n delete proposalVote.voted[proposalVote.againstVoteds[_i]];\n delete proposalVote.sig[proposalVote.againstVoteds[_i]];\n\n unchecked {\n ++_i;\n }\n }\n delete proposalVote.status;\n delete proposalVote.hash;\n delete proposalVote.againstVoteWeight;\n delete proposalVote.forVoteWeight;\n delete proposalVote.forVoteds;\n delete proposalVote.againstVoteds;\n delete proposalVote.expiryTimestamp;\n }\n }\n\n /**\n * @dev Executes the proposal and update the vote status once the proposal is executable.\n */\n function _tryExecute(ProposalVote storage vote_, Proposal.ProposalDetail memory proposal) internal {\n if (proposal.executable()) {\n vote_.status = VoteStatus.Executed;\n (bool[] memory _successCalls, bytes[] memory _returnDatas) = proposal.execute();\n emit ProposalExecuted(vote_.hash, _successCalls, _returnDatas);\n }\n }\n\n /**\n * @dev Sets the expiry duration for a new proposal.\n */\n function _setProposalExpiryDuration(uint256 expiryDuration) internal {\n _proposalExpiryDuration = expiryDuration;\n emit ProposalExpiryDurationChanged(expiryDuration);\n }\n\n /**\n * @dev Returns the expiry duration for a new proposal.\n */\n function _getProposalExpiryDuration() internal view returns (uint256) {\n return _proposalExpiryDuration;\n }\n\n /**\n * @dev Returns whether the voter casted for the proposal.\n */\n function _voted(ProposalVote storage vote_, address voter) internal view returns (bool) {\n return vote_.voted[voter];\n }\n\n /**\n * @dev Returns total weight from validators.\n */\n function _getTotalWeight() internal view virtual returns (uint256);\n\n /**\n * @dev Returns minimum vote to pass a proposal.\n */\n function _getMinimumVoteWeight() internal view virtual returns (uint256);\n\n /**\n * @dev Returns current context is running on whether Ronin chain or on mainchain.\n */\n function _getChainType() internal view virtual returns (ChainType);\n}\n" + }, + "contracts/extensions/sequential-governance/GlobalCoreGovernance.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../../libraries/Proposal.sol\";\nimport \"../../libraries/GlobalProposal.sol\";\nimport \"./CoreGovernance.sol\";\n\nabstract contract GlobalCoreGovernance is CoreGovernance {\n using Proposal for Proposal.ProposalDetail;\n using GlobalProposal for GlobalProposal.GlobalProposalDetail;\n\n mapping(GlobalProposal.TargetOption => address) internal _targetOptionsMap;\n\n /// @dev Emitted when a proposal is created\n event GlobalProposalCreated(\n uint256 indexed round,\n bytes32 indexed proposalHash,\n Proposal.ProposalDetail proposal,\n bytes32 globalProposalHash,\n GlobalProposal.GlobalProposalDetail globalProposal,\n address creator\n );\n\n /// @dev Emitted when the target options are updated\n event TargetOptionUpdated(GlobalProposal.TargetOption indexed targetOption, address indexed addr);\n\n constructor(GlobalProposal.TargetOption[] memory targetOptions, address[] memory addrs) {\n _updateTargetOption(GlobalProposal.TargetOption.BridgeManager, address(this));\n _updateManyTargetOption(targetOptions, addrs);\n }\n\n /**\n * @dev Proposes for a global proposal.\n *\n * Emits the `GlobalProposalCreated` event.\n *\n */\n function _proposeGlobal(\n uint256 expiryTimestamp,\n GlobalProposal.TargetOption[] calldata targetOptions,\n uint256[] memory values,\n bytes[] memory calldatas,\n uint256[] memory gasAmounts,\n address creator\n ) internal virtual {\n uint256 round_ = _createVotingRound(0);\n GlobalProposal.GlobalProposalDetail memory globalProposal = GlobalProposal.GlobalProposalDetail(\n round_,\n expiryTimestamp,\n targetOptions,\n values,\n calldatas,\n gasAmounts\n );\n Proposal.ProposalDetail memory proposal = globalProposal.intoProposalDetail(\n _resolveTargets({ targetOptions: targetOptions, strict: true })\n );\n proposal.validate(_proposalExpiryDuration);\n\n bytes32 proposalHash = proposal.hash();\n _saveVotingRound(vote[0][round_], proposalHash, expiryTimestamp);\n emit GlobalProposalCreated(round_, proposalHash, proposal, globalProposal.hash(), globalProposal, creator);\n }\n\n /**\n * @dev Proposes global proposal struct.\n *\n * Requirements:\n * - The proposal nonce is equal to the new round.\n *\n * Emits the `GlobalProposalCreated` event.\n *\n */\n function _proposeGlobalStruct(\n GlobalProposal.GlobalProposalDetail memory globalProposal,\n address creator\n ) internal virtual returns (Proposal.ProposalDetail memory proposal) {\n proposal = globalProposal.intoProposalDetail(\n _resolveTargets({ targetOptions: globalProposal.targetOptions, strict: true })\n );\n proposal.validate(_proposalExpiryDuration);\n\n bytes32 proposalHash = proposal.hash();\n uint256 round_ = _createVotingRound(0);\n _saveVotingRound(vote[0][round_], proposalHash, globalProposal.expiryTimestamp);\n\n if (round_ != proposal.nonce) revert ErrInvalidProposalNonce(msg.sig);\n emit GlobalProposalCreated(round_, proposalHash, proposal, globalProposal.hash(), globalProposal, creator);\n }\n\n /**\n * @dev Returns corresponding address of target options. Return address(0) on non-existent target.\n */\n function resolveTargets(\n GlobalProposal.TargetOption[] calldata targetOptions\n ) external view returns (address[] memory targets) {\n return _resolveTargets({ targetOptions: targetOptions, strict: false });\n }\n\n /**\n * @dev Internal helper of {resolveTargets}.\n *\n * @param strict When the param is set to `true`, revert on non-existent target.\n */\n function _resolveTargets(\n GlobalProposal.TargetOption[] memory targetOptions,\n bool strict\n ) internal view returns (address[] memory targets) {\n targets = new address[](targetOptions.length);\n\n for (uint256 i; i < targetOptions.length; ) {\n targets[i] = _targetOptionsMap[targetOptions[i]];\n if (strict && targets[i] == address(0)) revert ErrInvalidArguments(msg.sig);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Updates list of `targetOptions` to `targets`.\n *\n * Requirement:\n * - Only allow self-call through proposal.\n * */\n function updateManyTargetOption(\n GlobalProposal.TargetOption[] memory targetOptions,\n address[] memory targets\n ) external {\n // HACK: Cannot reuse the existing library due to too deep stack\n if (msg.sender != address(this)) revert ErrOnlySelfCall(msg.sig);\n _updateManyTargetOption(targetOptions, targets);\n }\n\n /**\n * @dev Updates list of `targetOptions` to `targets`.\n */\n function _updateManyTargetOption(\n GlobalProposal.TargetOption[] memory targetOptions,\n address[] memory targets\n ) internal {\n for (uint256 i; i < targetOptions.length; ) {\n if (targets[i] == address(this)) revert ErrInvalidArguments(msg.sig);\n _updateTargetOption(targetOptions[i], targets[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Updates `targetOption` to `target`.\n *\n * Requirement:\n * - Emit a `TargetOptionUpdated` event.\n */\n function _updateTargetOption(GlobalProposal.TargetOption targetOption, address target) internal {\n _targetOptionsMap[targetOption] = target;\n emit TargetOptionUpdated(targetOption, target);\n }\n}\n" + }, + "contracts/extensions/sequential-governance/governance-proposal/CommonGovernanceProposal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../CoreGovernance.sol\";\n\nabstract contract CommonGovernanceProposal is CoreGovernance {\n using Proposal for Proposal.ProposalDetail;\n\n /**\n * @dev Error thrown when an invalid proposal is encountered.\n * @param actual The actual value of the proposal.\n * @param expected The expected value of the proposal.\n */\n error ErrInvalidProposal(bytes32 actual, bytes32 expected);\n\n /**\n * @dev Casts votes by signatures.\n *\n * Note: This method does not verify the proposal hash with the vote hash. Please consider checking it before.\n *\n */\n function _castVotesBySignatures(\n Proposal.ProposalDetail memory _proposal,\n Ballot.VoteType[] calldata _supports,\n Signature[] calldata _signatures,\n bytes32 _forDigest,\n bytes32 _againstDigest\n ) internal {\n if (!(_supports.length != 0 && _supports.length == _signatures.length)) revert ErrLengthMismatch(msg.sig);\n\n uint256 _minimumForVoteWeight = _getMinimumVoteWeight();\n uint256 _minimumAgainstVoteWeight = _getTotalWeight() - _minimumForVoteWeight + 1;\n\n address _lastSigner;\n address _signer;\n Signature calldata _sig;\n bool _hasValidVotes;\n for (uint256 _i; _i < _signatures.length; ) {\n _sig = _signatures[_i];\n\n if (_supports[_i] == Ballot.VoteType.For) {\n _signer = ECDSA.recover(_forDigest, _sig.v, _sig.r, _sig.s);\n } else if (_supports[_i] == Ballot.VoteType.Against) {\n _signer = ECDSA.recover(_againstDigest, _sig.v, _sig.r, _sig.s);\n } else revert ErrUnsupportedVoteType(msg.sig);\n\n if (_lastSigner >= _signer) revert ErrInvalidOrder(msg.sig);\n _lastSigner = _signer;\n\n uint256 _weight = _getWeight(_signer);\n if (_weight > 0) {\n _hasValidVotes = true;\n if (\n _castVote(_proposal, _supports[_i], _minimumForVoteWeight, _minimumAgainstVoteWeight, _signer, _sig, _weight)\n ) {\n return;\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n\n if (!_hasValidVotes) revert ErrInvalidSignatures(msg.sig);\n }\n\n /**\n * @dev Returns the voted signatures for the proposals.\n *\n * Note: The signatures can be empty in case the proposal is voted on the current network.\n *\n */\n function _getProposalSignatures(\n uint256 _chainId,\n uint256 _round\n )\n internal\n view\n returns (address[] memory _voters, Ballot.VoteType[] memory _supports, Signature[] memory _signatures)\n {\n ProposalVote storage _vote = vote[_chainId][_round];\n\n uint256 _forLength = _vote.forVoteds.length;\n uint256 _againstLength = _vote.againstVoteds.length;\n uint256 _voterLength = _forLength + _againstLength;\n\n _supports = new Ballot.VoteType[](_voterLength);\n _signatures = new Signature[](_voterLength);\n _voters = new address[](_voterLength);\n for (uint256 _i; _i < _forLength; ) {\n _supports[_i] = Ballot.VoteType.For;\n _signatures[_i] = vote[_chainId][_round].sig[_vote.forVoteds[_i]];\n _voters[_i] = _vote.forVoteds[_i];\n\n unchecked {\n ++_i;\n }\n }\n for (uint256 _i; _i < _againstLength; ) {\n _supports[_i + _forLength] = Ballot.VoteType.Against;\n _signatures[_i + _forLength] = vote[_chainId][_round].sig[_vote.againstVoteds[_i]];\n _voters[_i + _forLength] = _vote.againstVoteds[_i];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @dev Returns whether the voter `_voter` casted vote for the proposal.\n */\n function _proposalVoted(uint256 _chainId, uint256 _round, address _voter) internal view returns (bool) {\n return _voted(vote[_chainId][_round], _voter);\n }\n\n /**\n * @dev Returns the weight of a governor.\n */\n function _getWeight(address _governor) internal view virtual returns (uint256);\n}\n" + }, + "contracts/extensions/sequential-governance/governance-proposal/GlobalGovernanceProposal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../../../libraries/Proposal.sol\";\nimport \"../GlobalCoreGovernance.sol\";\nimport \"./CommonGovernanceProposal.sol\";\n\nabstract contract GlobalGovernanceProposal is GlobalCoreGovernance, CommonGovernanceProposal {\n using Proposal for Proposal.ProposalDetail;\n using GlobalProposal for GlobalProposal.GlobalProposalDetail;\n\n /**\n * @dev Proposes and votes by signature.\n */\n function _proposeGlobalProposalStructAndCastVotes(\n GlobalProposal.GlobalProposalDetail calldata globalProposal,\n Ballot.VoteType[] calldata supports_,\n Signature[] calldata signatures,\n bytes32 domainSeparator,\n address creator\n ) internal returns (Proposal.ProposalDetail memory proposal) {\n proposal = _proposeGlobalStruct(globalProposal, creator);\n bytes32 _globalProposalHash = globalProposal.hash();\n _castVotesBySignatures(\n proposal,\n supports_,\n signatures,\n ECDSA.toTypedDataHash(domainSeparator, Ballot.hash(_globalProposalHash, Ballot.VoteType.For)),\n ECDSA.toTypedDataHash(domainSeparator, Ballot.hash(_globalProposalHash, Ballot.VoteType.Against))\n );\n }\n\n /**\n * @dev Proposes a global proposal struct and casts votes by signature.\n */\n function _castGlobalProposalBySignatures(\n GlobalProposal.GlobalProposalDetail calldata globalProposal,\n Ballot.VoteType[] calldata supports_,\n Signature[] calldata signatures,\n bytes32 domainSeparator\n ) internal {\n Proposal.ProposalDetail memory _proposal = globalProposal.intoProposalDetail(\n _resolveTargets({ targetOptions: globalProposal.targetOptions, strict: true })\n );\n\n bytes32 proposalHash = _proposal.hash();\n if (vote[0][_proposal.nonce].hash != proposalHash)\n revert ErrInvalidProposal(proposalHash, vote[0][_proposal.nonce].hash);\n\n bytes32 globalProposalHash = globalProposal.hash();\n _castVotesBySignatures(\n _proposal,\n supports_,\n signatures,\n ECDSA.toTypedDataHash(domainSeparator, Ballot.hash(globalProposalHash, Ballot.VoteType.For)),\n ECDSA.toTypedDataHash(domainSeparator, Ballot.hash(globalProposalHash, Ballot.VoteType.Against))\n );\n }\n\n /**\n * @dev See {CommonGovernanceProposal-_getProposalSignatures}\n */\n function getGlobalProposalSignatures(\n uint256 round_\n ) external view returns (address[] memory voters, Ballot.VoteType[] memory supports_, Signature[] memory signatures) {\n return _getProposalSignatures(0, round_);\n }\n\n /**\n * @dev See {CommonGovernanceProposal-_proposalVoted}\n */\n function globalProposalVoted(uint256 round_, address voter) external view returns (bool) {\n return _proposalVoted(0, round_, voter);\n }\n}\n" + }, + "contracts/extensions/sequential-governance/governance-proposal/GovernanceProposal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../CoreGovernance.sol\";\nimport \"./CommonGovernanceProposal.sol\";\n\nabstract contract GovernanceProposal is CoreGovernance, CommonGovernanceProposal {\n using Proposal for Proposal.ProposalDetail;\n\n /**\n * @dev Proposes a proposal struct and casts votes by signature.\n */\n function _proposeProposalStructAndCastVotes(\n Proposal.ProposalDetail calldata _proposal,\n Ballot.VoteType[] calldata _supports,\n Signature[] calldata _signatures,\n bytes32 _domainSeparator,\n address _creator\n ) internal {\n _proposeProposalStruct(_proposal, _creator);\n bytes32 _proposalHash = _proposal.hash();\n _castVotesBySignatures(\n _proposal,\n _supports,\n _signatures,\n ECDSA.toTypedDataHash(_domainSeparator, Ballot.hash(_proposalHash, Ballot.VoteType.For)),\n ECDSA.toTypedDataHash(_domainSeparator, Ballot.hash(_proposalHash, Ballot.VoteType.Against))\n );\n }\n\n /**\n * @dev Proposes a proposal struct and casts votes by signature.\n */\n function _castProposalBySignatures(\n Proposal.ProposalDetail calldata _proposal,\n Ballot.VoteType[] calldata _supports,\n Signature[] calldata _signatures,\n bytes32 _domainSeparator\n ) internal {\n bytes32 _proposalHash = _proposal.hash();\n\n if (vote[_proposal.chainId][_proposal.nonce].hash != _proposalHash) {\n revert ErrInvalidProposal(_proposalHash, vote[_proposal.chainId][_proposal.nonce].hash);\n }\n\n _castVotesBySignatures(\n _proposal,\n _supports,\n _signatures,\n ECDSA.toTypedDataHash(_domainSeparator, Ballot.hash(_proposalHash, Ballot.VoteType.For)),\n ECDSA.toTypedDataHash(_domainSeparator, Ballot.hash(_proposalHash, Ballot.VoteType.Against))\n );\n }\n\n /**\n * @dev See `castProposalVoteForCurrentNetwork`.\n */\n function _castProposalVoteForCurrentNetwork(\n address _voter,\n Proposal.ProposalDetail memory _proposal,\n Ballot.VoteType _support\n ) internal {\n if (_proposal.chainId != block.chainid) revert ErrInvalidChainId(msg.sig, _proposal.chainId, block.chainid);\n\n bytes32 proposalHash = _proposal.hash();\n if (vote[_proposal.chainId][_proposal.nonce].hash != proposalHash)\n revert ErrInvalidProposal(proposalHash, vote[_proposal.chainId][_proposal.nonce].hash);\n\n uint256 _minimumForVoteWeight = _getMinimumVoteWeight();\n uint256 _minimumAgainstVoteWeight = _getTotalWeight() - _minimumForVoteWeight + 1;\n Signature memory _emptySignature;\n _castVote(\n _proposal,\n _support,\n _minimumForVoteWeight,\n _minimumAgainstVoteWeight,\n _voter,\n _emptySignature,\n _getWeight(_voter)\n );\n }\n\n /**\n * @dev See {CommonGovernanceProposal-_getProposalSignatures}\n */\n function getProposalSignatures(\n uint256 _chainId,\n uint256 _round\n )\n external\n view\n returns (address[] memory _voters, Ballot.VoteType[] memory _supports, Signature[] memory _signatures)\n {\n return _getProposalSignatures(_chainId, _round);\n }\n\n /**\n * @dev See {CommonGovernanceProposal-_proposalVoted}\n */\n function proposalVoted(uint256 _chainId, uint256 _round, address _voter) external view returns (bool) {\n return _proposalVoted(_chainId, _round, _voter);\n }\n}\n" + }, + "contracts/extensions/sequential-governance/governance-relay/CommonGovernanceRelay.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../CoreGovernance.sol\";\n\nabstract contract CommonGovernanceRelay is CoreGovernance {\n using Proposal for Proposal.ProposalDetail;\n using GlobalProposal for GlobalProposal.GlobalProposalDetail;\n\n /**\n * @dev Relays votes by signatures.\n *\n * @notice Does not store the voter signature into storage.\n *\n */\n function _relayVotesBySignatures(\n Proposal.ProposalDetail memory _proposal,\n Ballot.VoteType[] calldata _supports,\n Signature[] calldata _signatures,\n bytes32 _forDigest,\n bytes32 _againstDigest\n ) internal {\n if (!(_supports.length > 0 && _supports.length == _signatures.length)) revert ErrLengthMismatch(msg.sig);\n\n uint256 _forVoteCount;\n uint256 _againstVoteCount;\n address[] memory _forVoteSigners = new address[](_signatures.length);\n address[] memory _againstVoteSigners = new address[](_signatures.length);\n\n {\n address _signer;\n address _lastSigner;\n Ballot.VoteType _support;\n Signature calldata _sig;\n\n for (uint256 _i; _i < _signatures.length; ) {\n _sig = _signatures[_i];\n _support = _supports[_i];\n\n if (_support == Ballot.VoteType.For) {\n _signer = ECDSA.recover(_forDigest, _sig.v, _sig.r, _sig.s);\n _forVoteSigners[_forVoteCount++] = _signer;\n } else if (_support == Ballot.VoteType.Against) {\n _signer = ECDSA.recover(_againstDigest, _sig.v, _sig.r, _sig.s);\n _againstVoteSigners[_againstVoteCount++] = _signer;\n } else revert ErrUnsupportedVoteType(msg.sig);\n\n if (_lastSigner >= _signer) revert ErrInvalidOrder(msg.sig);\n _lastSigner = _signer;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n assembly {\n mstore(_forVoteSigners, _forVoteCount)\n mstore(_againstVoteSigners, _againstVoteCount)\n }\n\n ProposalVote storage _vote = vote[_proposal.chainId][_proposal.nonce];\n uint256 _minimumForVoteWeight = _getMinimumVoteWeight();\n uint256 _totalForVoteWeight = _sumWeight(_forVoteSigners);\n if (_totalForVoteWeight >= _minimumForVoteWeight) {\n if (_totalForVoteWeight == 0) revert ErrInvalidVoteWeight(msg.sig);\n _vote.status = VoteStatus.Approved;\n emit ProposalApproved(_vote.hash);\n _tryExecute(_vote, _proposal);\n return;\n }\n\n uint256 _minimumAgainstVoteWeight = _getTotalWeight() - _minimumForVoteWeight + 1;\n uint256 _totalAgainstVoteWeight = _sumWeight(_againstVoteSigners);\n if (_totalAgainstVoteWeight >= _minimumAgainstVoteWeight) {\n if (_totalAgainstVoteWeight == 0) revert ErrInvalidVoteWeight(msg.sig);\n _vote.status = VoteStatus.Rejected;\n emit ProposalRejected(_vote.hash);\n return;\n }\n\n revert ErrRelayFailed(msg.sig);\n }\n\n /**\n * @dev Returns the weight of the governor list.\n */\n function _sumWeight(address[] memory _governors) internal view virtual returns (uint256);\n}\n" + }, + "contracts/extensions/sequential-governance/governance-relay/GlobalGovernanceRelay.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../GlobalCoreGovernance.sol\";\nimport \"./CommonGovernanceRelay.sol\";\n\nabstract contract GlobalGovernanceRelay is CommonGovernanceRelay, GlobalCoreGovernance {\n using GlobalProposal for GlobalProposal.GlobalProposalDetail;\n\n /**\n * @dev Returns whether the voter `_voter` casted vote for the proposal.\n */\n function globalProposalRelayed(uint256 _round) external view returns (bool) {\n return vote[0][_round].status != VoteStatus.Pending;\n }\n\n /**\n * @dev Relays voted global proposal.\n *\n * Requirements:\n * - The relay proposal is finalized.\n *\n */\n function _relayGlobalProposal(\n GlobalProposal.GlobalProposalDetail calldata globalProposal,\n Ballot.VoteType[] calldata supports_,\n Signature[] calldata signatures,\n bytes32 domainSeparator,\n address creator\n ) internal {\n Proposal.ProposalDetail memory _proposal = _proposeGlobalStruct(globalProposal, creator);\n bytes32 globalProposalHash = globalProposal.hash();\n _relayVotesBySignatures(\n _proposal,\n supports_,\n signatures,\n ECDSA.toTypedDataHash(domainSeparator, Ballot.hash(globalProposalHash, Ballot.VoteType.For)),\n ECDSA.toTypedDataHash(domainSeparator, Ballot.hash(globalProposalHash, Ballot.VoteType.Against))\n );\n }\n}\n" + }, + "contracts/extensions/sequential-governance/governance-relay/GovernanceRelay.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../CoreGovernance.sol\";\nimport \"./CommonGovernanceRelay.sol\";\n\nabstract contract GovernanceRelay is CoreGovernance, CommonGovernanceRelay {\n using Proposal for Proposal.ProposalDetail;\n using GlobalProposal for GlobalProposal.GlobalProposalDetail;\n\n /**\n * @dev Relays voted proposal.\n *\n * Requirements:\n * - The relay proposal is finalized.\n *\n */\n function _relayProposal(\n Proposal.ProposalDetail calldata _proposal,\n Ballot.VoteType[] calldata _supports,\n Signature[] calldata _signatures,\n bytes32 _domainSeparator,\n address _creator\n ) internal {\n _proposeProposalStruct(_proposal, _creator);\n bytes32 _proposalHash = _proposal.hash();\n _relayVotesBySignatures(\n _proposal,\n _supports,\n _signatures,\n ECDSA.toTypedDataHash(_domainSeparator, Ballot.hash(_proposalHash, Ballot.VoteType.For)),\n ECDSA.toTypedDataHash(_domainSeparator, Ballot.hash(_proposalHash, Ballot.VoteType.Against))\n );\n }\n}\n" + }, + "contracts/extensions/TransparentUpgradeableProxyV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol\";\n\ncontract TransparentUpgradeableProxyV2 is TransparentUpgradeableProxy {\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable TransparentUpgradeableProxy(_logic, admin_, _data) {}\n\n /**\n * @dev Calls a function from the current implementation as specified by `_data`, which should be an encoded function call.\n *\n * Requirements:\n * - Only the admin can call this function.\n *\n * Note: The proxy admin is not allowed to interact with the proxy logic through the fallback function to avoid\n * triggering some unexpected logic. This is to allow the administrator to explicitly call the proxy, please consider\n * reviewing the encoded data `_data` and the method which is called before using this.\n *\n */\n function functionDelegateCall(bytes memory _data) public payable ifAdmin {\n address _addr = _implementation();\n assembly {\n let _result := delegatecall(gas(), _addr, add(_data, 32), mload(_data), 0, 0)\n returndatacopy(0, 0, returndatasize())\n switch _result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/extensions/version-control/ConditionalImplementControl.sol": { + "content": "/// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IConditionalImplementControl } from \"../../interfaces/version-control/IConditionalImplementControl.sol\";\nimport { ErrorHandler } from \"../../libraries/ErrorHandler.sol\";\nimport { AddressArrayUtils } from \"../../libraries/AddressArrayUtils.sol\";\nimport { ErrOnlySelfCall, IdentityGuard } from \"../../utils/IdentityGuard.sol\";\n\n/**\n * @title ConditionalImplementControl\n * @dev A contract that allows conditional version control of contract implementations.\n */\nabstract contract ConditionalImplementControl is IConditionalImplementControl, IdentityGuard {\n using ErrorHandler for bool;\n using AddressArrayUtils for address[];\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev address of the proxy that delegates to this contract.\n * @notice immutable variables are directly stored in contract code.\n * ensuring no storage writes are required.\n * The values of immutable variables remain fixed and cannot be modified,\n * regardless of any interactions, including delegations.\n */\n address public immutable PROXY_STORAGE;\n /**\n * @dev The address of the new implementation.\n */\n address public immutable NEW_IMPL;\n /**\n * @dev The address of the previous implementation.\n */\n address public immutable PREV_IMPL;\n\n /**\n * @dev Modifier that executes the function when conditions are met.\n */\n modifier whenConditionsAreMet() virtual {\n _;\n if (_isConditionMet()) {\n try this.selfUpgrade{ gas: _gasStipenedNoGrief() }() {} catch {}\n }\n }\n\n /**\n * @dev Modifier that only allows delegate calls from the admin proxy storage.\n */\n modifier onlyDelegateFromProxyStorage() virtual {\n _requireDelegateFromProxyStorage();\n _;\n }\n\n /**\n * @dev Constructs the ConditionalImplementControl contract.\n * @param proxyStorage The address of the proxy that is allowed to delegate to this contract.\n * @param prevImpl The address of the current contract implementation.\n * @param newImpl The address of the new contract implementation.\n */\n constructor(address proxyStorage, address prevImpl, address newImpl) {\n _requireHasCode(newImpl);\n _requireHasCode(prevImpl);\n _requireHasCode(proxyStorage);\n\n address[] memory addrs = new address[](3);\n addrs[0] = proxyStorage;\n addrs[1] = prevImpl;\n addrs[2] = newImpl;\n if (addrs.hasDuplicate()) revert AddressArrayUtils.ErrDuplicated(msg.sig);\n\n PROXY_STORAGE = proxyStorage;\n NEW_IMPL = newImpl;\n PREV_IMPL = prevImpl;\n }\n\n /**\n * @dev Fallback function that forwards the call to the current or new contract implementation based on a condition.\n */\n fallback() external payable virtual onlyDelegateFromProxyStorage {\n _fallback();\n }\n\n /**\n * @dev Receive function that forwards the call to the current or new contract implementation based on a condition.\n */\n receive() external payable virtual onlyDelegateFromProxyStorage {\n _fallback();\n }\n\n /**\n * @dev See {IConditionalImplementControl-selfUpgrade}.\n */\n function selfUpgrade() external virtual onlyDelegateFromProxyStorage onlySelfCall {\n _upgradeTo(NEW_IMPL);\n }\n\n function _upgradeTo(address newImplementation) internal {\n assembly (\"memory-safe\") {\n sstore(_IMPLEMENTATION_SLOT, newImplementation)\n }\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Internal function to get the current version of the contract implementation.\n * @return The address of the current version.\n */\n function _getConditionedImplementation() internal view virtual returns (address) {\n return _isConditionMet() ? NEW_IMPL : PREV_IMPL;\n }\n\n /**\n * @dev Internal function to check if the condition for switching implementation is met.\n * @return the boolean indicating if condition is met.\n */\n function _isConditionMet() internal view virtual returns (bool) {}\n\n /**\n * @dev Logic for fallback function.\n */\n function _fallback() internal virtual {\n bytes memory returnData = _dispatchCall(_getConditionedImplementation());\n assembly {\n return(add(returnData, 0x20), mload(returnData))\n }\n }\n\n /**\n * @dev Internal function to dispatch the call to the specified version.\n * @param impl The address of the version to call.\n * @return returnData The return data of the call.\n */\n function _dispatchCall(address impl) internal virtual whenConditionsAreMet returns (bytes memory returnData) {\n (bool success, bytes memory returnOrRevertData) = impl.delegatecall(msg.data);\n success.handleRevert(msg.sig, returnOrRevertData);\n assembly {\n returnData := returnOrRevertData\n }\n }\n\n /**\n * @dev Internal function to check if the caller is delegating from proxy storage.\n * Throws an error if the current implementation of the proxy storage is not this contract.\n */\n function _requireDelegateFromProxyStorage() private view {\n if (address(this) != PROXY_STORAGE) revert ErrDelegateFromUnknownOrigin(address(this));\n }\n\n /**\n * @dev Internal method to check method caller.\n *\n * Requirements:\n *\n * - The method caller must be this contract.\n *\n */\n function _requireSelfCall() internal view virtual override {\n if (msg.sender != PROXY_STORAGE) revert ErrOnlySelfCall(msg.sig);\n }\n\n /**\n * @dev Suggested gas stipend for contract to call {selfUpgrade} function.\n */\n function _gasStipenedNoGrief() internal pure virtual returns (uint256) {\n // Gas stipend for contract to perform a few read and write operations on storage, but\n // low enough to prevent comsuming gas exhaustively when function call are reverted.\n // Multiply by a small constant (e.g. 2), if needed.\n return 50_000;\n }\n}\n" + }, + "contracts/extensions/WithdrawalLimitation.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./GatewayV2.sol\";\n\nabstract contract WithdrawalLimitation is GatewayV2 {\n /// @dev Error of invalid percentage.\n error ErrInvalidPercentage();\n\n /// @dev Emitted when the high-tier vote weight threshold is updated\n event HighTierVoteWeightThresholdUpdated(\n uint256 indexed nonce,\n uint256 indexed numerator,\n uint256 indexed denominator,\n uint256 previousNumerator,\n uint256 previousDenominator\n );\n /// @dev Emitted when the thresholds for high-tier withdrawals that requires high-tier vote weights are updated\n event HighTierThresholdsUpdated(address[] tokens, uint256[] thresholds);\n /// @dev Emitted when the thresholds for locked withdrawals are updated\n event LockedThresholdsUpdated(address[] tokens, uint256[] thresholds);\n /// @dev Emitted when the fee percentages to unlock withdraw are updated\n event UnlockFeePercentagesUpdated(address[] tokens, uint256[] percentages);\n /// @dev Emitted when the daily limit thresholds are updated\n event DailyWithdrawalLimitsUpdated(address[] tokens, uint256[] limits);\n\n uint256 public constant _MAX_PERCENTAGE = 1_000_000;\n\n uint256 internal _highTierVWNum;\n uint256 internal _highTierVWDenom;\n\n /// @dev Mapping from mainchain token => the amount thresholds for high-tier withdrawals that requires high-tier vote weights\n mapping(address => uint256) public highTierThreshold;\n /// @dev Mapping from mainchain token => the amount thresholds to lock withdrawal\n mapping(address => uint256) public lockedThreshold;\n /// @dev Mapping from mainchain token => unlock fee percentages for unlocker\n /// @notice Values 0-1,000,000 map to 0%-100%\n mapping(address => uint256) public unlockFeePercentages;\n /// @dev Mapping from mainchain token => daily limit amount for withdrawal\n mapping(address => uint256) public dailyWithdrawalLimit;\n /// @dev Mapping from token address => today withdrawal amount\n mapping(address => uint256) public lastSyncedWithdrawal;\n /// @dev Mapping from token address => last date synced to record the `lastSyncedWithdrawal`\n mapping(address => uint256) public lastDateSynced;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @dev Override `GatewayV2-setThreshold`.\n *\n * Requirements:\n * - The high-tier vote weight threshold must equal to or larger than the normal threshold.\n *\n */\n function setThreshold(\n uint256 _numerator,\n uint256 _denominator\n ) external virtual override onlyAdmin returns (uint256 _previousNum, uint256 _previousDenom) {\n (_previousNum, _previousDenom) = _setThreshold(_numerator, _denominator);\n _verifyThresholds();\n }\n\n /**\n * @dev Returns the high-tier vote weight threshold.\n */\n function getHighTierVoteWeightThreshold() external view virtual returns (uint256, uint256) {\n return (_highTierVWNum, _highTierVWDenom);\n }\n\n /**\n * @dev Checks whether the `_voteWeight` passes the high-tier vote weight threshold.\n */\n function checkHighTierVoteWeightThreshold(uint256 _voteWeight) external view virtual returns (bool) {\n return _voteWeight * _highTierVWDenom >= _highTierVWNum * _getTotalWeight();\n }\n\n /**\n * @dev Sets high-tier vote weight threshold and returns the old one.\n *\n * Requirements:\n * - The method caller is admin.\n * - The high-tier vote weight threshold must equal to or larger than the normal threshold.\n *\n * Emits the `HighTierVoteWeightThresholdUpdated` event.\n *\n */\n function setHighTierVoteWeightThreshold(\n uint256 _numerator,\n uint256 _denominator\n ) external virtual onlyAdmin returns (uint256 _previousNum, uint256 _previousDenom) {\n (_previousNum, _previousDenom) = _setHighTierVoteWeightThreshold(_numerator, _denominator);\n _verifyThresholds();\n }\n\n /**\n * @dev Sets the thresholds for high-tier withdrawals that requires high-tier vote weights.\n *\n * Requirements:\n * - The method caller is admin.\n * - The arrays have the same length and its length larger than 0.\n *\n * Emits the `HighTierThresholdsUpdated` event.\n *\n */\n function setHighTierThresholds(\n address[] calldata _tokens,\n uint256[] calldata _thresholds\n ) external virtual onlyAdmin {\n if (_tokens.length == 0) revert ErrEmptyArray();\n _setHighTierThresholds(_tokens, _thresholds);\n }\n\n /**\n * @dev Sets the amount thresholds to lock withdrawal.\n *\n * Requirements:\n * - The method caller is admin.\n * - The arrays have the same length and its length larger than 0.\n *\n * Emits the `LockedThresholdsUpdated` event.\n *\n */\n function setLockedThresholds(address[] calldata _tokens, uint256[] calldata _thresholds) external virtual onlyAdmin {\n if (_tokens.length == 0) revert ErrEmptyArray();\n _setLockedThresholds(_tokens, _thresholds);\n }\n\n /**\n * @dev Sets fee percentages to unlock withdrawal.\n *\n * Requirements:\n * - The method caller is admin.\n * - The arrays have the same length and its length larger than 0.\n *\n * Emits the `UnlockFeePercentagesUpdated` event.\n *\n */\n function setUnlockFeePercentages(\n address[] calldata _tokens,\n uint256[] calldata _percentages\n ) external virtual onlyAdmin {\n if (_tokens.length == 0) revert ErrEmptyArray();\n _setUnlockFeePercentages(_tokens, _percentages);\n }\n\n /**\n * @dev Sets daily limit amounts for the withdrawals.\n *\n * Requirements:\n * - The method caller is admin.\n * - The arrays have the same length and its length larger than 0.\n *\n * Emits the `DailyWithdrawalLimitsUpdated` event.\n *\n */\n function setDailyWithdrawalLimits(address[] calldata _tokens, uint256[] calldata _limits) external virtual onlyAdmin {\n if (_tokens.length == 0) revert ErrEmptyArray();\n _setDailyWithdrawalLimits(_tokens, _limits);\n }\n\n /**\n * @dev Checks whether the withdrawal reaches the limitation.\n */\n function reachedWithdrawalLimit(address _token, uint256 _quantity) external view virtual returns (bool) {\n return _reachedWithdrawalLimit(_token, _quantity);\n }\n\n /**\n * @dev Sets high-tier vote weight threshold and returns the old one.\n *\n * Emits the `HighTierVoteWeightThresholdUpdated` event.\n *\n */\n function _setHighTierVoteWeightThreshold(\n uint256 _numerator,\n uint256 _denominator\n ) internal returns (uint256 _previousNum, uint256 _previousDenom) {\n if (_numerator > _denominator) revert ErrInvalidThreshold(msg.sig);\n\n _previousNum = _highTierVWNum;\n _previousDenom = _highTierVWDenom;\n _highTierVWNum = _numerator;\n _highTierVWDenom = _denominator;\n\n unchecked {\n emit HighTierVoteWeightThresholdUpdated(nonce++, _numerator, _denominator, _previousNum, _previousDenom);\n }\n }\n\n /**\n * @dev Sets the thresholds for high-tier withdrawals that requires high-tier vote weights.\n *\n * Requirements:\n * - The array lengths are equal.\n *\n * Emits the `HighTierThresholdsUpdated` event.\n *\n */\n function _setHighTierThresholds(address[] calldata _tokens, uint256[] calldata _thresholds) internal virtual {\n if (_tokens.length != _thresholds.length) revert ErrLengthMismatch(msg.sig);\n\n for (uint256 _i; _i < _tokens.length; ) {\n highTierThreshold[_tokens[_i]] = _thresholds[_i];\n\n unchecked {\n ++_i;\n }\n }\n emit HighTierThresholdsUpdated(_tokens, _thresholds);\n }\n\n /**\n * @dev Sets the amount thresholds to lock withdrawal.\n *\n * Requirements:\n * - The array lengths are equal.\n *\n * Emits the `LockedThresholdsUpdated` event.\n *\n */\n function _setLockedThresholds(address[] calldata _tokens, uint256[] calldata _thresholds) internal virtual {\n if (_tokens.length != _thresholds.length) revert ErrLengthMismatch(msg.sig);\n\n for (uint256 _i; _i < _tokens.length; ) {\n lockedThreshold[_tokens[_i]] = _thresholds[_i];\n\n unchecked {\n ++_i;\n }\n }\n emit LockedThresholdsUpdated(_tokens, _thresholds);\n }\n\n /**\n * @dev Sets fee percentages to unlock withdrawal.\n *\n * Requirements:\n * - The array lengths are equal.\n * - The percentage is equal to or less than 100_000.\n *\n * Emits the `UnlockFeePercentagesUpdated` event.\n *\n */\n function _setUnlockFeePercentages(address[] calldata _tokens, uint256[] calldata _percentages) internal virtual {\n if (_tokens.length != _percentages.length) revert ErrLengthMismatch(msg.sig);\n\n for (uint256 _i; _i < _tokens.length; ) {\n if (_percentages[_i] > _MAX_PERCENTAGE) revert ErrInvalidPercentage();\n\n unlockFeePercentages[_tokens[_i]] = _percentages[_i];\n\n unchecked {\n ++_i;\n }\n }\n emit UnlockFeePercentagesUpdated(_tokens, _percentages);\n }\n\n /**\n * @dev Sets daily limit amounts for the withdrawals.\n *\n * Requirements:\n * - The array lengths are equal.\n *\n * Emits the `DailyWithdrawalLimitsUpdated` event.\n *\n */\n function _setDailyWithdrawalLimits(address[] calldata _tokens, uint256[] calldata _limits) internal virtual {\n if (_tokens.length != _limits.length) revert ErrLengthMismatch(msg.sig);\n\n for (uint256 _i; _i < _tokens.length; ) {\n dailyWithdrawalLimit[_tokens[_i]] = _limits[_i];\n\n unchecked {\n ++_i;\n }\n }\n emit DailyWithdrawalLimitsUpdated(_tokens, _limits);\n }\n\n /**\n * @dev Checks whether the withdrawal reaches the daily limitation.\n *\n * Requirements:\n * - The daily withdrawal threshold should not apply for locked withdrawals.\n *\n */\n function _reachedWithdrawalLimit(address _token, uint256 _quantity) internal view virtual returns (bool) {\n if (_lockedWithdrawalRequest(_token, _quantity)) {\n return false;\n }\n\n uint256 _currentDate = block.timestamp / 1 days;\n if (_currentDate > lastDateSynced[_token]) {\n return dailyWithdrawalLimit[_token] <= _quantity;\n } else {\n return dailyWithdrawalLimit[_token] <= lastSyncedWithdrawal[_token] + _quantity;\n }\n }\n\n /**\n * @dev Record withdrawal token.\n */\n function _recordWithdrawal(address _token, uint256 _quantity) internal virtual {\n uint256 _currentDate = block.timestamp / 1 days;\n if (_currentDate > lastDateSynced[_token]) {\n lastDateSynced[_token] = _currentDate;\n lastSyncedWithdrawal[_token] = _quantity;\n } else {\n lastSyncedWithdrawal[_token] += _quantity;\n }\n }\n\n /**\n * @dev Returns whether the withdrawal request is locked or not.\n */\n function _lockedWithdrawalRequest(address _token, uint256 _quantity) internal view virtual returns (bool) {\n return lockedThreshold[_token] <= _quantity;\n }\n\n /**\n * @dev Computes fee percentage.\n */\n function _computeFeePercentage(uint256 _amount, uint256 _percentage) internal view virtual returns (uint256) {\n return (_amount * _percentage) / _MAX_PERCENTAGE;\n }\n\n /**\n * @dev Returns high-tier vote weight.\n */\n function _highTierVoteWeight(uint256 _totalWeight) internal view virtual returns (uint256) {\n return (_highTierVWNum * _totalWeight + _highTierVWDenom - 1) / _highTierVWDenom;\n }\n\n /**\n * @dev Validates whether the high-tier vote weight threshold is larger than the normal threshold.\n */\n function _verifyThresholds() internal view {\n if (_num * _highTierVWDenom > _highTierVWNum * _denom) revert ErrInvalidThreshold(msg.sig);\n }\n}\n" + }, + "contracts/interfaces/bridge/events/IBridgeManagerEvents.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBridgeManagerEvents {\n /**\n * @dev The structure representing information about a bridge operator.\n * @param addr The address of the bridge operator.\n * @param voteWeight The vote weight assigned to the bridge operator.\n */\n struct BridgeOperatorInfo {\n address addr;\n uint96 voteWeight;\n }\n\n /**\n * @dev Emitted when new bridge operators are added.\n * @param statuses The array of boolean values represents whether the corresponding bridge operator is added successfully.\n * @param voteWeights The array of vote weights assigned to the added bridge operators.\n * @param governors The array of addresses representing the governors associated with the added bridge operators.\n * @param bridgeOperators The array of addresses representing the added bridge operators.\n */\n event BridgeOperatorsAdded(bool[] statuses, uint96[] voteWeights, address[] governors, address[] bridgeOperators);\n\n /**\n * @dev Emitted when bridge operators are removed.\n * @param statuses The array of boolean values representing the statuses of the removed bridge operators.\n * @param bridgeOperators The array of addresses representing the removed bridge operators.\n */\n event BridgeOperatorsRemoved(bool[] statuses, address[] bridgeOperators);\n\n /**\n * @dev Emitted when a bridge operator is updated.\n * @param governor The address of the governor initiating the update.\n * @param fromBridgeOperator The address of the bridge operator being updated.\n * @param toBridgeOperator The updated address of the bridge operator.\n */\n event BridgeOperatorUpdated(\n address indexed governor,\n address indexed fromBridgeOperator,\n address indexed toBridgeOperator\n );\n}\n" + }, + "contracts/interfaces/bridge/events/IBridgeRewardEvents.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBridgeRewardEvents {\n /**\n * @dev Reward-related information for a bridge operator.\n * @param claimed The amount of rewards claimed by the bridge operator.\n * @param slashed The amount of rewards that have been slashed from the bridge operator.\n */\n struct BridgeRewardInfo {\n uint256 claimed;\n uint256 slashed;\n }\n\n /**\n * @dev Emitted when RON are safely received as rewards in the contract.\n * @param from The address of the sender who transferred RON tokens as rewards.\n * @param balanceBefore The balance of the contract before receiving the RON tokens.\n * @param amount The amount of RON received.\n */\n event SafeReceived(address indexed from, uint256 balanceBefore, uint256 amount);\n /// @dev Event emitted when the reward per period config is updated.\n event UpdatedRewardPerPeriod(uint256 newRewardPerPeriod);\n /// @dev Event emitted when the reward of the `operator` is scattered with `amount`.\n event BridgeRewardScattered(uint256 indexed period, address operator, uint256 amount);\n /// @dev Event emitted when the reward of the `operator` is slashed with `amount`.\n event BridgeRewardSlashed(uint256 indexed period, address operator, uint256 amount);\n /// @dev Event emitted when the reward of the `operator` is scattered with `amount` but failed to transfer.\n event BridgeRewardScatterFailed(uint256 indexed period, address operator, uint256 amount);\n /// @dev Event emitted when the requesting period to sync is too far.\n event BridgeRewardSyncTooFarPeriod(uint256 requestingPeriod, uint256 latestPeriod);\n}\n" + }, + "contracts/interfaces/bridge/events/IBridgeSlashEvents.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBridgeSlashEvents {\n /**\n * @dev Enumeration representing the slashing tiers for bridge operators.\n */\n enum Tier {\n Tier0,\n Tier1,\n Tier2\n }\n\n /**\n * @dev Struct representing the status of a bridge operator.\n */\n struct BridgeSlashInfo {\n uint128 slashUntilPeriod;\n uint128 newlyAddedAtPeriod;\n }\n\n /**\n * @dev Event emitted when a bridge operator is slashed.\n * @param tier The slash tier of the operator.\n * @param bridgeOperator The address of the slashed bridge operator.\n * @param period The period in which the operator is slashed.\n * @param slashUntilPeriod The period until which the operator is penalized.\n */\n event Slashed(Tier indexed tier, address indexed bridgeOperator, uint256 indexed period, uint256 slashUntilPeriod);\n\n /**\n * @dev Emitted when a removal request is made for a bridge operator.\n * @param period The period for which the removal request is made.\n * @param bridgeOperator The address of the bridge operator being requested for removal.\n */\n event RemovalRequested(uint256 indexed period, address indexed bridgeOperator);\n}\n" + }, + "contracts/interfaces/bridge/IBridgeManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IBridgeManagerEvents } from \"./events/IBridgeManagerEvents.sol\";\n\n/**\n * @title IBridgeManager\n * @dev The interface for managing bridge operators.\n */\ninterface IBridgeManager is IBridgeManagerEvents {\n /**\n * @dev The domain separator used for computing hash digests in the contract.\n */\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n /**\n * @dev Returns the total number of bridge operators.\n * @return The total number of bridge operators.\n */\n function totalBridgeOperator() external view returns (uint256);\n\n /**\n * @dev Checks if the given address is a bridge operator.\n * @param addr The address to check.\n * @return A boolean indicating whether the address is a bridge operator.\n */\n function isBridgeOperator(address addr) external view returns (bool);\n\n /**\n * @dev Retrieves the full information of all registered bridge operators.\n *\n * This external function allows external callers to obtain the full information of all the registered bridge operators.\n * The returned arrays include the addresses of governors, bridge operators, and their corresponding vote weights.\n *\n * @return governors An array of addresses representing the governors of each bridge operator.\n * @return bridgeOperators An array of addresses representing the registered bridge operators.\n * @return weights An array of uint256 values representing the vote weights of each bridge operator.\n *\n * Note: The length of each array will be the same, and the order of elements corresponds to the same bridge operator.\n *\n * Example Usage:\n * ```\n * (address[] memory governors, address[] memory bridgeOperators, uint256[] memory weights) = getFullBridgeOperatorInfos();\n * for (uint256 i = 0; i < bridgeOperators.length; i++) {\n * // Access individual information for each bridge operator.\n * address governor = governors[i];\n * address bridgeOperator = bridgeOperators[i];\n * uint256 weight = weights[i];\n * // ... (Process or use the information as required) ...\n * }\n * ```\n *\n */\n function getFullBridgeOperatorInfos()\n external\n view\n returns (address[] memory governors, address[] memory bridgeOperators, uint96[] memory weights);\n\n /**\n * @dev Returns total weights of the governor list.\n */\n function sumGovernorsWeight(address[] calldata governors) external view returns (uint256 sum);\n\n /**\n * @dev Returns total weights.\n */\n function getTotalWeight() external view returns (uint256);\n\n /**\n * @dev Returns an array of all bridge operators.\n * @return An array containing the addresses of all bridge operators.\n */\n function getBridgeOperators() external view returns (address[] memory);\n\n /**\n * @dev Returns an array of bridge operators correspoding to governor addresses.\n * @return bridgeOperators_ An array containing the addresses of all bridge operators.\n */\n function getBridgeOperatorOf(address[] calldata gorvernors) external view returns (address[] memory bridgeOperators_);\n\n /**\n * @dev Retrieves the governors corresponding to a given array of bridge operators.\n * This external function allows external callers to obtain the governors associated with a given array of bridge operators.\n * The function takes an input array `bridgeOperators` containing bridge operator addresses and returns an array of corresponding governors.\n * @param bridgeOperators An array of bridge operator addresses for which governors are to be retrieved.\n * @return governors An array of addresses representing the governors corresponding to the provided bridge operators.\n */\n function getGovernorsOf(address[] calldata bridgeOperators) external view returns (address[] memory governors);\n\n /**\n * @dev External function to retrieve the vote weight of a specific governor.\n * @param governor The address of the governor to get the vote weight for.\n * @return voteWeight The vote weight of the specified governor.\n */\n function getGovernorWeight(address governor) external view returns (uint96);\n\n /**\n * @dev External function to retrieve the vote weight of a specific bridge operator.\n * @param bridgeOperator The address of the bridge operator to get the vote weight for.\n * @return weight The vote weight of the specified bridge operator.\n */\n function getBridgeOperatorWeight(address bridgeOperator) external view returns (uint96 weight);\n\n /**\n * @dev Returns the weights of a list of governor addresses.\n */\n function getGovernorWeights(address[] calldata governors) external view returns (uint96[] memory weights);\n\n /**\n * @dev Returns an array of all governors.\n * @return An array containing the addresses of all governors.\n */\n function getGovernors() external view returns (address[] memory);\n\n /**\n * @dev Adds multiple bridge operators.\n * @param governors An array of addresses of hot/cold wallets for bridge operator to update their node address.\n * @param bridgeOperators An array of addresses representing the bridge operators to add.\n * @return addeds An array of booleans indicating whether each bridge operator was added successfully.\n *\n * Note: return boolean array `addeds` indicates whether a group (voteWeight, governor, operator) are recorded.\n * It is expected that FE/BE staticcall to the function first to get the return values and handle it correctly.\n * Governors are expected to see the outcome of this function and decide if they want to vote for the proposal or not.\n *\n * Example Usage:\n * Making an `eth_call` in ethers.js\n * ```\n * const {addeds} = await bridgeManagerContract.callStatic.addBridgeOperators(\n * voteWeights,\n * governors,\n * bridgeOperators,\n * // overriding the caller to the contract itself since we use `onlySelfCall` guard\n * {from: bridgeManagerContract.address}\n * )\n * const filteredOperators = bridgeOperators.filter((_, index) => addeds[index]);\n * const filteredWeights = weights.filter((_, index) => addeds[index]);\n * const filteredGovernors = governors.filter((_, index) => addeds[index]);\n * // ... (Process or use the information as required) ...\n * ```\n */\n function addBridgeOperators(\n uint96[] calldata voteWeights,\n address[] calldata governors,\n address[] calldata bridgeOperators\n ) external returns (bool[] memory addeds);\n\n /**\n * @dev Removes multiple bridge operators.\n * @param bridgeOperators An array of addresses representing the bridge operators to remove.\n * @return removeds An array of booleans indicating whether each bridge operator was removed successfully.\n *\n * * Note: return boolean array `removeds` indicates whether a group (voteWeight, governor, operator) are recorded.\n * It is expected that FE/BE staticcall to the function first to get the return values and handle it correctly.\n * Governors are expected to see the outcome of this function and decide if they want to vote for the proposal or not.\n *\n * Example Usage:\n * Making an `eth_call` in ethers.js\n * ```\n * const {removeds} = await bridgeManagerContract.callStatic.removeBridgeOperators(\n * bridgeOperators,\n * // overriding the caller to the contract itself since we use `onlySelfCall` guard\n * {from: bridgeManagerContract.address}\n * )\n * const filteredOperators = bridgeOperators.filter((_, index) => removeds[index]);\n * // ... (Process or use the information as required) ...\n * ```\n */\n function removeBridgeOperators(address[] calldata bridgeOperators) external returns (bool[] memory removeds);\n\n /**\n * @dev Governor updates their corresponding governor and/or operator address.\n * Requirements:\n * - The caller must the governor of the operator that is requested changes.\n * @param bridgeOperator The address of the bridge operator to update.\n */\n function updateBridgeOperator(address bridgeOperator) external;\n}\n" + }, + "contracts/interfaces/bridge/IBridgeManagerCallback.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title IBridgeManagerCallback\n * @dev Interface for the callback functions to be implemented by the Bridge Manager contract.\n */\ninterface IBridgeManagerCallback is IERC165 {\n /**\n * @dev Handles the event when bridge operators are added.\n * @param bridgeOperators The addresses of the bridge operators.\n * @param addeds The corresponding boolean values indicating whether the operators were added or not.\n * @return selector The selector of the function being called.\n */\n function onBridgeOperatorsAdded(\n address[] memory bridgeOperators,\n bool[] memory addeds\n ) external returns (bytes4 selector);\n\n /**\n * @dev Handles the event when bridge operators are removed.\n * @param bridgeOperators The addresses of the bridge operators.\n * @param removeds The corresponding boolean values indicating whether the operators were removed or not.\n * @return selector The selector of the function being called.\n */\n function onBridgeOperatorsRemoved(\n address[] memory bridgeOperators,\n bool[] memory removeds\n ) external returns (bytes4 selector);\n\n /**\n * @dev Handles the event when a bridge operator is updated.\n * @param currentBridgeOperator The address of the current bridge operator.\n * @param newbridgeOperator The new address of the bridge operator.\n * @return selector The selector of the function being called.\n */\n function onBridgeOperatorUpdated(\n address currentBridgeOperator,\n address newbridgeOperator\n ) external returns (bytes4 selector);\n}\n" + }, + "contracts/interfaces/bridge/IBridgeManagerCallbackRegister.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBridgeManagerCallbackRegister {\n /**\n * @dev Emitted when the contract notifies multiple registers with statuses and return data.\n */\n event Notified(bytes callData, address[] registers, bool[] statuses, bytes[] returnDatas);\n\n /**\n * @dev Retrieves the addresses of registered callbacks.\n * @return registers An array containing the addresses of registered callbacks.\n */\n function getCallbackRegisters() external view returns (address[] memory registers);\n\n /**\n * @dev Registers multiple callbacks with the bridge.\n * @param registers The array of callback addresses to register.\n * @return registereds An array indicating the success status of each registration.\n */\n function registerCallbacks(address[] calldata registers) external returns (bool[] memory registereds);\n\n /**\n * @dev Unregisters multiple callbacks from the bridge.\n * @param registers The array of callback addresses to unregister.\n * @return unregistereds An array indicating the success status of each unregistration.\n */\n function unregisterCallbacks(address[] calldata registers) external returns (bool[] memory unregistereds);\n}\n" + }, + "contracts/interfaces/bridge/IBridgeReward.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport { IBridgeRewardEvents } from \"./events/IBridgeRewardEvents.sol\";\n\ninterface IBridgeReward is IBridgeRewardEvents {\n /**\n * @dev This function allows bridge operators to manually synchronize the reward for a given period length.\n * @param periodLength The length of the reward period for which synchronization is requested.\n */\n function syncReward(uint256 periodLength) external;\n\n /**\n * @dev Receives RON from any address.\n */\n function receiveRON() external payable;\n\n /**\n * @dev Invoke calculate and transfer reward to operators based on their performance.\n *\n * Requirements:\n * - This method is only called once each period.\n * - The caller must be the bridge tracking contract or a bridge operator.\n */\n function execSyncReward(\n address[] calldata operators,\n uint256[] calldata ballots,\n uint256 totalBallot,\n uint256 totalVote,\n uint256 period\n ) external;\n\n /**\n * @dev Retrieve the total amount of rewards that have been topped up in the contract.\n * @return totalRewardToppedUp The total rewards topped up value.\n */\n function getTotalRewardToppedUp() external view returns (uint256);\n\n /**\n * @dev Retrieve the total amount of rewards that have been scattered to bridge operators in the contract.\n * @return totalRewardScattered The total rewards scattered value.\n */\n function getTotalRewardScattered() external view returns (uint256);\n\n /**\n * @dev Getter for all bridge operators per period.\n */\n function getRewardPerPeriod() external view returns (uint256);\n\n /**\n * @dev External function to retrieve the latest rewarded period in the contract.\n * @return latestRewardedPeriod The latest rewarded period value.\n */\n function getLatestRewardedPeriod() external view returns (uint256);\n\n /**\n * @dev Setter for all bridge operators per period.\n */\n function setRewardPerPeriod(uint256 rewardPerPeriod) external;\n}\n" + }, + "contracts/interfaces/bridge/IBridgeSlash.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IBridgeSlashEvents } from \"./events/IBridgeSlashEvents.sol\";\n\n/**\n * @title IBridgeSlash\n * @dev Interface for the BridgeSlash contract to manage slashing functionality for bridge operators.\n */\ninterface IBridgeSlash is IBridgeSlashEvents {\n /**\n * @dev Slashes the unavailability of bridge operators during a specific period.\n * @param period The period to slash the bridge operators for.\n */\n function execSlashBridgeOperators(\n address[] calldata operators,\n uint256[] calldata ballots,\n uint256 totalBallot,\n uint256 totalVote,\n uint256 period\n ) external returns (bool slashed);\n\n /**\n * @dev Returns the penalize durations for the specified bridge operators.\n * @param bridgeOperators The addresses of the bridge operators.\n * @return untilPeriods The penalized periods for the bridge operators.\n */\n function getSlashUntilPeriodOf(address[] calldata bridgeOperators) external returns (uint256[] memory untilPeriods);\n\n /**\n * @dev Retrieves the added periods of the specified bridge operators.\n * @param bridgeOperators An array of bridge operator addresses.\n * @return addedPeriods An array of uint256 values representing the added periods for each bridge operator.\n */\n function getAddedPeriodOf(address[] calldata bridgeOperators) external view returns (uint256[] memory addedPeriods);\n\n /**\n * @dev Gets the slash tier based on the given ballot and total ballots.\n * @param ballot The ballot count for a bridge operator.\n * @param totalVote The total vote count for the period.\n * @return tier The slash tier.\n */\n function getSlashTier(uint256 ballot, uint256 totalVote) external pure returns (Tier tier);\n\n /**\n * @dev Retrieve the penalty durations for different slash tiers.\n * @return penaltyDurations The array of penalty durations for each slash tier.\n */\n function getPenaltyDurations() external pure returns (uint256[] memory penaltyDurations);\n\n /**\n * @dev Returns the penalty duration for Tier 1 slashing.\n * @return The duration in period number for Tier 1 slashing.\n */\n function TIER_1_PENALTY_DURATION() external view returns (uint256);\n\n /**\n * @dev Returns the penalty duration for Tier 2 slashing.\n * @return The duration in period number for Tier 2 slashing.\n */\n function TIER_2_PENALTY_DURATION() external view returns (uint256);\n\n /**\n * @dev Returns the threshold duration for removing bridge operators.\n * @return The duration in period number that exceeds which a bridge operator will be removed.\n */\n function REMOVE_DURATION_THRESHOLD() external view returns (uint256);\n\n /**\n * @dev External function to retrieve the value of the minimum vote threshold to execute slashing rule.\n * @return minimumVoteThreshold The minimum vote threshold value.\n */\n function MINIMUM_VOTE_THRESHOLD() external view returns (uint256);\n}\n" + }, + "contracts/interfaces/bridge/IBridgeTracking.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBridgeTracking {\n struct Request {\n VoteKind kind;\n uint256 id;\n }\n\n enum VoteKind {\n Deposit,\n Withdrawal,\n MainchainWithdrawal\n }\n\n event ExternalCallFailed(address indexed to, bytes4 indexed msgSig, bytes reason);\n\n /**\n * @dev Returns the block that allow incomming mutable call.\n */\n function startedAtBlock() external view returns (uint256);\n\n /**\n * @dev Returns the total number of votes at the specific period `_period`.\n */\n function totalVote(uint256 _period) external view returns (uint256);\n\n /**\n * @dev Returns the total number of ballots at the specific period `_period`.\n */\n function totalBallot(uint256 _period) external view returns (uint256);\n\n /**\n * @dev Returns the total number of ballots of bridge operators at the specific period `_period`.\n */\n function getManyTotalBallots(\n uint256 _period,\n address[] calldata _bridgeOperators\n ) external view returns (uint256[] memory);\n\n /**\n * @dev Returns the total number of ballots of a bridge operator at the specific period `_period`.\n */\n function totalBallotOf(uint256 _period, address _bridgeOperator) external view returns (uint256);\n\n /**\n * @dev Handles the request once it is approved.\n *\n * Requirements:\n * - The method caller is the bridge contract.\n *\n */\n function handleVoteApproved(VoteKind _kind, uint256 _requestId) external;\n\n /**\n * @dev Records vote for a receipt and a operator.\n *\n * Requirements:\n * - The method caller is the bridge contract.\n *\n */\n function recordVote(VoteKind _kind, uint256 _requestId, address _operator) external;\n}\n" + }, + "contracts/interfaces/collections/IHasContracts.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport { ContractType } from \"../../utils/ContractType.sol\";\n\ninterface IHasContracts {\n /// @dev Error of invalid role.\n error ErrContractTypeNotFound(ContractType contractType);\n\n /// @dev Emitted when a contract is updated.\n event ContractUpdated(ContractType indexed contractType, address indexed addr);\n\n /**\n * @dev Returns the address of a contract with a specific role.\n * Throws an error if no contract is set for the specified role.\n *\n * @param contractType The role of the contract to retrieve.\n * @return contract_ The address of the contract with the specified role.\n */\n function getContract(ContractType contractType) external view returns (address contract_);\n\n /**\n * @dev Sets the address of a contract with a specific role.\n * Emits the event {ContractUpdated}.\n * @param contractType The role of the contract to set.\n * @param addr The address of the contract to set.\n */\n function setContract(ContractType contractType, address addr) external;\n}\n" + }, + "contracts/interfaces/consumers/ChainTypeConsumer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ChainTypeConsumer {\n enum ChainType {\n RoninChain,\n Mainchain\n }\n}\n" + }, + "contracts/interfaces/consumers/MappedTokenConsumer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../../libraries/Token.sol\";\n\ninterface MappedTokenConsumer {\n struct MappedToken {\n Token.Standard erc;\n address tokenAddr;\n }\n}\n" + }, + "contracts/interfaces/consumers/PeriodWrapperConsumer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface PeriodWrapperConsumer {\n struct PeriodWrapper {\n // Inner value.\n uint256 inner;\n // Last period number that the info updated.\n uint256 lastPeriod;\n }\n}\n" + }, + "contracts/interfaces/consumers/SignatureConsumer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface SignatureConsumer {\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n}\n" + }, + "contracts/interfaces/consumers/VoteStatusConsumer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface VoteStatusConsumer {\n enum VoteStatus {\n Pending,\n Approved,\n Executed,\n Rejected,\n Expired\n }\n}\n" + }, + "contracts/interfaces/consumers/WeightedAddressConsumer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface WeightedAddressConsumer {\n struct WeightedAddress {\n address addr;\n uint256 weight;\n }\n}\n" + }, + "contracts/interfaces/IBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBridge {\n /**\n * @dev Replaces the old bridge operator list by the new one.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emitted the event `BridgeOperatorsReplaced`.\n *\n */\n function replaceBridgeOperators(address[] calldata) external;\n\n /**\n * @dev Returns the bridge operator list.\n */\n function getBridgeOperators() external view returns (address[] memory);\n}\n" + }, + "contracts/interfaces/IBridgeAdminProposal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { BridgeOperatorsBallot } from \"../libraries/BridgeOperatorsBallot.sol\";\n\ninterface IBridgeAdminProposal {\n /// @dev Emitted when the bridge operators are approved.\n event BridgeOperatorsApproved(uint256 period, uint256 epoch, address[] operators);\n\n /**\n * @dev Returns the last voted block of the bridge voter.\n */\n function lastVotedBlock(address bridgeVoter) external view returns (uint256);\n\n /**\n * @dev Returns the synced bridge operator set info.\n */\n function lastSyncedBridgeOperatorSetInfo()\n external\n view\n returns (BridgeOperatorsBallot.BridgeOperatorSet memory bridgeOperatorSetInfo);\n}\n" + }, + "contracts/interfaces/IERC20Mintable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.2;\n\ninterface IERC20Mintable {\n function mint(address _to, uint256 _value) external returns (bool _success);\n}\n" + }, + "contracts/interfaces/IERC721Mintable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IERC721Mintable {\n function mint(address _to, uint256 _tokenId) external returns (bool);\n}\n" + }, + "contracts/interfaces/IFastFinalityTracking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface IFastFinalityTracking {\n /**\n * @dev Submit list of `voters` who vote for fast finality in the current block.\n *\n * Requirements:\n * - Only called once per block\n * - Only coinbase can call this method\n */\n function recordFinality(address[] calldata voters) external;\n\n /**\n * @dev Returns vote count of `addrs` in the `period`.\n */\n function getManyFinalityVoteCounts(\n uint256 period,\n address[] calldata addrs\n ) external view returns (uint256[] memory voteCounts);\n}\n" + }, + "contracts/interfaces/IMainchainGatewayV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./IWETH.sol\";\nimport \"./consumers/SignatureConsumer.sol\";\nimport \"./consumers/MappedTokenConsumer.sol\";\nimport \"../libraries/Transfer.sol\";\n\ninterface IMainchainGatewayV2 is SignatureConsumer, MappedTokenConsumer {\n /**\n * @dev Error indicating that a query was made for an approved withdrawal.\n */\n error ErrQueryForApprovedWithdrawal();\n\n /**\n * @dev Error indicating that the daily withdrawal limit has been reached.\n */\n error ErrReachedDailyWithdrawalLimit();\n\n /**\n * @dev Error indicating that a query was made for a processed withdrawal.\n */\n error ErrQueryForProcessedWithdrawal();\n\n /**\n * @dev Error indicating that a query was made for insufficient vote weight.\n */\n error ErrQueryForInsufficientVoteWeight();\n\n /// @dev Emitted when the deposit is requested\n event DepositRequested(bytes32 receiptHash, Transfer.Receipt receipt);\n /// @dev Emitted when the assets are withdrawn\n event Withdrew(bytes32 receiptHash, Transfer.Receipt receipt);\n /// @dev Emitted when the tokens are mapped\n event TokenMapped(address[] mainchainTokens, address[] roninTokens, Token.Standard[] standards);\n /// @dev Emitted when the wrapped native token contract is updated\n event WrappedNativeTokenContractUpdated(IWETH weth);\n /// @dev Emitted when the withdrawal is locked\n event WithdrawalLocked(bytes32 receiptHash, Transfer.Receipt receipt);\n /// @dev Emitted when the withdrawal is unlocked\n event WithdrawalUnlocked(bytes32 receiptHash, Transfer.Receipt receipt);\n\n /**\n * @dev Returns the domain seperator.\n */\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n /**\n * @dev Returns deposit count.\n */\n function depositCount() external view returns (uint256);\n\n /**\n * @dev Sets the wrapped native token contract.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the `WrappedNativeTokenContractUpdated` event.\n *\n */\n function setWrappedNativeTokenContract(IWETH _wrappedToken) external;\n\n /**\n * @dev Returns whether the withdrawal is locked.\n */\n function withdrawalLocked(uint256 withdrawalId) external view returns (bool);\n\n /**\n * @dev Returns the withdrawal hash.\n */\n function withdrawalHash(uint256 withdrawalId) external view returns (bytes32);\n\n /**\n * @dev Locks the assets and request deposit.\n */\n function requestDepositFor(Transfer.Request calldata _request) external payable;\n\n /**\n * @dev Withdraws based on the receipt and the validator signatures.\n * Returns whether the withdrawal is locked.\n *\n * Emits the `Withdrew` once the assets are released.\n *\n */\n function submitWithdrawal(\n Transfer.Receipt memory _receipt,\n Signature[] memory _signatures\n ) external returns (bool _locked);\n\n /**\n * @dev Approves a specific withdrawal.\n *\n * Requirements:\n * - The method caller is a validator.\n *\n * Emits the `Withdrew` once the assets are released.\n *\n */\n function unlockWithdrawal(Transfer.Receipt calldata _receipt) external;\n\n /**\n * @dev Maps mainchain tokens to Ronin network.\n *\n * Requirement:\n * - The method caller is admin.\n * - The arrays have the same length and its length larger than 0.\n *\n * Emits the `TokenMapped` event.\n *\n */\n function mapTokens(\n address[] calldata _mainchainTokens,\n address[] calldata _roninTokens,\n Token.Standard[] calldata _standards\n ) external;\n\n /**\n * @dev Maps mainchain tokens to Ronin network and sets thresholds.\n *\n * Requirement:\n * - The method caller is admin.\n * - The arrays have the same length and its length larger than 0.\n *\n * Emits the `TokenMapped` event.\n *\n */\n function mapTokensAndThresholds(\n address[] calldata _mainchainTokens,\n address[] calldata _roninTokens,\n Token.Standard[] calldata _standards,\n uint256[][4] calldata _thresholds\n ) external;\n\n /**\n * @dev Returns token address on Ronin network.\n * Note: Reverts for unsupported token.\n */\n function getRoninToken(address _mainchainToken) external view returns (MappedToken memory _token);\n}\n" + }, + "contracts/interfaces/IMaintenance.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface IMaintenance {\n /**\n * @dev Error thrown when attempting to schedule an already scheduled event.\n */\n error ErrAlreadyScheduled();\n\n /**\n * @dev Error thrown when referring to a non-existent schedule.\n */\n error ErrUnexistedSchedule();\n\n /**\n * @dev Error thrown when the end block of a schedule is out of range.\n */\n error ErrEndBlockOutOfRange();\n\n /**\n * @dev Error thrown when the start block of a schedule is out of range.\n */\n error ErrStartBlockOutOfRange();\n\n /**\n * @dev Error thrown when attempting to initiate maintenance while already in maintenance mode.\n */\n error ErrAlreadyOnMaintenance();\n\n /**\n * @dev Error thrown when attempting an action before the cooldown period has ended.\n */\n error ErrCooldownTimeNotYetEnded();\n\n /**\n * @dev Error thrown when the total number of schedules exceeds the limit.\n */\n error ErrTotalOfSchedulesExceeded();\n\n /**\n * @dev Error thrown when an invalid maintenance duration is specified.\n */\n error ErrInvalidMaintenanceDuration();\n\n /**\n * @dev Error thrown when an invalid maintenance duration configuration is provided.\n */\n error ErrInvalidMaintenanceDurationConfig();\n\n /**\n * @dev Error thrown when an invalid offset is specified to start the schedule configurations.\n */\n error ErrInvalidOffsetToStartScheduleConfigs();\n\n struct Schedule {\n uint256 from;\n uint256 to;\n uint256 lastUpdatedBlock;\n uint256 requestTimestamp;\n }\n\n /// @dev Emitted when a maintenance is scheduled.\n event MaintenanceScheduled(address indexed consensusAddr, Schedule);\n /// @dev Emitted when a schedule of maintenance is cancelled.\n event MaintenanceScheduleCancelled(address indexed consensusAddr);\n /// @dev Emitted when the maintenance config is updated.\n event MaintenanceConfigUpdated(\n uint256 minMaintenanceDurationInBlock,\n uint256 maxMaintenanceDurationInBlock,\n uint256 minOffsetToStartSchedule,\n uint256 maxOffsetToStartSchedule,\n uint256 maxSchedules,\n uint256 cooldownSecsToMaintain\n );\n\n /**\n * @dev Returns whether the validator `_consensusAddr` maintained at the block number `_block`.\n */\n function checkMaintained(address _consensusAddr, uint256 _block) external view returns (bool);\n\n /**\n * @dev Returns whether the validator `_consensusAddr` maintained in the inclusive range [`_fromBlock`, `_toBlock`] of blocks.\n */\n function checkMaintainedInBlockRange(\n address _consensusAddr,\n uint256 _fromBlock,\n uint256 _toBlock\n ) external view returns (bool);\n\n /**\n * @dev Returns the bool array indicating the validators maintained at block number `_block` or not.\n */\n function checkManyMaintained(address[] calldata _addrList, uint256 _block) external view returns (bool[] memory);\n\n /**\n * @dev Returns a bool array indicating the validators maintained in the inclusive range [`_fromBlock`, `_toBlock`] of blocks or not.\n */\n function checkManyMaintainedInBlockRange(\n address[] calldata _addrList,\n uint256 _fromBlock,\n uint256 _toBlock\n ) external view returns (bool[] memory);\n\n /**\n * @dev Returns whether the validator `_consensusAddr` has scheduled.\n */\n function checkScheduled(address _consensusAddr) external view returns (bool);\n\n /**\n * @dev Returns whether the validator `_consensusAddr`\n */\n function checkCooldownEnded(address _consensusAddr) external view returns (bool);\n\n /**\n * @dev Returns the detailed schedule of the validator `_consensusAddr`.\n */\n function getSchedule(address _consensusAddr) external view returns (Schedule memory);\n\n /**\n * @dev Returns the total of current schedules.\n */\n function totalSchedule() external view returns (uint256 _count);\n\n /**\n * @dev Sets the duration restriction, start time restriction, and max allowed for maintenance.\n *\n * Requirements:\n * - The method caller is admin.\n * - The max duration is larger than the min duration.\n * - The max offset is larger than the min offset.\n *\n * Emits the event `MaintenanceConfigUpdated`.\n *\n */\n function setMaintenanceConfig(\n uint256 _minMaintenanceDurationInBlock,\n uint256 _maxMaintenanceDurationInBlock,\n uint256 _minOffsetToStartSchedule,\n uint256 _maxOffsetToStartSchedule,\n uint256 _maxSchedules,\n uint256 _cooldownSecsToMaintain\n ) external;\n\n /**\n * @dev Returns the min duration for maintenance in block.\n */\n function minMaintenanceDurationInBlock() external view returns (uint256);\n\n /**\n * @dev Returns the max duration for maintenance in block.\n */\n function maxMaintenanceDurationInBlock() external view returns (uint256);\n\n /**\n * @dev The offset to the min block number that the schedule can start\n */\n function minOffsetToStartSchedule() external view returns (uint256);\n\n /**\n * @dev The offset to the max block number that the schedule can start\n */\n function maxOffsetToStartSchedule() external view returns (uint256);\n\n /**\n * @dev Returns the max number of scheduled maintenances.\n */\n function maxSchedule() external view returns (uint256);\n\n /**\n * @dev Schedules for maintenance from `_startedAtBlock` to `_startedAtBlock`.\n *\n * Requirements:\n * - The candidate `_consensusAddr` is the block producer.\n * - The method caller is candidate admin of the candidate `_consensusAddr`.\n * - The candidate `_consensusAddr` has no schedule yet or the previous is done.\n * - The total number of schedules is not larger than `maxSchedules()`.\n * - The start block must be at least `minOffsetToStartSchedule()` and at most `maxOffsetToStartSchedule()` blocks from the current block.\n * - The end block is larger than the start block.\n * - The scheduled duration is larger than the `minMaintenanceDurationInBlock()` and less than the `maxMaintenanceDurationInBlock()`.\n * - The start block is at the start of an epoch.\n * - The end block is at the end of an epoch.\n *\n * Emits the event `MaintenanceScheduled`.\n *\n */\n function schedule(address _consensusAddr, uint256 _startedAtBlock, uint256 _endedAtBlock) external;\n\n /**\n * @dev Cancel the schedule of maintenance for the `_consensusAddr`.\n *\n * Requirements:\n * - The candidate `_consensusAddr` is the block producer.\n * - The method caller is candidate admin of the candidate `_consensusAddr`.\n * - A schedule for the `_consensusAddr` must be existent and not executed yet.\n *\n * Emits the event `MaintenanceScheduleCancelled`.\n */\n function cancelSchedule(address _consensusAddr) external;\n}\n" + }, + "contracts/interfaces/IPauseTarget.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IPauseTarget {\n function pause() external;\n\n function unpause() external;\n\n function paused() external returns (bool);\n}\n" + }, + "contracts/interfaces/IProfile.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../utils/RoleAccess.sol\";\n\ninterface IProfile {\n struct CandidateProfile {\n /**\n * @dev Primary key of the profile, use for backward querying.\n *\n * {Staking} Contract: index of pool\n * {RoninValidatorSet} Contract: index of almost all data related to a validator\n *\n */\n address id;\n /// @dev Consensus address.\n address consensus;\n /// @dev Pool admin address.\n address admin;\n /// @dev Treasury address.\n address payable treasury;\n /// @dev Address to voting proposal.\n address governor;\n /// @dev Public key for fast finality.\n bytes pubkey;\n }\n\n /// @dev Event emitted when a profile with `id` is added.\n event ProfileAdded(address indexed id);\n /// @dev Event emitted when a address in a profile is changed.\n event ProfileAddressChanged(address indexed id, RoleAccess indexed addressType);\n\n /// @dev Error of already existed profile.\n error ErrExistentProfile();\n /// @dev Error of non existed profile.\n error ErrNonExistentProfile();\n\n /// @dev Getter to query full `profile` from `id` address.\n function getId2Profile(address id) external view returns (CandidateProfile memory profile);\n\n /**\n * @notice Add a new profile.\n *\n * @dev Requirements:\n * - The profile must not be existent before.\n * - Only contract admin can call this method.\n */\n function addNewProfile(CandidateProfile memory profile) external;\n\n /**\n * @notice The candidate admin registers a new profile.\n *\n * @dev Requirements:\n * - The profile must not be existent before.\n * - Only user with candidate admin role can call this method.\n */\n\n function registerProfile(CandidateProfile memory profile) external;\n}\n" + }, + "contracts/interfaces/IQuorum.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IQuorum {\n /// @dev Emitted when the threshold is updated\n event ThresholdUpdated(\n uint256 indexed nonce,\n uint256 indexed numerator,\n uint256 indexed denominator,\n uint256 previousNumerator,\n uint256 previousDenominator\n );\n\n /**\n * @dev Returns the threshold.\n */\n function getThreshold() external view returns (uint256 _num, uint256 _denom);\n\n /**\n * @dev Checks whether the `_voteWeight` passes the threshold.\n */\n function checkThreshold(uint256 _voteWeight) external view returns (bool);\n\n /**\n * @dev Returns the minimum vote weight to pass the threshold.\n */\n function minimumVoteWeight() external view returns (uint256);\n\n /**\n * @dev Sets the threshold.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the `ThresholdUpdated` event.\n *\n */\n function setThreshold(\n uint256 _numerator,\n uint256 _denominator\n ) external returns (uint256 _previousNum, uint256 _previousDenom);\n}\n" + }, + "contracts/interfaces/IRoninGatewayV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../libraries/Transfer.sol\";\nimport \"./consumers/MappedTokenConsumer.sol\";\n\ninterface IRoninGatewayV2 is MappedTokenConsumer {\n /**\n * @dev Error thrown when attempting to withdraw funds that have already been migrated.\n */\n error ErrWithdrawalsMigrated();\n\n /**\n * @dev Error thrown when an invalid trusted threshold is specified.\n */\n error ErrInvalidTrustedThreshold();\n\n /**\n * @dev Error thrown when attempting to withdraw funds that have already been withdrawn on the mainchain.\n */\n error ErrWithdrawnOnMainchainAlready();\n\n /// @dev Emitted when the assets are depositted\n event Deposited(bytes32 receiptHash, Transfer.Receipt receipt);\n /// @dev Emitted when the withdrawal is requested\n event WithdrawalRequested(bytes32 receiptHash, Transfer.Receipt);\n /// @dev Emitted when the assets are withdrawn on mainchain\n event MainchainWithdrew(bytes32 receiptHash, Transfer.Receipt receipt);\n /// @dev Emitted when the withdrawal signatures is requested\n event WithdrawalSignaturesRequested(bytes32 receiptHash, Transfer.Receipt);\n /// @dev Emitted when the tokens are mapped\n event TokenMapped(address[] roninTokens, address[] mainchainTokens, uint256[] chainIds, Token.Standard[] standards);\n /// @dev Emitted when the threshold is updated\n event TrustedThresholdUpdated(\n uint256 indexed nonce,\n uint256 indexed numerator,\n uint256 indexed denominator,\n uint256 previousNumerator,\n uint256 previousDenominator\n );\n /// @dev Emitted when a deposit is voted\n event DepositVoted(address indexed bridgeOperator, uint256 indexed id, uint256 indexed chainId, bytes32 receiptHash);\n\n /**\n * @dev Returns withdrawal count.\n */\n function withdrawalCount() external view returns (uint256);\n\n /**\n * @dev Returns withdrawal signatures.\n */\n function getWithdrawalSignatures(\n uint256 _withdrawalId,\n address[] calldata _validators\n ) external view returns (bytes[] memory);\n\n /**\n * @dev Deposits based on the receipt.\n *\n * Requirements:\n * - The method caller is a validator.\n *\n * Emits the `Deposited` once the assets are released.\n *\n * @notice The assets will be transferred whenever the valid call passes the quorum threshold.\n *\n */\n function depositFor(Transfer.Receipt calldata _receipt) external;\n\n /**\n * @dev Marks the withdrawals are done on mainchain and returns the boolean array indicating whether the withdrawal\n * vote is already done before.\n *\n * Requirements:\n * - The method caller is a validator.\n *\n * Emits the `MainchainWithdrew` once the valid call passes the quorum threshold.\n *\n * @notice Not reverting to avoid unnecessary failed transactions because the validators can send transactions at the\n * same time.\n *\n */\n function tryBulkAcknowledgeMainchainWithdrew(uint256[] calldata _withdrawalIds) external returns (bool[] memory);\n\n /**\n * @dev Tries bulk deposits based on the receipts and returns the boolean array indicating whether the deposit vote\n * is already done before. Reverts if the deposit is invalid or is voted by the validator again.\n *\n * Requirements:\n * - The method caller is a validator.\n *\n * Emits the `Deposited` once the assets are released.\n *\n * @notice The assets will be transferred whenever the valid call for the receipt passes the quorum threshold. Not\n * reverting to avoid unnecessary failed transactions because the validators can send transactions at the same time.\n *\n */\n function tryBulkDepositFor(Transfer.Receipt[] calldata _receipts) external returns (bool[] memory);\n\n /**\n * @dev Locks the assets and request withdrawal.\n *\n * Emits the `WithdrawalRequested` event.\n *\n */\n function requestWithdrawalFor(Transfer.Request calldata _request, uint256 _chainId) external;\n\n /**\n * @dev Bulk requests withdrawals.\n *\n * Emits the `WithdrawalRequested` events.\n *\n */\n function bulkRequestWithdrawalFor(Transfer.Request[] calldata _requests, uint256 _chainId) external;\n\n /**\n * @dev Requests withdrawal signatures for a specific withdrawal.\n *\n * Emits the `WithdrawalSignaturesRequested` event.\n *\n */\n function requestWithdrawalSignatures(uint256 _withdrawalId) external;\n\n /**\n * @dev Submits withdrawal signatures.\n *\n * Requirements:\n * - The method caller is a validator.\n *\n */\n function bulkSubmitWithdrawalSignatures(uint256[] calldata _withdrawals, bytes[] calldata _signatures) external;\n\n /**\n * @dev Maps Ronin tokens to mainchain networks.\n *\n * Requirement:\n * - The method caller is admin.\n * - The arrays have the same length and its length larger than 0.\n *\n * Emits the `TokenMapped` event.\n *\n */\n function mapTokens(\n address[] calldata _roninTokens,\n address[] calldata _mainchainTokens,\n uint256[] calldata chainIds,\n Token.Standard[] calldata _standards\n ) external;\n\n /**\n * @dev Returns whether the deposit is casted by the voter.\n */\n function depositVoted(uint256 _chainId, uint256 _depositId, address _voter) external view returns (bool);\n\n /**\n * @dev Returns whether the mainchain withdrew is casted by the voter.\n */\n function mainchainWithdrewVoted(uint256 _withdrawalId, address _voter) external view returns (bool);\n\n /**\n * @dev Returns whether the withdrawal is done on mainchain.\n */\n function mainchainWithdrew(uint256 _withdrawalId) external view returns (bool);\n\n /**\n * @dev Returns mainchain token address.\n * Reverts for unsupported token.\n */\n function getMainchainToken(address _roninToken, uint256 _chainId) external view returns (MappedToken memory _token);\n}\n" + }, + "contracts/interfaces/IRoninGovernanceAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../utils/CommonErrors.sol\";\n\ninterface IRoninGovernanceAdmin {\n /// @dev Emitted when an emergency exit poll is created.\n event EmergencyExitPollCreated(\n bytes32 _voteHash,\n address _consensusAddr,\n address _recipientAfterUnlockedFund,\n uint256 _requestedAt,\n uint256 _expiredAt\n );\n /// @dev Emitted when an emergency exit poll is approved.\n event EmergencyExitPollApproved(bytes32 _voteHash);\n /// @dev Emitted when an emergency exit poll is expired.\n event EmergencyExitPollExpired(bytes32 _voteHash);\n /// @dev Emitted when an emergency exit poll is voted.\n event EmergencyExitPollVoted(bytes32 indexed _voteHash, address indexed _voter);\n\n /**\n * @dev Create a vote to agree that an emergency exit is valid and should return the locked funds back.a\n *\n * Requirements:\n * - The method caller is validator contract.\n *\n */\n function createEmergencyExitPoll(\n address _consensusAddr,\n address _recipientAfterUnlockedFund,\n uint256 _requestedAt,\n uint256 _expiredAt\n ) external;\n}\n" + }, + "contracts/interfaces/IRoninTrustedOrganization.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IQuorum.sol\";\n\ninterface IRoninTrustedOrganization is IQuorum {\n /**\n * @dev Error indicating that a query for a duplicate entry was made.\n */\n error ErrQueryForDupplicated();\n\n /**\n * @dev Error indicating that a query was made for a non-existent consensus address.\n */\n error ErrQueryForNonExistentConsensusAddress();\n\n /**\n * @dev Error indicating that a bridge voter has already been added.\n * @param voter The address of the bridge voter that is already added.\n */\n error ErrBridgeVoterIsAlreadyAdded(address voter);\n\n /**\n * @dev Error indicating that a governor address has already been added.\n * @param addr The address of the governor that is already added.\n */\n error ErrGovernorAddressIsAlreadyAdded(address addr);\n\n /**\n * @dev Error indicating that a consensus address is not added.\n * @param addr The address of the consensus contract that is not added.\n */\n error ErrConsensusAddressIsNotAdded(address addr);\n\n /**\n * @dev Error indicating that a consensus address is already added.\n * @param addr The address of the consensus contract that is already added.\n */\n error ErrConsensusAddressIsAlreadyAdded(address addr);\n\n struct TrustedOrganization {\n // Address of the validator that produces block, e.g. block.coinbase. This is so-called validator address.\n address consensusAddr;\n // Address to voting proposal\n address governor;\n // Address to voting bridge operators\n address bridgeVoter;\n // Its Weight\n uint256 weight;\n // The block that the organization was added\n uint256 addedBlock;\n }\n\n /// @dev Emitted when the trusted organization is added.\n event TrustedOrganizationsAdded(TrustedOrganization[] orgs);\n /// @dev Emitted when the trusted organization is updated.\n event TrustedOrganizationsUpdated(TrustedOrganization[] orgs);\n /// @dev Emitted when the trusted organization is removed.\n event TrustedOrganizationsRemoved(address[] orgs);\n\n /**\n * @dev Adds a list of addresses into the trusted organization.\n *\n * Requirements:\n * - The weights should larger than 0.\n * - The method caller is admin.\n * - The field `addedBlock` should be blank.\n *\n * Emits the event `TrustedOrganizationAdded` once an organization is added.\n *\n */\n function addTrustedOrganizations(TrustedOrganization[] calldata) external;\n\n /**\n * @dev Updates weights for a list of existent trusted organization.\n *\n * Requirements:\n * - The weights should larger than 0.\n * - The method caller is admin.\n *\n * Emits the `TrustedOrganizationUpdated` event.\n *\n */\n function updateTrustedOrganizations(TrustedOrganization[] calldata _list) external;\n\n /**\n * @dev Removes a list of addresses from the trusted organization.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `TrustedOrganizationRemoved` once an organization is removed.\n *\n * @param _consensusAddrs The list of consensus addresses linked to corresponding trusted organization that to be removed.\n */\n function removeTrustedOrganizations(address[] calldata _consensusAddrs) external;\n\n /**\n * @dev Returns total weights.\n */\n function totalWeight() external view returns (uint256);\n\n /**\n * @dev Returns the weight of a consensus.\n */\n function getConsensusWeight(address _consensusAddr) external view returns (uint256);\n\n /**\n * @dev Returns the weight of a governor.\n */\n function getGovernorWeight(address _governor) external view returns (uint256);\n\n /**\n * @dev Returns the weight of a bridge voter.\n */\n function getBridgeVoterWeight(address _addr) external view returns (uint256);\n\n /**\n * @dev Returns the weights of a list of consensus addresses.\n */\n function getConsensusWeights(address[] calldata _list) external view returns (uint256[] memory);\n\n /**\n * @dev Returns the weights of a list of governor addresses.\n */\n function getGovernorWeights(address[] calldata _list) external view returns (uint256[] memory);\n\n /**\n * @dev Returns the weights of a list of bridge voter addresses.\n */\n function getBridgeVoterWeights(address[] calldata _list) external view returns (uint256[] memory);\n\n /**\n * @dev Returns total weights of the consensus list.\n */\n function sumConsensusWeight(address[] calldata _list) external view returns (uint256 _res);\n\n /**\n * @dev Returns total weights of the governor list.\n */\n function sumGovernorWeight(address[] calldata _list) external view returns (uint256 _res);\n\n /**\n * @dev Returns total weights of the bridge voter list.\n */\n function sumBridgeVoterWeight(address[] calldata _list) external view returns (uint256 _res);\n\n /**\n * @dev Returns the trusted organization at `_index`.\n */\n function getTrustedOrganizationAt(uint256 _index) external view returns (TrustedOrganization memory);\n\n /**\n * @dev Returns the number of trusted organizations.\n */\n function countTrustedOrganization() external view returns (uint256);\n\n /**\n * @dev Returns all of the trusted organizations.\n */\n function getAllTrustedOrganizations() external view returns (TrustedOrganization[] memory);\n\n /**\n * @dev Returns the trusted organization by consensus address.\n *\n * Reverts once the consensus address is non-existent.\n */\n function getTrustedOrganization(address _consensusAddr) external view returns (TrustedOrganization memory);\n}\n" + }, + "contracts/interfaces/IStakingVesting.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface IStakingVesting {\n /**\n * @dev Error thrown when attempting to send a bonus that has already been sent.\n */\n error ErrBonusAlreadySent();\n\n /// @dev Emitted when the block bonus for block producer is transferred.\n event BonusTransferred(\n uint256 indexed blockNumber,\n address indexed recipient,\n uint256 blockProducerAmount,\n uint256 bridgeOperatorAmount\n );\n /// @dev Emitted when the transfer of block bonus for block producer is failed.\n event BonusTransferFailed(\n uint256 indexed blockNumber,\n address indexed recipient,\n uint256 blockProducerAmount,\n uint256 bridgeOperatorAmount,\n uint256 contractBalance\n );\n /// @dev Emitted when the block bonus for block producer is updated\n event BlockProducerBonusPerBlockUpdated(uint256);\n /// @dev Emitted when the block bonus for bridge operator is updated\n event BridgeOperatorBonusPerBlockUpdated(uint256);\n /// @dev Emitted when the percent of fast finality reward is updated\n event FastFinalityRewardPercentageUpdated(uint256);\n\n /**\n * @dev Returns the bonus amount for the block producer at `_block`.\n */\n function blockProducerBlockBonus(uint256 _block) external view returns (uint256);\n\n /**\n * @dev Returns the bonus amount for the bridge validator at `_block`.\n */\n function bridgeOperatorBlockBonus(uint256 _block) external view returns (uint256);\n\n /**\n * @dev Returns the percentage of fast finality reward.\n */\n function fastFinalityRewardPercentage() external view returns (uint256);\n\n /**\n * @dev Receives RON from any address.\n */\n function receiveRON() external payable;\n\n /**\n * @dev Returns the last block number that the staking vesting is sent.\n */\n function lastBlockSendingBonus() external view returns (uint256);\n\n /**\n * @dev Transfers the staking vesting for the block producer and the bridge operator whenever a new block is mined.\n *\n * Requirements:\n * - The method caller must be validator contract.\n * - The method must be called only once per block.\n *\n * Emits the event `BonusTransferred` or `BonusTransferFailed`.\n *\n * Notes:\n * - The method does not revert when the contract balance is insufficient to send bonus. This assure the submit reward method\n * will not be reverted, and the underlying nodes does not hang.\n *\n * @param forBlockProducer Indicates whether requesting the bonus for the block procucer, in case of being in jail or relevance.\n * @param forBridgeOperator Indicates whether requesting the bonus for the bridge operator.\n *\n * @return success Whether the transfer is successfully. This returns false mostly because this contract is out of balance.\n * @return blockProducerBonus The amount of bonus actually sent for the block producer, returns 0 when the transfer is failed.\n * @return bridgeOperatorBonus The amount of bonus actually sent for the bridge operator, returns 0 when the transfer is failed.\n * @return fastFinalityRewardPercentage The percent of fast finality reward, returns 0 when the transfer is failed.\n *\n */\n function requestBonus(\n bool forBlockProducer,\n bool forBridgeOperator\n )\n external\n returns (\n bool success,\n uint256 blockProducerBonus,\n uint256 bridgeOperatorBonus,\n uint256 fastFinalityRewardPercentage\n );\n\n /**\n * @dev Sets the bonus amount per block for block producer.\n *\n * Emits the event `BlockProducerBonusPerBlockUpdated`.\n *\n * Requirements:\n * - The method caller is admin.\n *\n */\n function setBlockProducerBonusPerBlock(uint256 _amount) external;\n\n /**\n * @dev Sets the bonus amount per block for bridge operator.\n *\n * Emits the event `BridgeOperatorBonusPerBlockUpdated`.\n *\n * Requirements:\n * - The method caller is admin.\n *\n */\n function setBridgeOperatorBonusPerBlock(uint256 _amount) external;\n\n /**\n * @dev Sets the percent of fast finality reward.\n *\n * Emits the event `FastFinalityRewardPercentageUpdated`.\n *\n * Requirements:\n * - The method caller is admin.\n *\n */\n function setFastFinalityRewardPercentage(uint256 _percent) external;\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IWETH {\n function deposit() external payable;\n\n function withdraw(uint256 _wad) external;\n\n function balanceOf(address) external view returns (uint256);\n}\n" + }, + "contracts/interfaces/slash-indicator/IBaseSlash.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface IBaseSlash {\n enum SlashType {\n UNKNOWN,\n UNAVAILABILITY_TIER_1,\n UNAVAILABILITY_TIER_2,\n DOUBLE_SIGNING,\n BRIDGE_VOTING,\n BRIDGE_OPERATOR_MISSING_VOTE_TIER_1,\n BRIDGE_OPERATOR_MISSING_VOTE_TIER_2,\n UNAVAILABILITY_TIER_3,\n FAST_FINALITY\n }\n\n /// @dev Error thrown when evidence has already been submitted.\n error ErrEvidenceAlreadySubmitted();\n\n /// @dev Emitted when the validator is slashed.\n event Slashed(address indexed validator, SlashType slashType, uint256 period);\n}\n" + }, + "contracts/interfaces/slash-indicator/ICreditScore.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface ICreditScore {\n /**\n * @dev Error thrown when an invalid credit score configuration is provided.\n */\n error ErrInvalidCreditScoreConfig();\n\n /**\n * @dev Error thrown when an invalid cut-off percentage configuration is provided.\n */\n error ErrInvalidCutOffPercentageConfig();\n\n /**\n * @dev Error thrown when the caller's credit score is insufficient to bail out a situation.\n */\n error ErrInsufficientCreditScoreToBailOut();\n\n /**\n * @dev Error thrown when a validator has previously bailed out.\n */\n error ErrValidatorHasBailedOutPreviously();\n\n /**\n * @dev Error thrown when the caller must be jailed in the current period.\n */\n error ErrCallerMustBeJailedInTheCurrentPeriod();\n\n /// @dev Emitted when the configs to credit score is updated. See the method `setCreditScoreConfigs` for param details.\n event CreditScoreConfigsUpdated(\n uint256 gainCreditScore,\n uint256 maxCreditScore,\n uint256 bailOutCostMultiplier,\n uint256 cutOffPercentageAfterBailout\n );\n /// @dev Emitted the credit score of validators is updated.\n event CreditScoresUpdated(address[] validators, uint256[] creditScores);\n /// @dev Emitted when a validator bailed out of jail.\n event BailedOut(address indexed validator, uint256 period, uint256 usedCreditScore);\n\n /**\n * @dev Updates the credit score for the validators.\n *\n * Requirements:\n * - Only validator contract can call this method.\n * - This method is only called at the end of each period.\n *\n * Emits the event `CreditScoresUpdated`.\n *\n */\n function updateCreditScores(address[] calldata _validators, uint256 _period) external;\n\n /**\n * @dev Resets the credit score for the revoked validators.\n *\n * Requirements:\n * - Only validator contract can call this method.\n * - This method is only called at the end of each period.\n *\n * Emits the event `CreditScoresUpdated`.\n *\n */\n function execResetCreditScores(address[] calldata _validators) external;\n\n /**\n * @dev A slashed validator use this method to get out of jail.\n *\n * Requirements:\n * - The `_consensusAddr` must be a validator.\n * - Only validator's admin can call this method.\n *\n * Emits the event `BailedOut`.\n *\n */\n function bailOut(address _consensusAddr) external;\n\n /**\n * @dev Sets the configs to credit score.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `CreditScoreConfigsUpdated`.\n *\n * @param _gainScore The score to gain per period.\n * @param _maxScore The max number of credit score that a validator can hold.\n * @param _bailOutMultiplier The number that will be multiplied with the remaining jailed time to get the cost of bailing out.\n * @param _cutOffPercentage The percentage of reward that the block producer will be cut off from until the end of the period after bailing out.\n *\n */\n function setCreditScoreConfigs(\n uint256 _gainScore,\n uint256 _maxScore,\n uint256 _bailOutMultiplier,\n uint256 _cutOffPercentage\n ) external;\n\n /**\n * @dev Returns the configs related to credit score.\n *\n * @return _gainCreditScore The score to gain per period.\n * @return _maxCreditScore The max number of credit score that a validator can hold.\n * @return _bailOutCostMultiplier The number that will be multiplied with the remaining jailed time to get the cost of bailing out.\n * @return _cutOffPercentageAfterBailout The percentage of reward that the block producer will be cut off from until the end of the period after bailing out.\n *\n */\n function getCreditScoreConfigs()\n external\n view\n returns (\n uint256 _gainCreditScore,\n uint256 _maxCreditScore,\n uint256 _bailOutCostMultiplier,\n uint256 _cutOffPercentageAfterBailout\n );\n\n /**\n * @dev Returns the current credit score of the validator.\n */\n function getCreditScore(address _validator) external view returns (uint256);\n\n /**\n * @dev Returns the current credit score of a list of validators.\n */\n function getManyCreditScores(address[] calldata _validators) external view returns (uint256[] memory _resultList);\n\n /**\n * @dev Returns the whether the `_validator` has been bailed out at the `_period`.\n */\n function checkBailedOutAtPeriod(address _validator, uint256 _period) external view returns (bool);\n}\n" + }, + "contracts/interfaces/slash-indicator/ISlashBridgeOperator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IBaseSlash.sol\";\n\ninterface ISlashBridgeOperator is IBaseSlash {\n /**\n * @dev Error thrown when invalid ratios are provided.\n */\n error ErrInvalidRatios();\n\n /**\n * @dev Emitted when the configs to slash bridge operator is updated. See the method\n * `getBridgeOperatorSlashingConfigs` for param details.\n */\n event BridgeOperatorSlashingConfigsUpdated(\n uint256 missingVotesRatioTier1,\n uint256 missingVotesRatioTier2,\n uint256 jailDurationForMissingVotesRatioTier2,\n uint256 skipBridgeOperatorSlashingThreshold\n );\n\n /**\n * @dev Acknowledges bridge operator slash and emit `Slashed` event correspondingly.\n * @param _tier The tier of the slash, in value of {1, 2}, corresponding to `SlashType.BRIDGE_OPERATOR_MISSING_VOTE_TIER_1`\n * and `SlashType.BRIDGE_OPERATOR_MISSING_VOTE_TIER_2`\n *\n * Requirements:\n * - Only validator contract can invoke this method.\n * - Should be called only at the end of period.\n * - Should be called only when there is slash of bridge operator.\n *\n * Emits the event `Slashed`.\n */\n function execSlashBridgeOperator(address _consensusAddr, uint256 _tier, uint256 _period) external;\n\n /**\n * @dev Returns the configs related to bridge operator slashing.\n *\n * @return _missingVotesRatioTier1 The bridge reward will be deprecated if (s)he missed more than this ratio.\n * @return _missingVotesRatioTier2 The bridge reward and mining reward will be deprecated and the corresponding\n * block producer will be put in jail if (s)he misses more than this ratio.\n * @return _jailDurationForMissingVotesRatioTier2 The number of blocks to jail the corresponding block producer when\n * its bridge operator is slashed tier-2.\n * @return _skipBridgeOperatorSlashingThreshold The threshold to skip slashing the bridge operator in case the total\n * number of votes in the bridge is too small.\n *\n */\n function getBridgeOperatorSlashingConfigs()\n external\n view\n returns (\n uint256 _missingVotesRatioTier1,\n uint256 _missingVotesRatioTier2,\n uint256 _jailDurationForMissingVotesRatioTier2,\n uint256 _skipBridgeOperatorSlashingThreshold\n );\n\n /**\n * @dev Sets the configs to slash bridge operators.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `BridgeOperatorSlashingConfigsUpdated`.\n *\n * @param _ratioTier1 The bridge reward will be deprecated if (s)he missed more than this ratio. Values 0-10,000 map\n * to 0%-100%.\n * @param _ratioTier2 The bridge reward and mining reward will be deprecated and the corresponding block producer will\n * be put in jail if (s)he misses more than this ratio. Values 0-10,000 map to 0%-100%.\n * @param _jailDurationTier2 The number of blocks to jail the corresponding block producer when its bridge operator is\n * slashed tier-2.\n * @param _skipSlashingThreshold The threshold to skip slashing the bridge operator in case the total number of votes\n * in the bridge is too small.\n *\n */\n function setBridgeOperatorSlashingConfigs(\n uint256 _ratioTier1,\n uint256 _ratioTier2,\n uint256 _jailDurationTier2,\n uint256 _skipSlashingThreshold\n ) external;\n}\n" + }, + "contracts/interfaces/slash-indicator/ISlashBridgeVoting.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IBaseSlash.sol\";\n\ninterface ISlashBridgeVoting is IBaseSlash {\n /**\n * @dev Error thrown when an invalid slash is encountered.\n */\n error ErrInvalidSlash();\n\n /**\n * @dev Emitted when the configs to slash bridge voting is updated. See the method `getBridgeVotingSlashingConfigs` for param\n * details.\n */\n event BridgeVotingSlashingConfigsUpdated(uint256 bridgeVotingThreshold, uint256 bridgeVotingSlashAmount);\n\n /**\n * @dev Slashes for bridge voter governance.\n *\n * Emits the event `Slashed`.\n */\n function slashBridgeVoting(address _consensusAddr) external;\n\n /**\n * @dev Returns the configs related to bridge voting slashing.\n *\n * @return _bridgeVotingThreshold The threshold to slash when a trusted organization does not vote for bridge\n * operators.\n * @return _bridgeVotingSlashAmount The amount of RON to slash bridge voting.\n *\n */\n function getBridgeVotingSlashingConfigs()\n external\n view\n returns (uint256 _bridgeVotingThreshold, uint256 _bridgeVotingSlashAmount);\n\n /**\n * @dev Sets the configs to slash bridge voting.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `BridgeVotingSlashingConfigsUpdated`.\n *\n * @param _threshold The threshold to slash when a trusted organization does not vote for bridge operators.\n * @param _slashAmount The amount of RON to slash bridge voting.\n *\n */\n function setBridgeVotingSlashingConfigs(uint256 _threshold, uint256 _slashAmount) external;\n}\n" + }, + "contracts/interfaces/slash-indicator/ISlashDoubleSign.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IBaseSlash.sol\";\n\ninterface ISlashDoubleSign is IBaseSlash {\n /**\n * @dev Emitted when the configs to slash double sign is updated. See the method `getDoubleSignSlashingConfigs`\n * for param details.\n */\n event DoubleSignSlashingConfigsUpdated(\n uint256 slashDoubleSignAmount,\n uint256 doubleSigningJailUntilBlock,\n uint256 doubleSigningOffsetLimitBlock\n );\n\n /**\n * @dev Slashes for double signing.\n *\n * Requirements:\n * - The method caller is coinbase.\n *\n * Emits the event `Slashed` if the double signing evidence of the two headers valid.\n */\n function slashDoubleSign(address _validatorAddr, bytes calldata _header1, bytes calldata _header2) external;\n\n /**\n * @dev Returns the configs related to block producer slashing.\n *\n * @return _slashDoubleSignAmount The amount of RON to slash double sign.\n * @return _doubleSigningJailUntilBlock The block number that the punished validator will be jailed until, due to\n * double signing.\n * @param _doubleSigningOffsetLimitBlock The number of block that the current block is at most far from the double\n * signing block.\n *\n */\n function getDoubleSignSlashingConfigs()\n external\n view\n returns (\n uint256 _slashDoubleSignAmount,\n uint256 _doubleSigningJailUntilBlock,\n uint256 _doubleSigningOffsetLimitBlock\n );\n\n /**\n * @dev Sets the configs to slash block producers.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `DoubleSignSlashingConfigsUpdated`.\n *\n * @param _slashAmount The amount of RON to slash double sign.\n * @param _jailUntilBlock The block number that the punished validator will be jailed until, due to double signing.\n * @param _doubleSigningOffsetLimitBlock The number of block that the current block is at most far from the double\n * signing block.\n *\n */\n function setDoubleSignSlashingConfigs(\n uint256 _slashAmount,\n uint256 _jailUntilBlock,\n uint256 _doubleSigningOffsetLimitBlock\n ) external;\n}\n" + }, + "contracts/interfaces/slash-indicator/ISlashFastFinality.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IBaseSlash.sol\";\n\ninterface ISlashFastFinality is IBaseSlash {\n /**\n * @dev Emitted when the configs to slash fast finality is updated. See the method `getFastFinalitySlashingConfigs`\n * for param details.\n */\n event FastFinalitySlashingConfigsUpdated(uint256 slashFastFinalityAmount, uint256 fastFinalityJailUntilBlock);\n\n /**\n * @dev Slashes for fast finality.\n *\n * Requirements:\n * - Only whitelisted addresses are allowed to call.\n *\n * Emits the event `Slashed` if the fast finality evidence of the two headers valid.\n */\n function slashFastFinality(\n address consensusAddr,\n bytes calldata voterPublicKey,\n uint256 targetBlockNumber,\n bytes32[2] calldata targetBlockHash,\n bytes[][2] calldata listOfPublicKey,\n bytes[2] calldata aggregatedSignature\n ) external;\n\n /**\n * @dev Returns the configs related to block producer slashing.\n *\n * @return slashFastFinalityAmount The amount of RON to slash fast finality.\n * @return fastFinalityJailUntilBlock The block number that the punished validator will be jailed until, due to\n * malicious fast finality.\n */\n function getFastFinalitySlashingConfigs()\n external\n view\n returns (uint256 slashFastFinalityAmount, uint256 fastFinalityJailUntilBlock);\n\n /**\n * @dev Sets the configs to slash block producers.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `FastFinalitySlashingConfigsUpdated`.\n *\n * @param slashAmount The amount of RON to slash fast finality.\n * @param jailUntilBlock The block number that the punished validator will be jailed until, due to fast finality.\n *\n */\n function setFastFinalitySlashingConfigs(uint256 slashAmount, uint256 jailUntilBlock) external;\n}\n" + }, + "contracts/interfaces/slash-indicator/ISlashIndicator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./ISlashDoubleSign.sol\";\nimport \"./ISlashBridgeVoting.sol\";\nimport \"./ISlashBridgeOperator.sol\";\nimport \"./ISlashUnavailability.sol\";\nimport \"./ICreditScore.sol\";\n\ninterface ISlashIndicator is\n ISlashDoubleSign,\n ISlashBridgeVoting,\n ISlashBridgeOperator,\n ISlashUnavailability,\n ICreditScore\n{}\n" + }, + "contracts/interfaces/slash-indicator/ISlashUnavailability.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IBaseSlash.sol\";\n\ninterface ISlashUnavailability is IBaseSlash {\n /**\n * @dev Error thrown when attempting to slash a validator twice or slash more than one validator in one block.\n */\n error ErrCannotSlashAValidatorTwiceOrSlashMoreThanOneValidatorInOneBlock();\n\n /**\n * @dev Emitted when the configs to slash bridge operator is updated. See the method `getUnavailabilitySlashingConfigs`\n * for param details.\n */\n event UnavailabilitySlashingConfigsUpdated(\n uint256 unavailabilityTier1Threshold,\n uint256 unavailabilityTier2Threshold,\n uint256 slashAmountForUnavailabilityTier2Threshold,\n uint256 jailDurationForUnavailabilityTier2Threshold\n );\n\n /**\n * @dev Returns the last block that a block producer is slashed for unavailability.\n */\n function lastUnavailabilitySlashedBlock() external view returns (uint256);\n\n /**\n * @dev Slashes for unavailability by increasing the counter of block producer `_consensusAddr`.\n *\n * Requirements:\n * - The method caller is coinbase.\n *\n * Emits the event `Slashed` when the threshold is reached.\n *\n */\n function slashUnavailability(address _consensusAddr) external;\n\n /**\n * @dev Returns the current unavailability indicator of a block producer.\n */\n function currentUnavailabilityIndicator(address _validator) external view returns (uint256);\n\n /**\n * @dev Returns the unavailability indicator in the period `_period` of a block producer.\n */\n function getUnavailabilityIndicator(address _validator, uint256 _period) external view returns (uint256);\n\n /**\n * @dev Returns the configs related to block producer slashing.\n *\n * @return _unavailabilityTier1Threshold The mining reward will be deprecated, if (s)he missed more than this\n * threshold. This threshold is applied for tier-1 and tier-3 slash.\n * @return _unavailabilityTier2Threshold The mining reward will be deprecated, (s)he will be put in jailed, and will\n * be deducted self-staking if (s)he misses more than this threshold. This threshold is applied for tier-2 slash.\n * @return _slashAmountForUnavailabilityTier2Threshold The amount of RON to deduct from self-staking of a block\n * producer when (s)he is slashed with tier-2 or tier-3.\n * @return _jailDurationForUnavailabilityTier2Threshold The number of blocks to jail a block producer when (s)he is\n * slashed with tier-2 or tier-3.\n *\n */\n function getUnavailabilitySlashingConfigs()\n external\n view\n returns (\n uint256 _unavailabilityTier1Threshold,\n uint256 _unavailabilityTier2Threshold,\n uint256 _slashAmountForUnavailabilityTier2Threshold,\n uint256 _jailDurationForUnavailabilityTier2Threshold\n );\n\n /**\n * @dev Sets the configs to slash block producers.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `BridgeOperatorSlashingConfigsUpdated`.\n *\n * @param _tier1Threshold The mining reward will be deprecated, if (s)he missed more than this threshold.\n * @param _tier2Threshold The mining reward will be deprecated, (s)he will be put in jailed, and will be deducted\n * self-staking if (s)he misses more than this threshold.\n * @param _slashAmountForTier2Threshold The amount of RON to deduct from self-staking of a block producer when (s)he\n * is slashed tier-2.\n * @param _jailDurationForTier2Threshold The number of blocks to jail a block producer when (s)he is slashed tier-2.\n *\n */\n function setUnavailabilitySlashingConfigs(\n uint256 _tier1Threshold,\n uint256 _tier2Threshold,\n uint256 _slashAmountForTier2Threshold,\n uint256 _jailDurationForTier2Threshold\n ) external;\n}\n" + }, + "contracts/interfaces/staking/IBaseStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface IBaseStaking {\n struct PoolDetail {\n // Address of the pool i.e. consensus address of the validator\n address addr;\n // Pool admin address\n address admin;\n // Self-staking amount\n uint256 stakingAmount;\n // Total number of RON staking for the pool\n uint256 stakingTotal;\n // Mapping from delegator => delegating amount\n mapping(address => uint256) delegatingAmount;\n // Mapping from delegator => the last timestamp that delegator staked\n mapping(address => uint256) lastDelegatingTimestamp;\n }\n\n /// @dev Emitted when the minium number of seconds to undelegate is updated.\n event CooldownSecsToUndelegateUpdated(uint256 minSecs);\n /// @dev Emitted when the number of seconds that a candidate must wait to be revoked.\n event WaitingSecsToRevokeUpdated(uint256 secs);\n\n /// @dev Error of cannot transfer RON.\n error ErrCannotTransferRON();\n /// @dev Error of receiving zero message value.\n error ErrZeroValue();\n /// @dev Error of pool admin is not allowed to call.\n error ErrPoolAdminForbidden();\n /// @dev Error of no one is allowed to call but the pool's admin.\n error ErrOnlyPoolAdminAllowed();\n /// @dev Error of admin of any active pool cannot delegate.\n error ErrAdminOfAnyActivePoolForbidden(address admin);\n /// @dev Error of querying inactive pool.\n error ErrInactivePool(address poolAddr);\n /// @dev Error of length of input arrays are not of the same.\n error ErrInvalidArrays();\n\n /**\n * @dev Returns whether the `_poolAdminAddr` is currently active.\n */\n function isAdminOfActivePool(address _poolAdminAddr) external view returns (bool);\n\n /**\n * @dev Returns the consensus address corresponding to the pool admin.\n */\n function getPoolAddressOf(address _poolAdminAddr) external view returns (address);\n\n /**\n * @dev Returns the staking pool detail.\n */\n function getPoolDetail(address) external view returns (address _admin, uint256 _stakingAmount, uint256 _stakingTotal);\n\n /**\n * @dev Returns the self-staking amounts of the pools.\n */\n function getManySelfStakings(address[] calldata) external view returns (uint256[] memory);\n\n /**\n * @dev Returns The cooldown time in seconds to undelegate from the last timestamp (s)he delegated.\n */\n function cooldownSecsToUndelegate() external view returns (uint256);\n\n /**\n * @dev Returns the number of seconds that a candidate must wait for the renounce request gets affected.\n */\n function waitingSecsToRevoke() external view returns (uint256);\n\n /**\n * @dev Sets the cooldown time in seconds to undelegate from the last timestamp (s)he delegated.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `CooldownSecsToUndelegateUpdated`.\n *\n */\n function setCooldownSecsToUndelegate(uint256 _cooldownSecs) external;\n\n /**\n * @dev Sets the number of seconds that a candidate must wait to be revoked.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `WaitingSecsToRevokeUpdated`.\n *\n */\n function setWaitingSecsToRevoke(uint256 _secs) external;\n}\n" + }, + "contracts/interfaces/staking/ICandidateStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IRewardPool.sol\";\n\ninterface ICandidateStaking is IRewardPool {\n /// @dev Emitted when the minimum staking amount for being a validator is updated.\n event MinValidatorStakingAmountUpdated(uint256 threshold);\n /// @dev Emitted when the commission rate range is updated.\n event CommissionRateRangeUpdated(uint256 minRate, uint256 maxRate);\n\n /// @dev Emitted when the pool admin staked for themself.\n event Staked(address indexed consensuAddr, uint256 amount);\n /// @dev Emitted when the pool admin unstaked the amount of RON from themself.\n event Unstaked(address indexed consensuAddr, uint256 amount);\n\n /// @dev Emitted when the validator pool is approved.\n event PoolApproved(address indexed validator, address indexed admin);\n /// @dev Emitted when the validator pool is deprecated.\n event PoolsDeprecated(address[] validator);\n /// @dev Emitted when the staking amount transfer failed.\n event StakingAmountTransferFailed(\n address indexed validator,\n address indexed admin,\n uint256 amount,\n uint256 contractBalance\n );\n /// @dev Emitted when the staking amount deducted failed, e.g. when the validator gets slashed.\n event StakingAmountDeductFailed(\n address indexed validator,\n address indexed recipient,\n uint256 amount,\n uint256 contractBalance\n );\n\n /// @dev Error of cannot transfer RON to specified target.\n error ErrCannotInitTransferRON(address addr, string extraInfo);\n /// @dev Error of three interaction addresses must be of the same in applying for validator candidate.\n error ErrThreeInteractionAddrsNotEqual();\n /// @dev Error of unstaking zero amount.\n error ErrUnstakeZeroAmount();\n /// @dev Error of invalid staking amount left after deducted.\n error ErrStakingAmountLeft();\n /// @dev Error of insufficient staking amount for unstaking.\n error ErrInsufficientStakingAmount();\n /// @dev Error of unstaking too early.\n error ErrUnstakeTooEarly();\n /// @dev Error of setting commission rate exceeds max allowed.\n error ErrInvalidCommissionRate();\n\n /**\n * @dev Returns the minimum threshold for being a validator candidate.\n */\n function minValidatorStakingAmount() external view returns (uint256);\n\n /**\n * @dev Returns the commission rate range that the candidate can set.\n */\n function getCommissionRateRange() external view returns (uint256 _minRange, uint256 _maxRange);\n\n /**\n * @dev Sets the minimum threshold for being a validator candidate.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the `MinValidatorStakingAmountUpdated` event.\n *\n */\n function setMinValidatorStakingAmount(uint256) external;\n\n /**\n * @dev Sets the commission rate range that a candidate can set.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the `CommissionRateRangeUpdated` event.\n *\n */\n function setCommissionRateRange(uint256 _minRate, uint256 _maxRate) external;\n\n /**\n * @dev Proposes a candidate to become a validator.\n *\n * Requirements:\n * - The method caller is able to receive RON.\n * - The treasury is able to receive RON.\n * - The amount is larger than or equal to the minimum validator staking amount `minValidatorStakingAmount()`.\n *\n * Emits the event `PoolApproved`.\n *\n * @param _candidateAdmin the candidate admin will be stored in the validator contract, used for calling function that affects\n * to its candidate, e.g. scheduling maintenance.\n *\n */\n function applyValidatorCandidate(\n address _candidateAdmin,\n address _consensusAddr,\n address payable _treasuryAddr,\n uint256 _commissionRate\n ) external payable;\n\n /**\n * @dev Deprecates the pool.\n * - Deduct self-staking amount of the pool admin to zero.\n * - Transfer the deducted amount to the pool admin.\n * - Deactivate the pool admin address in the mapping of active pool admins\n *\n * Requirements:\n * - The method caller is validator contract.\n *\n * Emits the event `PoolsDeprecated` and `Unstaked` events.\n * Emits the event `StakingAmountTransferFailed` if the contract cannot transfer RON back to the pool admin.\n *\n */\n function execDeprecatePools(address[] calldata _pools, uint256 _period) external;\n\n /**\n * @dev Self-delegates to the validator candidate `_consensusAddr`.\n *\n * Requirements:\n * - The consensus address is a validator candidate.\n * - The method caller is the pool admin.\n * - The `msg.value` is larger than 0.\n *\n * Emits the event `Staked`.\n *\n */\n function stake(address _consensusAddr) external payable;\n\n /**\n * @dev Unstakes from the validator candidate `_consensusAddr` for `_amount`.\n *\n * Requirements:\n * - The consensus address is a validator candidate.\n * - The method caller is the pool admin.\n *\n * Emits the event `Unstaked`.\n *\n */\n function unstake(address _consensusAddr, uint256 _amount) external;\n\n /**\n * @dev Pool admin requests update validator commission rate. The request will be forwarded to the candidate manager\n * contract, and the value is getting updated in {ICandidateManager-execRequestUpdateCommissionRate}.\n *\n * Requirements:\n * - The consensus address is a validator candidate.\n * - The method caller is the pool admin.\n * - The `_effectiveDaysOnwards` must be equal to or larger than the {CandidateManager-_minEffectiveDaysOnwards}.\n * - The `_rate` must be in range of [0_00; 100_00].\n *\n * Emits the event `CommissionRateUpdated`.\n *\n */\n function requestUpdateCommissionRate(\n address _consensusAddr,\n uint256 _effectiveDaysOnwards,\n uint256 _commissionRate\n ) external;\n\n /**\n * @dev Renounces being a validator candidate and takes back the delegating/staking amount.\n *\n * Requirements:\n * - The consensus address is a validator candidate.\n * - The method caller is the pool admin.\n *\n */\n function requestRenounce(address _consensusAddr) external;\n\n /**\n * @dev Renounces being a validator candidate and takes back the delegating/staking amount.\n *\n * Requirements:\n * - The consensus address is a validator candidate.\n * - The method caller is the pool admin.\n *\n */\n function requestEmergencyExit(address _consensusAddr) external;\n}\n" + }, + "contracts/interfaces/staking/IDelegatorStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IRewardPool.sol\";\n\ninterface IDelegatorStaking is IRewardPool {\n /// @dev Emitted when the delegator staked for a validator candidate.\n event Delegated(address indexed delegator, address indexed consensuAddr, uint256 amount);\n /// @dev Emitted when the delegator unstaked from a validator candidate.\n event Undelegated(address indexed delegator, address indexed consensuAddr, uint256 amount);\n\n /// @dev Error of undelegating zero amount.\n error ErrUndelegateZeroAmount();\n /// @dev Error of undelegating insufficient amount.\n error ErrInsufficientDelegatingAmount();\n /// @dev Error of undelegating too early.\n error ErrUndelegateTooEarly();\n\n /**\n * @dev Stakes for a validator candidate `_consensusAddr`.\n *\n * Requirements:\n * - The consensus address is a validator candidate.\n * - The method caller is not the pool admin.\n *\n * Emits the `Delegated` event.\n *\n */\n function delegate(address _consensusAddr) external payable;\n\n /**\n * @dev Unstakes from a validator candidate `_consensusAddr` for `_amount`.\n *\n * Requirements:\n * - The method caller is not the pool admin.\n *\n * Emits the `Undelegated` event.\n *\n */\n function undelegate(address _consensusAddr, uint256 _amount) external;\n\n /**\n * @dev Bulk unstakes from a list of candidates.\n *\n * Requirements:\n * - The method caller is not the pool admin.\n *\n * Emits the events `Undelegated`.\n *\n */\n function bulkUndelegate(address[] calldata _consensusAddrs, uint256[] calldata _amounts) external;\n\n /**\n * @dev Unstakes an amount of RON from the `_consensusAddrSrc` and stake for `_consensusAddrDst`.\n *\n * Requirements:\n * - The method caller is not the pool admin.\n * - The consensus address `_consensusAddrDst` is a validator candidate.\n *\n * Emits the `Undelegated` event and the `Delegated` event.\n *\n */\n function redelegate(address _consensusAddrSrc, address _consensusAddrDst, uint256 _amount) external;\n\n /**\n * @dev Returns the claimable reward of the user `_user`.\n */\n function getRewards(\n address _user,\n address[] calldata _poolAddrList\n ) external view returns (uint256[] memory _rewards);\n\n /**\n * @dev Claims the reward of method caller.\n *\n * Emits the `RewardClaimed` event.\n *\n */\n function claimRewards(address[] calldata _consensusAddrList) external returns (uint256 _amount);\n\n /**\n * @dev Claims the rewards and delegates them to the consensus address.\n *\n * Requirements:\n * - The method caller is not the pool admin.\n * - The consensus address `_consensusAddrDst` is a validator candidate.\n *\n * Emits the `RewardClaimed` event and the `Delegated` event.\n *\n */\n function delegateRewards(\n address[] calldata _consensusAddrList,\n address _consensusAddrDst\n ) external returns (uint256 _amount);\n}\n" + }, + "contracts/interfaces/staking/IRewardPool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../interfaces/consumers/PeriodWrapperConsumer.sol\";\n\ninterface IRewardPool is PeriodWrapperConsumer {\n struct UserRewardFields {\n // Recorded reward amount.\n uint256 debited;\n // The last accumulated of the amount rewards per share (one unit staking) that the info updated.\n uint256 aRps;\n // Lowest staking amount in the period.\n uint256 lowestAmount;\n // Last period number that the info updated.\n uint256 lastPeriod;\n }\n\n struct PoolFields {\n // Accumulated of the amount rewards per share (one unit staking).\n uint256 aRps;\n // The staking total to share reward of the current period.\n PeriodWrapper shares;\n }\n\n /// @dev Emitted when the fields to calculate pending reward for the user is updated.\n event UserRewardUpdated(address indexed poolAddr, address indexed user, uint256 debited);\n /// @dev Emitted when the user claimed their reward\n event RewardClaimed(address indexed poolAddr, address indexed user, uint256 amount);\n\n /// @dev Emitted when the pool shares are updated\n event PoolSharesUpdated(uint256 indexed period, address indexed poolAddr, uint256 shares);\n /// @dev Emitted when the pools are updated\n event PoolsUpdated(uint256 indexed period, address[] poolAddrs, uint256[] aRps, uint256[] shares);\n /// @dev Emitted when the contract fails when updating the pools\n event PoolsUpdateFailed(uint256 indexed period, address[] poolAddrs, uint256[] rewards);\n /// @dev Emitted when the contract fails when updating the pools that already set\n event PoolsUpdateConflicted(uint256 indexed period, address[] poolAddrs);\n\n /// @dev Error of invalid pool share.\n error ErrInvalidPoolShare();\n\n /**\n * @dev Returns the reward amount that user claimable.\n */\n function getReward(address _poolAddr, address _user) external view returns (uint256);\n\n /**\n * @dev Returns the staking amount of an user.\n */\n function getStakingAmount(address _poolAddr, address _user) external view returns (uint256);\n\n /**\n * @dev Returns the staking amounts of the users.\n */\n function getManyStakingAmounts(\n address[] calldata _poolAddrs,\n address[] calldata _userList\n ) external view returns (uint256[] memory);\n\n /**\n * @dev Returns the total staking amount of all users for a pool.\n */\n function getStakingTotal(address _poolAddr) external view returns (uint256);\n\n /**\n * @dev Returns the total staking amounts of all users for the pools `_poolAddrs`.\n */\n function getManyStakingTotals(address[] calldata _poolAddrs) external view returns (uint256[] memory);\n}\n" + }, + "contracts/interfaces/staking/IStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IBaseStaking.sol\";\nimport \"./ICandidateStaking.sol\";\nimport \"./IDelegatorStaking.sol\";\n\ninterface IStaking is IRewardPool, IBaseStaking, ICandidateStaking, IDelegatorStaking {\n /**\n * @dev Records the amount of rewards `_rewards` for the pools `_consensusAddrs`.\n *\n * Requirements:\n * - The method caller must be validator contract.\n *\n * Emits the event `PoolsUpdated` once the contract recorded the rewards successfully.\n * Emits the event `PoolsUpdateFailed` once the input array lengths are not equal.\n * Emits the event `PoolsUpdateConflicted` when there are some pools which already updated in the period.\n *\n * Note: This method should be called once at the period ending.\n *\n */\n function execRecordRewards(\n address[] calldata _consensusAddrs,\n uint256[] calldata _rewards,\n uint256 _period\n ) external payable;\n\n /**\n * @dev Deducts from staking amount of the validator `_consensusAddr` for `_amount`.\n *\n * Requirements:\n * - The method caller must be validator contract.\n *\n * Emits the event `Unstaked`.\n *\n */\n function execDeductStakingAmount(\n address _consensusAddr,\n uint256 _amount\n ) external returns (uint256 _actualDeductingAmount);\n}\n" + }, + "contracts/interfaces/validator/ICandidateManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface ICandidateManager {\n struct ValidatorCandidate {\n // Admin of the candidate\n address admin;\n // Address of the validator that produces block, e.g. block.coinbase. This is so-called validator address.\n address consensusAddr;\n // Address that receives mining reward of the validator\n address payable treasuryAddr;\n // Address of the bridge operator corresponding to the candidate\n address ______deprecatedbridgeOperatorAddr;\n // The percentage of reward that validators can be received, the rest goes to the delegators.\n // Values in range [0; 100_00] stands for 0-100%\n uint256 commissionRate;\n // The timestamp that scheduled to revoke the candidate (no schedule=0)\n uint256 revokingTimestamp;\n // The deadline that the candidate must top up staking amount to keep it larger than or equal to the threshold (no deadline=0)\n uint256 topupDeadline;\n }\n\n struct CommissionSchedule {\n // The timestamp that the commission schedule gets affected (no schedule=0).\n uint256 effectiveTimestamp;\n // The new commission rate. Value is in range [0; 100_00], stands for 0-100%\n uint256 commissionRate;\n }\n\n /// @dev Emitted when the maximum number of validator candidates is updated.\n event MaxValidatorCandidateUpdated(uint256 threshold);\n /// @dev Emitted when the min offset to the effective date of commission rate change is updated.\n event MinEffectiveDaysOnwardsUpdated(uint256 numOfDays);\n /// @dev Emitted when the validator candidate is granted.\n event CandidateGranted(address indexed consensusAddr, address indexed treasuryAddr, address indexed admin);\n /// @dev Emitted when the revoking timestamp of a candidate is updated.\n event CandidateRevokingTimestampUpdated(address indexed consensusAddr, uint256 revokingTimestamp);\n /// @dev Emitted when the topup deadline of a candidate is updated.\n event CandidateTopupDeadlineUpdated(address indexed consensusAddr, uint256 topupDeadline);\n /// @dev Emitted when the validator candidate is revoked.\n event CandidatesRevoked(address[] consensusAddrs);\n\n /// @dev Emitted when a schedule for updating commission rate is set.\n event CommissionRateUpdateScheduled(address indexed consensusAddr, uint256 effectiveTimestamp, uint256 rate);\n /// @dev Emitted when the commission rate of a validator is updated.\n event CommissionRateUpdated(address indexed consensusAddr, uint256 rate);\n\n /// @dev Error of exceeding maximum number of candidates.\n error ErrExceedsMaxNumberOfCandidate();\n /// @dev Error of querying for already existent candidate.\n error ErrExistentCandidate();\n /// @dev Error of querying for non-existent candidate.\n error ErrNonExistentCandidate();\n /// @dev Error of candidate admin already exists.\n error ErrExistentCandidateAdmin(address _candidateAdminAddr);\n /// @dev Error of treasury already exists.\n error ErrExistentTreasury(address _treasuryAddr);\n /// @dev Error of invalid commission rate.\n error ErrInvalidCommissionRate();\n /// @dev Error of invalid effective days onwards.\n error ErrInvalidEffectiveDaysOnwards();\n /// @dev Error of invalid min effective days onwards.\n error ErrInvalidMinEffectiveDaysOnwards();\n /// @dev Error of already requested revoking candidate before.\n error ErrAlreadyRequestedRevokingCandidate();\n /// @dev Error of commission change schedule exists.\n error ErrAlreadyRequestedUpdatingCommissionRate();\n /// @dev Error of trusted org cannot renounce.\n error ErrTrustedOrgCannotRenounce();\n\n /**\n * @dev Returns the maximum number of validator candidate.\n */\n function maxValidatorCandidate() external view returns (uint256);\n\n /**\n * @dev Returns the minimum number of days to the effective date of commission rate change.\n */\n function minEffectiveDaysOnward() external view returns (uint256);\n\n /**\n * @dev Sets the maximum number of validator candidate.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the `MaxValidatorCandidateUpdated` event.\n *\n */\n function setMaxValidatorCandidate(uint256) external;\n\n /**\n * @dev Sets the minimum number of days to the effective date of commision rate change.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the `MinEffectiveDaysOnwardsUpdated` event.\n *\n */\n function setMinEffectiveDaysOnwards(uint256 _numOfDays) external;\n\n /**\n * @dev Grants a validator candidate.\n *\n * Requirements:\n * - The method caller is staking contract.\n *\n * Emits the event `CandidateGranted`.\n *\n */\n function execApplyValidatorCandidate(\n address _admin,\n address _consensusAddr,\n address payable _treasuryAddr,\n uint256 _commissionRate\n ) external;\n\n /**\n * @dev Requests to revoke a validator candidate in next `_secsLeft` seconds.\n *\n * Requirements:\n * - The method caller is staking contract.\n *\n * Emits the event `CandidateRevokingTimestampUpdated`.\n *\n */\n function execRequestRenounceCandidate(address, uint256 _secsLeft) external;\n\n /**\n * @dev Fallback function of `CandidateStaking-requestUpdateCommissionRate`.\n *\n * Requirements:\n * - The method caller is the staking contract.\n * - The `_effectiveTimestamp` must be the beginning of a UTC day, and at least from 7 days onwards\n * - The `_rate` must be in range of [0_00; 100_00].\n *\n * Emits the event `CommissionRateUpdateScheduled`.\n *\n */\n function execRequestUpdateCommissionRate(address _consensusAddr, uint256 _effectiveTimestamp, uint256 _rate) external;\n\n /**\n * @dev Returns whether the address is a validator (candidate).\n */\n function isValidatorCandidate(address _addr) external view returns (bool);\n\n /**\n * @dev Returns the validator candidate.\n */\n function getValidatorCandidates() external view returns (address[] memory);\n\n /**\n * @dev Returns all candidate info.\n */\n function getCandidateInfos() external view returns (ValidatorCandidate[] memory);\n\n /**\n * @dev Returns the info of a candidate.\n */\n function getCandidateInfo(address _candidate) external view returns (ValidatorCandidate memory);\n\n /**\n * @dev Returns whether the address is the candidate admin.\n */\n function isCandidateAdmin(address _candidate, address _admin) external view returns (bool);\n\n /**\n * @dev Returns the schedule of changing commission rate of a candidate address.\n */\n function getCommissionChangeSchedule(address _candidate) external view returns (CommissionSchedule memory);\n}\n" + }, + "contracts/interfaces/validator/ICoinbaseExecution.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./ISlashingExecution.sol\";\n\ninterface ICoinbaseExecution is ISlashingExecution {\n enum BlockRewardDeprecatedType {\n UNKNOWN,\n UNAVAILABILITY,\n AFTER_BAILOUT\n }\n\n /// @dev Emitted when the validator set is updated\n event ValidatorSetUpdated(uint256 indexed period, address[] consensusAddrs);\n /// @dev Emitted when the bridge operator set is updated, to mirror the in-jail and maintaining status of the validator.\n event BlockProducerSetUpdated(uint256 indexed period, uint256 indexed epoch, address[] consensusAddrs);\n /// @dev Emitted when the bridge operator set is updated.\n event BridgeOperatorSetUpdated(uint256 indexed period, uint256 indexed epoch, address[] bridgeOperators);\n\n /// @dev Emitted when the reward of the block producer is deprecated.\n event BlockRewardDeprecated(\n address indexed coinbaseAddr,\n uint256 rewardAmount,\n BlockRewardDeprecatedType deprecatedType\n );\n /// @dev Emitted when the block reward is submitted.\n event BlockRewardSubmitted(address indexed coinbaseAddr, uint256 submittedAmount, uint256 bonusAmount);\n\n /// @dev Emitted when the block producer reward is distributed.\n event MiningRewardDistributed(address indexed consensusAddr, address indexed recipient, uint256 amount);\n /// @dev Emitted when the contract fails when distributing the block producer reward.\n event MiningRewardDistributionFailed(\n address indexed consensusAddr,\n address indexed recipient,\n uint256 amount,\n uint256 contractBalance\n );\n\n /// @dev Emitted when the bridge operator reward is distributed.\n event BridgeOperatorRewardDistributed(\n address indexed consensusAddr,\n address indexed bridgeOperator,\n address indexed recipientAddr,\n uint256 amount\n );\n /// @dev Emitted when the contract fails when distributing the bridge operator reward.\n event BridgeOperatorRewardDistributionFailed(\n address indexed consensusAddr,\n address indexed bridgeOperator,\n address indexed recipient,\n uint256 amount,\n uint256 contractBalance\n );\n\n /// @dev Emitted when the fast finality reward is distributed.\n event FastFinalityRewardDistributed(address indexed consensusAddr, address indexed recipient, uint256 amount);\n /// @dev Emitted when the contract fails when distributing the fast finality reward.\n event FastFinalityRewardDistributionFailed(\n address indexed consensusAddr,\n address indexed recipient,\n uint256 amount,\n uint256 contractBalance\n );\n\n /// @dev Emitted when the amount of RON reward is distributed to staking contract.\n event StakingRewardDistributed(uint256 totalAmount, address[] consensusAddrs, uint256[] amounts);\n /// @dev Emitted when the contracts fails when distributing the amount of RON to the staking contract.\n event StakingRewardDistributionFailed(\n uint256 totalAmount,\n address[] consensusAddrs,\n uint256[] amounts,\n uint256 contractBalance\n );\n\n /// @dev Emitted when the epoch is wrapped up.\n event WrappedUpEpoch(uint256 indexed periodNumber, uint256 indexed epochNumber, bool periodEnding);\n\n /// @dev Error of only allowed at the end of epoch\n error ErrAtEndOfEpochOnly();\n /// @dev Error of query for already wrapped up epoch\n error ErrAlreadyWrappedEpoch();\n\n /**\n * @dev Submits reward of the current block.\n *\n * Requirements:\n * - The method caller is coinbase.\n *\n * Emits the event `MiningRewardDeprecated` if the coinbase is slashed or no longer be a block producer.\n * Emits the event `BlockRewardSubmitted` for the valid call.\n *\n */\n function submitBlockReward() external payable;\n\n /**\n * @dev Wraps up the current epoch.\n *\n * Requirements:\n * - The method must be called when the current epoch is ending.\n * - The epoch is not wrapped yet.\n * - The method caller is coinbase.\n *\n * Emits the event `MiningRewardDistributed` when some validator has reward distributed.\n * Emits the event `StakingRewardDistributed` when some staking pool has reward distributed.\n * Emits the event `BlockProducerSetUpdated` when the epoch is wrapped up.\n * Emits the event `BridgeOperatorSetUpdated` when the epoch is wrapped up at period ending.\n * Emits the event `ValidatorSetUpdated` when the epoch is wrapped up at period ending, and the validator set gets updated.\n * Emits the event `WrappedUpEpoch`.\n *\n */\n function wrapUpEpoch() external payable;\n}\n" + }, + "contracts/interfaces/validator/IEmergencyExit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface IEmergencyExit {\n /// @dev Emitted when the fund is locked from an emergency exit request\n event EmergencyExitRequested(address indexed consensusAddr, uint256 lockedAmount);\n /// @dev Emitted when the fund that locked from an emergency exit request is transferred to the recipient.\n event EmergencyExitLockedFundReleased(\n address indexed consensusAddr,\n address indexed recipient,\n uint256 unlockedAmount\n );\n /// @dev Emitted when the fund that locked from an emergency exit request is failed to transferred back.\n event EmergencyExitLockedFundReleasingFailed(\n address indexed consensusAddr,\n address indexed recipient,\n uint256 unlockedAmount,\n uint256 contractBalance\n );\n\n /// @dev Emitted when the emergency exit locked amount is updated.\n event EmergencyExitLockedAmountUpdated(uint256 amount);\n /// @dev Emitted when the emergency expiry duration is updated.\n event EmergencyExpiryDurationUpdated(uint256 amount);\n\n /// @dev Error of already requested emergency exit before.\n error ErrAlreadyRequestedEmergencyExit();\n\n /**\n * @dev Returns the amount of RON to lock from a consensus address.\n */\n function emergencyExitLockedAmount() external returns (uint256);\n\n /**\n * @dev Returns the duration that an emergency request is expired and the fund will be recycled.\n */\n function emergencyExpiryDuration() external returns (uint256);\n\n /**\n * @dev Sets the amount of RON to lock from a consensus address.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `EmergencyExitLockedAmountUpdated`.\n *\n */\n function setEmergencyExitLockedAmount(uint256 _emergencyExitLockedAmount) external;\n\n /**\n * @dev Sets the duration that an emergency request is expired and the fund will be recycled.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `EmergencyExpiryDurationUpdated`.\n *\n */\n function setEmergencyExpiryDuration(uint256 _emergencyExpiryDuration) external;\n\n /**\n * @dev Unlocks fund for emergency exit request.\n *\n * Requirements:\n * - The method caller is admin.\n *\n * Emits the event `EmergencyExitLockedFundReleased` if the fund is successfully unlocked.\n * Emits the event `EmergencyExitLockedFundReleasingFailed` if the fund is failed to unlock.\n *\n */\n function execReleaseLockedFundForEmergencyExitRequest(address _consensusAddr, address payable _recipient) external;\n\n /**\n * @dev Fallback function of `IStaking-requestEmergencyExit`.\n *\n * Requirements:\n * - The method caller is staking contract.\n *\n */\n function execEmergencyExit(address _consensusAddr, uint256 _secLeftToRevoke) external;\n}\n" + }, + "contracts/interfaces/validator/info-fragments/ICommonInfo.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./IJailingInfo.sol\";\nimport \"./ITimingInfo.sol\";\nimport \"./IValidatorInfoV2.sol\";\n\ninterface ICommonInfo is ITimingInfo, IJailingInfo, IValidatorInfoV2 {\n struct EmergencyExitInfo {\n uint256 lockedAmount;\n // The timestamp that this locked amount will be recycled to staking vesting contract\n uint256 recyclingAt;\n }\n\n /// @dev Emitted when the deprecated reward is withdrawn.\n event DeprecatedRewardRecycled(address indexed recipientAddr, uint256 amount);\n /// @dev Emitted when the deprecated reward withdrawal is failed\n event DeprecatedRewardRecycleFailed(address indexed recipientAddr, uint256 amount, uint256 balance);\n\n /// @dev Error thrown when receives RON from neither staking vesting contract nor staking contract\n error ErrUnauthorizedReceiveRON();\n /// @dev Error thrown when queries for a non existent info.\n error NonExistentRecyclingInfo();\n\n /**\n * @dev Returns the total deprecated reward, which includes reward that is not sent for slashed validators and unsastified bridge operators\n */\n function totalDeprecatedReward() external view returns (uint256);\n\n /**\n * @dev Returns the emergency exit request.\n */\n function getEmergencyExitInfo(address _consensusAddr) external view returns (EmergencyExitInfo memory);\n}\n" + }, + "contracts/interfaces/validator/info-fragments/IJailingInfo.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface IJailingInfo {\n /**\n * @dev Returns whether the validator are put in jail (cannot join the set of validators) during the current period.\n */\n function checkJailed(address) external view returns (bool);\n\n /**\n * @dev Returns whether the validator are put in jail and the number of block and epoch that he still is in the jail.\n */\n function getJailedTimeLeft(\n address _addr\n ) external view returns (bool isJailed_, uint256 blockLeft_, uint256 epochLeft_);\n\n /**\n * @dev Returns whether the validator are put in jail (cannot join the set of validators) at a specific block.\n */\n function checkJailedAtBlock(address _addr, uint256 _blockNum) external view returns (bool);\n\n /**\n * @dev Returns whether the validator are put in jail at a specific block and the number of block and epoch that he still is in the jail.\n */\n function getJailedTimeLeftAtBlock(\n address _addr,\n uint256 _blockNum\n ) external view returns (bool isJailed_, uint256 blockLeft_, uint256 epochLeft_);\n\n /**\n * @dev Returns whether the validators are put in jail (cannot join the set of validators) during the current period.\n */\n function checkManyJailed(address[] calldata) external view returns (bool[] memory);\n\n /**\n * @dev Returns whether the incoming reward of the block producer is deprecated during the current period.\n */\n function checkMiningRewardDeprecated(address _blockProducer) external view returns (bool);\n\n /**\n * @dev Returns whether the incoming reward of the block producer is deprecated during a specific period.\n */\n function checkMiningRewardDeprecatedAtPeriod(address _blockProducer, uint256 _period) external view returns (bool);\n}\n" + }, + "contracts/interfaces/validator/info-fragments/ITimingInfo.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface ITimingInfo {\n /**\n * @dev Returns the block that validator set was updated.\n */\n function getLastUpdatedBlock() external view returns (uint256);\n\n /**\n * @dev Returns the number of blocks in a epoch.\n */\n function numberOfBlocksInEpoch() external view returns (uint256 _numberOfBlocks);\n\n /**\n * @dev Returns the epoch index from the block number.\n */\n function epochOf(uint256 _block) external view returns (uint256);\n\n /**\n * @dev Returns whether the epoch ending is at the block number `_block`.\n */\n function epochEndingAt(uint256 _block) external view returns (bool);\n\n /**\n * @dev Tries to get the period index from the epoch number.\n */\n function tryGetPeriodOfEpoch(uint256 _epoch) external view returns (bool _filled, uint256 _periodNumber);\n\n /**\n * @dev Returns whether the period ending at the current block number.\n */\n function isPeriodEnding() external view returns (bool);\n\n /**\n * @dev Returns the period index from the current block.\n */\n function currentPeriod() external view returns (uint256);\n\n /**\n * @dev Returns the block number that the current period starts at.\n */\n function currentPeriodStartAtBlock() external view returns (uint256);\n}\n" + }, + "contracts/interfaces/validator/info-fragments/IValidatorInfo.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../../libraries/EnumFlags.sol\";\n\ninterface IValidatorInfo {\n /**\n * @dev Error thrown when an invalid maximum prioritized validator number is provided.\n */\n error ErrInvalidMaxPrioritizedValidatorNumber();\n\n /// @dev Emitted when the number of max validator is updated.\n event MaxValidatorNumberUpdated(uint256);\n /// @dev Emitted when the number of reserved slots for prioritized validators is updated.\n event MaxPrioritizedValidatorNumberUpdated(uint256);\n\n /**\n * @dev Returns the maximum number of validators in the epoch.\n */\n function maxValidatorNumber() external view returns (uint256 _maximumValidatorNumber);\n\n /**\n * @dev Returns the number of reserved slots for prioritized validators.\n */\n function maxPrioritizedValidatorNumber() external view returns (uint256 _maximumPrioritizedValidatorNumber);\n\n /**\n * @dev Returns the current validator list.\n */\n function getValidators()\n external\n view\n returns (\n address[] memory _validatorList,\n address[] memory _bridgeOperators,\n EnumFlags.ValidatorFlag[] memory _flags\n );\n\n /**\n * @dev Returns whether the address is either a bridge operator or a block producer.\n */\n function isValidator(address _addr) external view returns (bool);\n\n /**\n * @dev Returns the current block producer list.\n */\n function getBlockProducers() external view returns (address[] memory);\n\n /**\n * @dev Returns whether the address is block producer or not.\n */\n function isBlockProducer(address _addr) external view returns (bool);\n\n /**\n * @dev Returns total numbers of the block producers.\n */\n function totalBlockProducer() external view returns (uint256);\n\n /**\n * @dev Returns the current on-working bridge operator list.\n * @param bridgeOperatorList The list of working bridge operators.\n * @param validatorList The list of corresponding validators.\n */\n function getBridgeOperators()\n external\n view\n returns (address[] memory bridgeOperatorList, address[] memory validatorList);\n\n /**\n * @dev Returns the bridge operator list corresponding to validator address list.\n */\n function getBridgeOperatorsOf(\n address[] memory _validatorAddrs\n ) external view returns (address[] memory bridgeOperatorList);\n\n /**\n * @dev Returns whether the address is bridge operator.\n */\n function isBridgeOperator(address _addr) external view returns (bool isOperator);\n\n /**\n * @dev Returns whether the consensus address is operating the bridge or not.\n */\n function isOperatingBridge(address _consensusAddr) external view returns (bool);\n\n /**\n * @dev Returns total numbers of the bridge operators.\n */\n function totalBridgeOperator() external view returns (uint256);\n\n /**\n * @dev Updates the max validator number\n *\n * Requirements:\n * - The method caller is admin\n *\n * Emits the event `MaxValidatorNumberUpdated`\n *\n */\n function setMaxValidatorNumber(uint256 _maxValidatorNumber) external;\n\n /**\n * @dev Updates the number of reserved slots for prioritized validators\n *\n * Requirements:\n * - The method caller is admin\n *\n * Emits the event `MaxPrioritizedValidatorNumberUpdated`\n *\n */\n function setMaxPrioritizedValidatorNumber(uint256 _maxPrioritizedValidatorNumber) external;\n}\n" + }, + "contracts/interfaces/validator/info-fragments/IValidatorInfoV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../../libraries/EnumFlags.sol\";\n\ninterface IValidatorInfoV2 {\n /**\n * @dev Error thrown when an invalid maximum prioritized validator number is provided.\n */\n error ErrInvalidMaxPrioritizedValidatorNumber();\n\n /// @dev Emitted when the number of max validator is updated.\n event MaxValidatorNumberUpdated(uint256);\n /// @dev Emitted when the number of reserved slots for prioritized validators is updated.\n event MaxPrioritizedValidatorNumberUpdated(uint256);\n\n /**\n * @dev Returns the maximum number of validators in the epoch.\n */\n function maxValidatorNumber() external view returns (uint256 _maximumValidatorNumber);\n\n /**\n * @dev Returns the number of reserved slots for prioritized validators.\n */\n function maxPrioritizedValidatorNumber() external view returns (uint256 _maximumPrioritizedValidatorNumber);\n\n /**\n * @dev Returns the current validator list.\n */\n function getValidators() external view returns (address[] memory _validatorList);\n\n /**\n * @dev Returns the current block producer list.\n */\n function getBlockProducers() external view returns (address[] memory);\n\n /**\n * @dev Returns whether the address is block producer or not.\n */\n function isBlockProducer(address _addr) external view returns (bool);\n\n /**\n * @dev Returns total numbers of the block producers.\n */\n function totalBlockProducer() external view returns (uint256);\n\n /**\n * @dev Updates the max validator number\n *\n * Requirements:\n * - The method caller is admin\n *\n * Emits the event `MaxValidatorNumberUpdated`\n *\n */\n function setMaxValidatorNumber(uint256 _maxValidatorNumber) external;\n\n /**\n * @dev Updates the number of reserved slots for prioritized validators\n *\n * Requirements:\n * - The method caller is admin\n *\n * Emits the event `MaxPrioritizedValidatorNumberUpdated`\n *\n */\n function setMaxPrioritizedValidatorNumber(uint256 _maxPrioritizedValidatorNumber) external;\n}\n" + }, + "contracts/interfaces/validator/IRoninValidatorSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./ICandidateManager.sol\";\nimport \"./info-fragments/ICommonInfo.sol\";\nimport \"./ICoinbaseExecution.sol\";\nimport \"./ISlashingExecution.sol\";\nimport \"./IEmergencyExit.sol\";\n\ninterface IRoninValidatorSet is\n ICandidateManager,\n ICommonInfo,\n ISlashingExecution,\n ICoinbaseExecution,\n IEmergencyExit\n{}\n" + }, + "contracts/interfaces/validator/ISlashingExecution.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\ninterface ISlashingExecution {\n /// @dev Emitted when the validator is punished.\n event ValidatorPunished(\n address indexed consensusAddr,\n uint256 indexed period,\n uint256 jailedUntil,\n uint256 deductedStakingAmount,\n bool blockProducerRewardDeprecated,\n bool bridgeOperatorRewardDeprecated\n );\n /// @dev Emitted when the validator get out of jail by bailout.\n event ValidatorUnjailed(address indexed validator, uint256 period);\n\n /// @dev Error of cannot bailout due to high tier slash.\n error ErrCannotBailout(address validator);\n\n /**\n * @dev Finalize the slash request from slash indicator contract.\n *\n * Requirements:\n * - The method caller is slash indicator contract.\n *\n * Emits the event `ValidatorPunished`.\n *\n */\n function execSlash(address validatorAddr, uint256 newJailedUntil, uint256 slashAmount, bool cannotBailout) external;\n\n /**\n * @dev Finalize the bailout request from slash indicator contract.\n *\n * Requirements:\n * - The method caller is slash indicator contract.\n *\n * Emits the event `ValidatorUnjailed`.\n *\n */\n function execBailOut(address _validatorAddr, uint256 _period) external;\n}\n" + }, + "contracts/interfaces/version-control/IConditionalImplementControl.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IConditionalImplementControl {\n /// @dev Error when contract which delegate to this contract is not compatible with ERC1967\n error ErrDelegateFromUnknownOrigin(address addr);\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Executes the selfUpgrade function, upgrading to the new contract implementation.\n */\n function selfUpgrade() external;\n}\n" + }, + "contracts/libraries/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary AddressArrayUtils {\n /**\n * @dev Error thrown when a duplicated element is detected in an array.\n * @param msgSig The function signature that invoke the error.\n */\n error ErrDuplicated(bytes4 msgSig);\n\n /**\n * @dev Returns whether or not there's a duplicate. Runs in O(n^2).\n * @param A Array to search\n * @return Returns true if duplicate, false otherwise\n */\n function hasDuplicate(address[] memory A) internal pure returns (bool) {\n if (A.length == 0) {\n return false;\n }\n unchecked {\n for (uint256 i = 0; i < A.length - 1; i++) {\n for (uint256 j = i + 1; j < A.length; j++) {\n if (A[i] == A[j]) {\n return true;\n }\n }\n }\n }\n return false;\n }\n\n /**\n * @dev Returns whether two arrays of addresses are equal or not.\n */\n function isEqual(address[] memory _this, address[] memory _other) internal pure returns (bool yes_) {\n // Hashing two arrays and compare their hash\n assembly {\n let _thisHash := keccak256(add(_this, 32), mul(mload(_this), 32))\n let _otherHash := keccak256(add(_other, 32), mul(mload(_other), 32))\n yes_ := eq(_thisHash, _otherHash)\n }\n }\n\n /**\n * @dev Return the concatenated array from a and b.\n */\n function extend(address[] memory a, address[] memory b) internal pure returns (address[] memory c) {\n uint256 lengthA = a.length;\n uint256 lengthB = b.length;\n unchecked {\n c = new address[](lengthA + lengthB);\n }\n uint256 i;\n for (; i < lengthA; ) {\n c[i] = a[i];\n unchecked {\n ++i;\n }\n }\n for (uint256 j; j < lengthB; ) {\n c[i] = b[j];\n unchecked {\n ++i;\n ++j;\n }\n }\n }\n}\n" + }, + "contracts/libraries/Ballot.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\n\nlibrary Ballot {\n using ECDSA for bytes32;\n\n enum VoteType {\n For,\n Against\n }\n\n // keccak256(\"Ballot(bytes32 proposalHash,uint8 support)\");\n bytes32 private constant BALLOT_TYPEHASH = 0xd900570327c4c0df8dd6bdd522b7da7e39145dd049d2fd4602276adcd511e3c2;\n\n function hash(bytes32 _proposalHash, VoteType _support) internal pure returns (bytes32 digest) {\n // return keccak256(abi.encode(BALLOT_TYPEHASH, _proposalHash, _support));\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, BALLOT_TYPEHASH)\n mstore(add(ptr, 0x20), _proposalHash)\n mstore(add(ptr, 0x40), _support)\n digest := keccak256(ptr, 0x60)\n }\n }\n}\n" + }, + "contracts/libraries/BridgeOperatorsBallot.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../utils/CommonErrors.sol\";\n\nlibrary BridgeOperatorsBallot {\n /**\n * @dev Error thrown when an invalid order of the bridge operator is detected.\n */\n error ErrInvalidOrderOfBridgeOperator();\n\n struct BridgeOperatorSet {\n uint256 period;\n uint256 epoch;\n address[] operators;\n }\n\n // keccak256(\"BridgeOperatorsBallot(uint256 period,uint256 epoch,address[] operators)\");\n bytes32 public constant BRIDGE_OPERATORS_BALLOT_TYPEHASH =\n 0xd679a49e9e099fa9ed83a5446aaec83e746b03ec6723d6f5efb29d37d7f0b78a;\n\n /**\n * @dev Verifies whether the ballot is valid or not.\n *\n * Requirements:\n * - The ballot is not for an empty operator set.\n * - The operator address list is in order.\n *\n */\n function verifyBallot(BridgeOperatorSet calldata _ballot) internal pure {\n if (_ballot.operators.length == 0) revert ErrEmptyArray();\n\n address _addr = _ballot.operators[0];\n for (uint _i = 1; _i < _ballot.operators.length; ) {\n if (_addr >= _ballot.operators[_i]) revert ErrInvalidOrderOfBridgeOperator();\n _addr = _ballot.operators[_i];\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @dev Returns hash of the ballot.\n */\n function hash(BridgeOperatorSet memory self) internal pure returns (bytes32 digest_) {\n bytes32 operatorsHash;\n address[] memory operators = self.operators;\n\n // return keccak256(abi.encode(BRIDGE_OPERATORS_BALLOT_TYPEHASH, _ballot.period, _ballot.epoch, _operatorsHash));\n assembly {\n operatorsHash := keccak256(add(operators, 32), mul(mload(operators), 32))\n let ptr := mload(0x40)\n mstore(ptr, BRIDGE_OPERATORS_BALLOT_TYPEHASH)\n mstore(add(ptr, 0x20), mload(self)) // _ballot.period\n mstore(add(ptr, 0x40), mload(add(self, 0x20))) // _ballot.epoch\n mstore(add(ptr, 0x60), operatorsHash)\n digest_ := keccak256(ptr, 0x80)\n }\n }\n}\n" + }, + "contracts/libraries/EmergencyExitBallot.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\n\nlibrary EmergencyExitBallot {\n // keccak256(\"EmergencyExitBallot(address consensusAddress,address recipientAfterUnlockedFund,uint256 requestedAt,uint256 expiredAt)\");\n bytes32 private constant EMERGENCY_EXIT_BALLOT_TYPEHASH =\n 0x697acba4deaf1a718d8c2d93e42860488cb7812696f28ca10eed17bac41e7027;\n\n /**\n * @dev Returns hash of the ballot.\n */\n function hash(\n address _consensusAddress,\n address _recipientAfterUnlockedFund,\n uint256 _requestedAt,\n uint256 _expiredAt\n ) internal pure returns (bytes32 digest) {\n /*\n * return\n * keccak256(\n * abi.encode(\n * EMERGENCY_EXIT_BALLOT_TYPEHASH,\n * _consensusAddress,\n * _recipientAfterUnlockedFund,\n * _requestedAt,\n * _expiredAt\n * )\n * );\n */\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, EMERGENCY_EXIT_BALLOT_TYPEHASH)\n mstore(add(ptr, 0x20), _consensusAddress)\n mstore(add(ptr, 0x40), _recipientAfterUnlockedFund)\n mstore(add(ptr, 0x60), _requestedAt)\n mstore(add(ptr, 0x80), _expiredAt)\n digest := keccak256(ptr, 0xa0)\n }\n }\n}\n" + }, + "contracts/libraries/EnumFlags.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This library implements checking flag of an enumerated value.\n * The originated idea is inherited from [Enum.HashFlag(Enum)](https://learn.microsoft.com/en-us/dotnet/api/system.enum.hasflag?view=net-6.0) method of C#.\n */\nlibrary EnumFlags {\n enum ValidatorFlag {\n None, // bit(00)\n BlockProducer, // bit(01)\n DeprecatedBridgeOperator, // bit(10)\n Both // bit(11)\n }\n\n function isNone(ValidatorFlag _value) internal pure returns (bool) {\n return uint8(_value) == 0;\n }\n\n /**\n * @dev Checks if `_value` has `_flag`.\n */\n function hasFlag(ValidatorFlag _value, ValidatorFlag _flag) internal pure returns (bool) {\n return (uint8(_value) & uint8(_flag)) != 0;\n }\n\n /**\n * @dev Calculate new value of `_value` after adding `_flag`.\n */\n function addFlag(ValidatorFlag _value, ValidatorFlag _flag) internal pure returns (ValidatorFlag) {\n return ValidatorFlag(uint8(_value) | uint8(_flag));\n }\n\n /**\n * @dev Calculate new value of `_value` after remove `_flag`.\n */\n function removeFlag(ValidatorFlag _value, ValidatorFlag _flag) internal pure returns (ValidatorFlag) {\n return ValidatorFlag(uint8(_value) & ~uint8(_flag));\n }\n}\n" + }, + "contracts/libraries/ErrorHandler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ErrProxyCallFailed } from \"../utils/CommonErrors.sol\";\n\nlibrary ErrorHandler {\n /// @notice handle low level call revert if call failed,\n /// If extcall return empty bytes, reverts with custom error.\n /// @param status Status of external call\n /// @param callSig function signature of the calldata\n /// @param returnOrRevertData bytes result from external call\n function handleRevert(bool status, bytes4 callSig, bytes memory returnOrRevertData) internal pure {\n // Get the function signature of current context\n bytes4 msgSig = msg.sig;\n assembly {\n if iszero(status) {\n // Load the length of bytes array\n let revertLength := mload(returnOrRevertData)\n // Check if length != 0 => revert following reason from external call\n if iszero(iszero(revertLength)) {\n // Start of revert data bytes. The 0x20 offset is always the same.\n revert(add(returnOrRevertData, 0x20), revertLength)\n }\n\n // Load free memory pointer\n let ptr := mload(0x40)\n // Store 4 bytes the function selector of ErrProxyCallFailed(msg.sig, callSig)\n // Equivalent to revert ErrProxyCallFailed(bytes4,bytes4)\n mstore(ptr, 0x8e3eda2b)\n // Store 4 bytes of msgSig parameter in the next slot\n mstore(add(ptr, 0x20), msgSig)\n // Store 4 bytes of callSig parameter in the next slot\n mstore(add(ptr, 0x40), callSig)\n // Revert 68 bytes of error starting from 0x1c\n revert(add(ptr, 0x1c), 0x44)\n }\n }\n }\n}\n" + }, + "contracts/libraries/GlobalProposal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./Proposal.sol\";\n\nlibrary GlobalProposal {\n /**\n * @dev Error thrown when attempting to interact with an unsupported target.\n */\n error ErrUnsupportedTarget(bytes32 proposalHash, uint256 targetNumber);\n\n enum TargetOption {\n /* 0 */ BridgeManager,\n /* 1 */ GatewayContract,\n /* 2 */ BridgeReward,\n /* 3 */ BridgeSlash\n }\n\n struct GlobalProposalDetail {\n // Nonce to make sure proposals are executed in order\n uint256 nonce;\n uint256 expiryTimestamp;\n TargetOption[] targetOptions;\n uint256[] values;\n bytes[] calldatas;\n uint256[] gasAmounts;\n }\n\n // keccak256(\"GlobalProposalDetail(uint256 nonce,uint256 expiryTimestamp,uint8[] targetOptions,uint256[] values,bytes[] calldatas,uint256[] gasAmounts)\");\n bytes32 public constant TYPE_HASH = 0x1463f426c05aff2c1a7a0957a71c9898bc8b47142540538e79ee25ee91141350;\n\n /**\n * @dev Returns struct hash of the proposal.\n */\n function hash(GlobalProposalDetail memory self) internal pure returns (bytes32 digest_) {\n uint256[] memory values = self.values;\n TargetOption[] memory targets = self.targetOptions;\n bytes32[] memory calldataHashList = new bytes32[](self.calldatas.length);\n uint256[] memory gasAmounts = self.gasAmounts;\n\n for (uint256 i; i < calldataHashList.length; ) {\n calldataHashList[i] = keccak256(self.calldatas[i]);\n\n unchecked {\n ++i;\n }\n }\n\n /*\n * return\n * keccak256(\n * abi.encode(\n * TYPE_HASH,\n * _proposal.nonce,\n * _proposal.expiryTimestamp,\n * _targetsHash,\n * _valuesHash,\n * _calldatasHash,\n * _gasAmountsHash\n * )\n * );\n */\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, TYPE_HASH)\n mstore(add(ptr, 0x20), mload(self)) // _proposal.nonce\n mstore(add(ptr, 0x40), mload(add(self, 0x20))) // _proposal.expiryTimestamp\n\n let arrayHashed\n arrayHashed := keccak256(add(targets, 32), mul(mload(targets), 32)) // targetsHash\n mstore(add(ptr, 0x60), arrayHashed)\n arrayHashed := keccak256(add(values, 32), mul(mload(values), 32)) // _valuesHash\n mstore(add(ptr, 0x80), arrayHashed)\n arrayHashed := keccak256(add(calldataHashList, 32), mul(mload(calldataHashList), 32)) // _calldatasHash\n mstore(add(ptr, 0xa0), arrayHashed)\n arrayHashed := keccak256(add(gasAmounts, 32), mul(mload(gasAmounts), 32)) // _gasAmountsHash\n mstore(add(ptr, 0xc0), arrayHashed)\n digest_ := keccak256(ptr, 0xe0)\n }\n }\n\n /**\n * @dev Converts into the normal proposal.\n */\n function intoProposalDetail(\n GlobalProposalDetail memory self,\n address[] memory targets\n ) internal pure returns (Proposal.ProposalDetail memory detail_) {\n detail_.nonce = self.nonce;\n detail_.expiryTimestamp = self.expiryTimestamp;\n detail_.chainId = 0;\n detail_.targets = new address[](self.targetOptions.length);\n detail_.values = self.values;\n detail_.calldatas = self.calldatas;\n detail_.gasAmounts = self.gasAmounts;\n\n for (uint256 i; i < self.targetOptions.length; ) {\n detail_.targets[i] = targets[i];\n unchecked {\n ++i;\n }\n }\n }\n}\n" + }, + "contracts/libraries/IsolatedGovernance.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../interfaces/consumers/VoteStatusConsumer.sol\";\nimport \"../utils/CommonErrors.sol\";\n\nlibrary IsolatedGovernance {\n struct Vote {\n VoteStatusConsumer.VoteStatus status;\n bytes32 finalHash;\n /// @dev Mapping from voter => receipt hash\n mapping(address => bytes32) voteHashOf;\n /// @dev The timestamp that voting is expired (no expiration=0)\n uint256 expiredAt;\n /// @dev The timestamp that voting is created\n uint256 createdAt;\n /// @dev The list of voters\n address[] voters;\n }\n\n /**\n * @dev Casts vote for the receipt with the receipt hash `_hash`.\n *\n * Requirements:\n * - The voter has not voted for the round.\n *\n */\n function castVote(Vote storage _v, address _voter, bytes32 _hash) internal {\n if (_v.expiredAt > 0 && _v.expiredAt <= block.timestamp) {\n _v.status = VoteStatusConsumer.VoteStatus.Expired;\n }\n\n if (voted(_v, _voter)) revert ErrAlreadyVoted(_voter);\n\n _v.voteHashOf[_voter] = _hash;\n _v.voters.push(_voter);\n }\n\n /**\n * @dev Updates vote with the requirement of minimum vote weight.\n */\n function syncVoteStatus(\n Vote storage _v,\n uint256 _minimumVoteWeight,\n uint256 _votedWeightForHash,\n bytes32 _hash\n ) internal returns (VoteStatusConsumer.VoteStatus _status) {\n if (_votedWeightForHash >= _minimumVoteWeight && _v.status == VoteStatusConsumer.VoteStatus.Pending) {\n _v.status = VoteStatusConsumer.VoteStatus.Approved;\n _v.finalHash = _hash;\n }\n\n return _v.status;\n }\n\n /**\n * @dev Returns the list of vote's addresses that voted for the hash `_hash`.\n */\n function filterByHash(Vote storage _v, bytes32 _hash) internal view returns (address[] memory _voters) {\n uint256 _count;\n _voters = new address[](_v.voters.length);\n\n unchecked {\n for (uint _i; _i < _voters.length; ++_i) {\n address _voter = _v.voters[_i];\n if (_v.voteHashOf[_voter] == _hash) {\n _voters[_count++] = _voter;\n }\n }\n }\n\n assembly {\n mstore(_voters, _count)\n }\n }\n\n /**\n * @dev Returns whether the voter casted for the proposal.\n */\n function voted(Vote storage _v, address _voter) internal view returns (bool) {\n return _v.voteHashOf[_voter] != bytes32(0);\n }\n}\n" + }, + "contracts/libraries/Math.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary Math {\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns whether the number `c` is in range of [a; b].\n */\n function inRange(uint256 c, uint256 a, uint256 b) internal pure returns (bool) {\n return a <= c && c <= b;\n }\n\n /**\n * @dev Returns whether two inclusive ranges [x1;x2] and [y1;y2] overlap.\n */\n function twoRangeOverlap(uint256 x1, uint256 x2, uint256 y1, uint256 y2) internal pure returns (bool) {\n return x1 <= y2 && y1 <= x2;\n }\n\n /**\n * @dev Returns value of a + b; in case result is larger than upperbound, upperbound is returned.\n */\n function addWithUpperbound(uint256 a, uint256 b, uint256 upperbound) internal pure returns (uint256) {\n return min(a + b, upperbound);\n }\n\n /**\n * @dev Returns value of a - b; in case of negative result, 0 is returned.\n */\n function subNonNegative(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : 0;\n }\n\n /**\n * @dev Returns value of `a + zeroable` if zerobale is not 0; otherwise, return 0.\n */\n function addIfNonZero(uint256 a, uint256 zeroable) internal pure returns (uint256) {\n return zeroable != 0 ? a + zeroable : 0;\n }\n}\n" + }, + "contracts/libraries/Proposal.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ErrInvalidChainId, ErrLengthMismatch } from \"../utils/CommonErrors.sol\";\n\nlibrary Proposal {\n /**\n * @dev Error thrown when there is insufficient gas to execute a function.\n */\n error ErrInsufficientGas(bytes32 proposalHash);\n\n /**\n * @dev Error thrown when an invalid expiry timestamp is provided.\n */\n error ErrInvalidExpiryTimestamp();\n\n struct ProposalDetail {\n // Nonce to make sure proposals are executed in order\n uint256 nonce;\n // Value 0: all chain should run this proposal\n // Other values: only specifc chain has to execute\n uint256 chainId;\n uint256 expiryTimestamp;\n address[] targets;\n uint256[] values;\n bytes[] calldatas;\n uint256[] gasAmounts;\n }\n\n // keccak256(\"ProposalDetail(uint256 nonce,uint256 chainId,uint256 expiryTimestamp,address[] targets,uint256[] values,bytes[] calldatas,uint256[] gasAmounts)\");\n bytes32 public constant TYPE_HASH = 0xd051578048e6ff0bbc9fca3b65a42088dbde10f36ca841de566711087ad9b08a;\n\n /**\n * @dev Validates the proposal.\n */\n function validate(ProposalDetail memory _proposal, uint256 _maxExpiryDuration) internal view {\n if (\n !(_proposal.targets.length > 0 &&\n _proposal.targets.length == _proposal.values.length &&\n _proposal.targets.length == _proposal.calldatas.length &&\n _proposal.targets.length == _proposal.gasAmounts.length)\n ) {\n revert ErrLengthMismatch(msg.sig);\n }\n\n if (_proposal.expiryTimestamp > block.timestamp + _maxExpiryDuration) {\n revert ErrInvalidExpiryTimestamp();\n }\n }\n\n /**\n * @dev Returns struct hash of the proposal.\n */\n function hash(ProposalDetail memory _proposal) internal pure returns (bytes32 digest_) {\n uint256[] memory _values = _proposal.values;\n address[] memory _targets = _proposal.targets;\n bytes32[] memory _calldataHashList = new bytes32[](_proposal.calldatas.length);\n uint256[] memory _gasAmounts = _proposal.gasAmounts;\n\n for (uint256 _i; _i < _calldataHashList.length; ) {\n _calldataHashList[_i] = keccak256(_proposal.calldatas[_i]);\n\n unchecked {\n ++_i;\n }\n }\n\n // return\n // keccak256(\n // abi.encode(\n // TYPE_HASH,\n // _proposal.nonce,\n // _proposal.chainId,\n // _targetsHash,\n // _valuesHash,\n // _calldatasHash,\n // _gasAmountsHash\n // )\n // );\n // /\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, TYPE_HASH)\n mstore(add(ptr, 0x20), mload(_proposal)) // _proposal.nonce\n mstore(add(ptr, 0x40), mload(add(_proposal, 0x20))) // _proposal.chainId\n mstore(add(ptr, 0x60), mload(add(_proposal, 0x40))) // expiry timestamp\n\n let arrayHashed\n arrayHashed := keccak256(add(_targets, 32), mul(mload(_targets), 32)) // targetsHash\n mstore(add(ptr, 0x80), arrayHashed)\n arrayHashed := keccak256(add(_values, 32), mul(mload(_values), 32)) // _valuesHash\n mstore(add(ptr, 0xa0), arrayHashed)\n arrayHashed := keccak256(add(_calldataHashList, 32), mul(mload(_calldataHashList), 32)) // _calldatasHash\n mstore(add(ptr, 0xc0), arrayHashed)\n arrayHashed := keccak256(add(_gasAmounts, 32), mul(mload(_gasAmounts), 32)) // _gasAmountsHash\n mstore(add(ptr, 0xe0), arrayHashed)\n digest_ := keccak256(ptr, 0x100)\n }\n }\n\n /**\n * @dev Returns whether the proposal is executable for the current chain.\n *\n * @notice Does not check whether the call result is successful or not. Please use `execute` instead.\n *\n */\n function executable(ProposalDetail memory _proposal) internal view returns (bool _result) {\n return _proposal.chainId == 0 || _proposal.chainId == block.chainid;\n }\n\n /**\n * @dev Executes the proposal.\n */\n function execute(\n ProposalDetail memory _proposal\n ) internal returns (bool[] memory _successCalls, bytes[] memory _returnDatas) {\n if (!executable(_proposal)) revert ErrInvalidChainId(msg.sig, _proposal.chainId, block.chainid);\n\n _successCalls = new bool[](_proposal.targets.length);\n _returnDatas = new bytes[](_proposal.targets.length);\n for (uint256 _i = 0; _i < _proposal.targets.length; ) {\n if (gasleft() <= _proposal.gasAmounts[_i]) revert ErrInsufficientGas(hash(_proposal));\n\n (_successCalls[_i], _returnDatas[_i]) = _proposal.targets[_i].call{\n value: _proposal.values[_i],\n gas: _proposal.gasAmounts[_i]\n }(_proposal.calldatas[_i]);\n\n unchecked {\n ++_i;\n }\n }\n }\n}\n" + }, + "contracts/libraries/Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport \"../interfaces/IWETH.sol\";\n\nlibrary Token {\n /// @dev Error indicating that the provided information is invalid.\n error ErrInvalidInfo();\n\n /// @dev Error indicating that the minting of ERC20 tokens has failed.\n error ErrERC20MintingFailed();\n\n /// @dev Error indicating that the minting of ERC721 tokens has failed.\n error ErrERC721MintingFailed();\n\n /// @dev Error indicating that an unsupported standard is encountered.\n error ErrUnsupportedStandard();\n\n /**\n * @dev Error indicating that the `transfer` has failed.\n * @param tokenInfo Info of the token including ERC standard, id or quantity.\n * @param to Receiver of the token value.\n * @param token Address of the token.\n */\n error ErrTokenCouldNotTransfer(Info tokenInfo, address to, address token);\n\n /**\n * @dev Error indicating that the `transferFrom` has failed.\n * @param tokenInfo Info of the token including ERC standard, id or quantity.\n * @param from Owner of the token value.\n * @param to Receiver of the token value.\n * @param token Address of the token.\n */\n error ErrTokenCouldNotTransferFrom(Info tokenInfo, address from, address to, address token);\n\n enum Standard {\n ERC20,\n ERC721\n }\n\n struct Info {\n Standard erc;\n // For ERC20: the id must be 0 and the quantity is larger than 0.\n // For ERC721: the quantity must be 0.\n uint256 id;\n uint256 quantity;\n }\n\n // keccak256(\"TokenInfo(uint8 erc,uint256 id,uint256 quantity)\");\n bytes32 public constant INFO_TYPE_HASH = 0x1e2b74b2a792d5c0f0b6e59b037fa9d43d84fbb759337f0112fcc15ca414fc8d;\n\n /**\n * @dev Returns token info struct hash.\n */\n function hash(Info memory _info) internal pure returns (bytes32 digest) {\n // keccak256(abi.encode(INFO_TYPE_HASH, _info.erc, _info.id, _info.quantity))\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, INFO_TYPE_HASH)\n mstore(add(ptr, 0x20), mload(_info)) // _info.erc\n mstore(add(ptr, 0x40), mload(add(_info, 0x20))) // _info.id\n mstore(add(ptr, 0x60), mload(add(_info, 0x40))) // _info.quantity\n digest := keccak256(ptr, 0x80)\n }\n }\n\n /**\n * @dev Validates the token info.\n */\n function validate(Info memory _info) internal pure {\n if (\n !((_info.erc == Standard.ERC20 && _info.quantity > 0 && _info.id == 0) ||\n (_info.erc == Standard.ERC721 && _info.quantity == 0))\n ) revert ErrInvalidInfo();\n }\n\n /**\n * @dev Transfer asset from.\n *\n * Requirements:\n * - The `_from` address must approve for the contract using this library.\n *\n */\n function transferFrom(Info memory _info, address _from, address _to, address _token) internal {\n bool _success;\n bytes memory _data;\n if (_info.erc == Standard.ERC20) {\n (_success, _data) = _token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, _from, _to, _info.quantity));\n _success = _success && (_data.length == 0 || abi.decode(_data, (bool)));\n } else if (_info.erc == Standard.ERC721) {\n // bytes4(keccak256(\"transferFrom(address,address,uint256)\"))\n (_success, ) = _token.call(abi.encodeWithSelector(0x23b872dd, _from, _to, _info.id));\n } else revert ErrUnsupportedStandard();\n\n if (!_success) revert ErrTokenCouldNotTransferFrom(_info, _from, _to, _token);\n }\n\n /**\n * @dev Transfers ERC721 token and returns the result.\n */\n function tryTransferERC721(address _token, address _to, uint256 _id) internal returns (bool _success) {\n (_success, ) = _token.call(abi.encodeWithSelector(IERC721.transferFrom.selector, address(this), _to, _id));\n }\n\n /**\n * @dev Transfers ERC20 token and returns the result.\n */\n function tryTransferERC20(address _token, address _to, uint256 _quantity) internal returns (bool _success) {\n bytes memory _data;\n (_success, _data) = _token.call(abi.encodeWithSelector(IERC20.transfer.selector, _to, _quantity));\n _success = _success && (_data.length == 0 || abi.decode(_data, (bool)));\n }\n\n /**\n * @dev Transfer assets from current address to `_to` address.\n */\n function transfer(Info memory _info, address _to, address _token) internal {\n bool _success;\n if (_info.erc == Standard.ERC20) {\n _success = tryTransferERC20(_token, _to, _info.quantity);\n } else if (_info.erc == Standard.ERC721) {\n _success = tryTransferERC721(_token, _to, _info.id);\n } else revert ErrUnsupportedStandard();\n\n if (!_success) revert ErrTokenCouldNotTransfer(_info, _to, _token);\n }\n\n /**\n * @dev Tries minting and transfering assets.\n *\n * @notice Prioritizes transfer native token if the token is wrapped.\n *\n */\n function handleAssetTransfer(\n Info memory _info,\n address payable _to,\n address _token,\n IWETH _wrappedNativeToken\n ) internal {\n bool _success;\n if (_token == address(_wrappedNativeToken)) {\n // Try sending the native token before transferring the wrapped token\n if (!_to.send(_info.quantity)) {\n _wrappedNativeToken.deposit{ value: _info.quantity }();\n transfer(_info, _to, _token);\n }\n } else if (_info.erc == Token.Standard.ERC20) {\n uint256 _balance = IERC20(_token).balanceOf(address(this));\n\n if (_balance < _info.quantity) {\n // bytes4(keccak256(\"mint(address,uint256)\"))\n (_success, ) = _token.call(abi.encodeWithSelector(0x40c10f19, address(this), _info.quantity - _balance));\n if (!_success) revert ErrERC20MintingFailed();\n }\n\n transfer(_info, _to, _token);\n } else if (_info.erc == Token.Standard.ERC721) {\n if (!tryTransferERC721(_token, _to, _info.id)) {\n // bytes4(keccak256(\"mint(address,uint256)\"))\n (_success, ) = _token.call(abi.encodeWithSelector(0x40c10f19, _to, _info.id));\n if (!_success) revert ErrERC721MintingFailed();\n }\n } else revert ErrUnsupportedStandard();\n }\n\n struct Owner {\n address addr;\n address tokenAddr;\n uint256 chainId;\n }\n\n // keccak256(\"TokenOwner(address addr,address tokenAddr,uint256 chainId)\");\n bytes32 public constant OWNER_TYPE_HASH = 0x353bdd8d69b9e3185b3972e08b03845c0c14a21a390215302776a7a34b0e8764;\n\n /**\n * @dev Returns ownership struct hash.\n */\n function hash(Owner memory _owner) internal pure returns (bytes32 digest) {\n // keccak256(abi.encode(OWNER_TYPE_HASH, _owner.addr, _owner.tokenAddr, _owner.chainId))\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, OWNER_TYPE_HASH)\n mstore(add(ptr, 0x20), mload(_owner)) // _owner.addr\n mstore(add(ptr, 0x40), mload(add(_owner, 0x20))) // _owner.tokenAddr\n mstore(add(ptr, 0x60), mload(add(_owner, 0x40))) // _owner.chainId\n digest := keccak256(ptr, 0x80)\n }\n }\n}\n" + }, + "contracts/libraries/Transfer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./Token.sol\";\n\nlibrary Transfer {\n using ECDSA for bytes32;\n\n enum Kind {\n Deposit,\n Withdrawal\n }\n\n struct Request {\n // For deposit request: Recipient address on Ronin network\n // For withdrawal request: Recipient address on mainchain network\n address recipientAddr;\n // Token address to deposit/withdraw\n // Value 0: native token\n address tokenAddr;\n Token.Info info;\n }\n\n /**\n * @dev Converts the transfer request into the deposit receipt.\n */\n function into_deposit_receipt(\n Request memory _request,\n address _requester,\n uint256 _id,\n address _roninTokenAddr,\n uint256 _roninChainId\n ) internal view returns (Receipt memory _receipt) {\n _receipt.id = _id;\n _receipt.kind = Kind.Deposit;\n _receipt.mainchain.addr = _requester;\n _receipt.mainchain.tokenAddr = _request.tokenAddr;\n _receipt.mainchain.chainId = block.chainid;\n _receipt.ronin.addr = _request.recipientAddr;\n _receipt.ronin.tokenAddr = _roninTokenAddr;\n _receipt.ronin.chainId = _roninChainId;\n _receipt.info = _request.info;\n }\n\n /**\n * @dev Converts the transfer request into the withdrawal receipt.\n */\n function into_withdrawal_receipt(\n Request memory _request,\n address _requester,\n uint256 _id,\n address _mainchainTokenAddr,\n uint256 _mainchainId\n ) internal view returns (Receipt memory _receipt) {\n _receipt.id = _id;\n _receipt.kind = Kind.Withdrawal;\n _receipt.ronin.addr = _requester;\n _receipt.ronin.tokenAddr = _request.tokenAddr;\n _receipt.ronin.chainId = block.chainid;\n _receipt.mainchain.addr = _request.recipientAddr;\n _receipt.mainchain.tokenAddr = _mainchainTokenAddr;\n _receipt.mainchain.chainId = _mainchainId;\n _receipt.info = _request.info;\n }\n\n struct Receipt {\n uint256 id;\n Kind kind;\n Token.Owner mainchain;\n Token.Owner ronin;\n Token.Info info;\n }\n\n // keccak256(\"Receipt(uint256 id,uint8 kind,TokenOwner mainchain,TokenOwner ronin,TokenInfo info)TokenInfo(uint8 erc,uint256 id,uint256 quantity)TokenOwner(address addr,address tokenAddr,uint256 chainId)\");\n bytes32 public constant TYPE_HASH = 0xb9d1fe7c9deeec5dc90a2f47ff1684239519f2545b2228d3d91fb27df3189eea;\n\n /**\n * @dev Returns token info struct hash.\n */\n function hash(Receipt memory _receipt) internal pure returns (bytes32 digest) {\n bytes32 hashedReceiptMainchain = Token.hash(_receipt.mainchain);\n bytes32 hashedReceiptRonin = Token.hash(_receipt.ronin);\n bytes32 hashedReceiptInfo = Token.hash(_receipt.info);\n\n /*\n * return\n * keccak256(\n * abi.encode(\n * TYPE_HASH,\n * _receipt.id,\n * _receipt.kind,\n * Token.hash(_receipt.mainchain),\n * Token.hash(_receipt.ronin),\n * Token.hash(_receipt.info)\n * )\n * );\n */\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, TYPE_HASH)\n mstore(add(ptr, 0x20), mload(_receipt)) // _receipt.id\n mstore(add(ptr, 0x40), mload(add(_receipt, 0x20))) // _receipt.kind\n mstore(add(ptr, 0x60), hashedReceiptMainchain)\n mstore(add(ptr, 0x80), hashedReceiptRonin)\n mstore(add(ptr, 0xa0), hashedReceiptInfo)\n digest := keccak256(ptr, 0xc0)\n }\n }\n\n /**\n * @dev Returns the receipt digest.\n */\n function receiptDigest(bytes32 _domainSeparator, bytes32 _receiptHash) internal pure returns (bytes32) {\n return _domainSeparator.toTypedDataHash(_receiptHash);\n }\n}\n" + }, + "contracts/mainchain/MainchainBridgeManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { CoreGovernance } from \"../extensions/sequential-governance/CoreGovernance.sol\";\nimport { GlobalCoreGovernance, GlobalGovernanceRelay } from \"../extensions/sequential-governance/governance-relay/GlobalGovernanceRelay.sol\";\nimport { GovernanceRelay } from \"../extensions/sequential-governance/governance-relay/GovernanceRelay.sol\";\nimport { ContractType, BridgeManager } from \"../extensions/bridge-operator-governance/BridgeManager.sol\";\nimport { Ballot } from \"../libraries/Ballot.sol\";\nimport { Proposal } from \"../libraries/Proposal.sol\";\nimport { GlobalProposal } from \"../libraries/GlobalProposal.sol\";\nimport \"../utils/CommonErrors.sol\";\n\ncontract MainchainBridgeManager is BridgeManager, GovernanceRelay, GlobalGovernanceRelay {\n uint256 private constant DEFAULT_EXPIRY_DURATION = 1 << 255;\n\n constructor(\n uint256 num,\n uint256 denom,\n uint256 roninChainId,\n address bridgeContract,\n address[] memory callbackRegisters,\n address[] memory bridgeOperators,\n address[] memory governors,\n uint96[] memory voteWeights,\n GlobalProposal.TargetOption[] memory targetOptions,\n address[] memory targets\n )\n payable\n CoreGovernance(DEFAULT_EXPIRY_DURATION)\n GlobalCoreGovernance(targetOptions, targets)\n BridgeManager(num, denom, roninChainId, bridgeContract, callbackRegisters, bridgeOperators, governors, voteWeights)\n {}\n\n /**\n * @dev See `GovernanceRelay-_relayProposal`.\n *\n * Requirements:\n * - The method caller is governor.\n */\n function relayProposal(\n Proposal.ProposalDetail calldata proposal,\n Ballot.VoteType[] calldata supports_,\n Signature[] calldata signatures\n ) external onlyGovernor {\n _relayProposal(proposal, supports_, signatures, DOMAIN_SEPARATOR, msg.sender);\n }\n\n /**\n * @dev See `GovernanceRelay-_relayGlobalProposal`.\n *\n * Requirements:\n * - The method caller is governor.\n */\n function relayGlobalProposal(\n GlobalProposal.GlobalProposalDetail calldata globalProposal,\n Ballot.VoteType[] calldata supports_,\n Signature[] calldata signatures\n ) external onlyGovernor {\n _relayGlobalProposal({\n globalProposal: globalProposal,\n supports_: supports_,\n signatures: signatures,\n domainSeparator: DOMAIN_SEPARATOR,\n creator: msg.sender\n });\n }\n\n /**\n * @dev Internal function to retrieve the minimum vote weight required for governance actions.\n * @return minimumVoteWeight The minimum vote weight required for governance actions.\n */\n function _getMinimumVoteWeight() internal view override returns (uint256) {\n return minimumVoteWeight();\n }\n\n /**\n * @dev Returns the expiry duration for a new proposal.\n */\n function getProposalExpiryDuration() external view returns (uint256) {\n return _getProposalExpiryDuration();\n }\n\n /**\n * @dev Internal function to retrieve the total weights of all governors.\n * @return totalWeights The total weights of all governors combined.\n */\n function _getTotalWeight() internal view override returns (uint256) {\n return getTotalWeight();\n }\n\n /**\n * @dev Internal function to calculate the sum of weights for a given array of governors.\n * @param governors An array containing the addresses of governors to calculate the sum of weights.\n * @return sumWeights The sum of weights for the provided governors.\n */\n function _sumWeight(address[] memory governors) internal view override returns (uint256) {\n return _sumGovernorsWeight(governors);\n }\n\n /**\n * @dev Internal function to retrieve the chain type of the contract.\n * @return chainType The chain type, indicating the type of the chain the contract operates on (e.g., Mainchain).\n */\n function _getChainType() internal pure override returns (ChainType) {\n return ChainType.Mainchain;\n }\n}\n" + }, + "contracts/mainchain/MainchainGatewayV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/AccessControlEnumerable.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { IBridgeManager } from \"../interfaces/bridge/IBridgeManager.sol\";\nimport { IBridgeManagerCallback } from \"../interfaces/bridge/IBridgeManagerCallback.sol\";\nimport { HasContracts, ContractType } from \"../extensions/collections/HasContracts.sol\";\nimport \"../extensions/WithdrawalLimitation.sol\";\nimport \"../libraries/Transfer.sol\";\nimport \"../interfaces/IMainchainGatewayV2.sol\";\n\ncontract MainchainGatewayV2 is\n WithdrawalLimitation,\n Initializable,\n AccessControlEnumerable,\n IMainchainGatewayV2,\n HasContracts\n{\n using Token for Token.Info;\n using Transfer for Transfer.Request;\n using Transfer for Transfer.Receipt;\n\n /// @dev Withdrawal unlocker role hash\n bytes32 public constant WITHDRAWAL_UNLOCKER_ROLE = keccak256(\"WITHDRAWAL_UNLOCKER_ROLE\");\n\n /// @dev Wrapped native token address\n IWETH public wrappedNativeToken;\n /// @dev Ronin network id\n uint256 public roninChainId;\n /// @dev Total deposit\n uint256 public depositCount;\n /// @dev Domain seperator\n bytes32 internal _domainSeparator;\n /// @dev Mapping from mainchain token => token address on Ronin network\n mapping(address => MappedToken) internal _roninToken;\n /// @dev Mapping from withdrawal id => withdrawal hash\n mapping(uint256 => bytes32) public withdrawalHash;\n /// @dev Mapping from withdrawal id => locked\n mapping(uint256 => bool) public withdrawalLocked;\n\n /// @custom:deprecated Previously `_bridgeOperatorAddedBlock` (mapping(address => uint256))\n uint256 private ______deprecatedBridgeOperatorAddedBlock;\n /// @custom:deprecated Previously `_bridgeOperators` (uint256[])\n uint256 private ______deprecatedBridgeOperators;\n\n fallback() external payable {\n _fallback();\n }\n\n receive() external payable {\n _fallback();\n }\n\n /**\n * @dev Initializes contract storage.\n */\n function initialize(\n address _roleSetter,\n IWETH _wrappedToken,\n uint256 _roninChainId,\n uint256 _numerator,\n uint256 _highTierVWNumerator,\n uint256 _denominator,\n // _addresses[0]: mainchainTokens\n // _addresses[1]: roninTokens\n // _addresses[2]: withdrawalUnlockers\n address[][3] calldata _addresses,\n // _thresholds[0]: highTierThreshold\n // _thresholds[1]: lockedThreshold\n // _thresholds[2]: unlockFeePercentages\n // _thresholds[3]: dailyWithdrawalLimit\n uint256[][4] calldata _thresholds,\n Token.Standard[] calldata _standards\n ) external payable virtual initializer {\n _setupRole(DEFAULT_ADMIN_ROLE, _roleSetter);\n roninChainId = _roninChainId;\n\n _setWrappedNativeTokenContract(_wrappedToken);\n _updateDomainSeparator();\n _setThreshold(_numerator, _denominator);\n _setHighTierVoteWeightThreshold(_highTierVWNumerator, _denominator);\n _verifyThresholds();\n\n if (_addresses[0].length > 0) {\n // Map mainchain tokens to ronin tokens\n _mapTokens(_addresses[0], _addresses[1], _standards);\n // Sets thresholds based on the mainchain tokens\n _setHighTierThresholds(_addresses[0], _thresholds[0]);\n _setLockedThresholds(_addresses[0], _thresholds[1]);\n _setUnlockFeePercentages(_addresses[0], _thresholds[2]);\n _setDailyWithdrawalLimits(_addresses[0], _thresholds[3]);\n }\n\n // Grant role for withdrawal unlocker\n for (uint256 _i; _i < _addresses[2].length; ) {\n _grantRole(WITHDRAWAL_UNLOCKER_ROLE, _addresses[2][_i]);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n function initializeV2(address bridgeManagerContract) external reinitializer(2) {\n _setContract(ContractType.BRIDGE_MANAGER, bridgeManagerContract);\n }\n\n /**\n * @dev Receives ether without doing anything. Use this function to topup native token.\n */\n function receiveEther() external payable {}\n\n /**\n * @inheritdoc IMainchainGatewayV2\n */\n function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {\n return _domainSeparator;\n }\n\n /**\n * @inheritdoc IMainchainGatewayV2\n */\n function setWrappedNativeTokenContract(IWETH _wrappedToken) external virtual onlyAdmin {\n _setWrappedNativeTokenContract(_wrappedToken);\n }\n\n /**\n * @inheritdoc IMainchainGatewayV2\n */\n function requestDepositFor(Transfer.Request calldata _request) external payable virtual whenNotPaused {\n _requestDepositFor(_request, msg.sender);\n }\n\n /**\n * @inheritdoc IMainchainGatewayV2\n */\n function submitWithdrawal(\n Transfer.Receipt calldata _receipt,\n Signature[] calldata _signatures\n ) external virtual whenNotPaused returns (bool _locked) {\n return _submitWithdrawal(_receipt, _signatures);\n }\n\n /**\n * @inheritdoc IMainchainGatewayV2\n */\n function unlockWithdrawal(Transfer.Receipt calldata _receipt) external onlyRole(WITHDRAWAL_UNLOCKER_ROLE) {\n bytes32 _receiptHash = _receipt.hash();\n if (withdrawalHash[_receipt.id] != _receipt.hash()) {\n revert ErrInvalidReceipt();\n }\n if (!withdrawalLocked[_receipt.id]) {\n revert ErrQueryForApprovedWithdrawal();\n }\n delete withdrawalLocked[_receipt.id];\n emit WithdrawalUnlocked(_receiptHash, _receipt);\n\n address _token = _receipt.mainchain.tokenAddr;\n if (_receipt.info.erc == Token.Standard.ERC20) {\n Token.Info memory _feeInfo = _receipt.info;\n _feeInfo.quantity = _computeFeePercentage(_receipt.info.quantity, unlockFeePercentages[_token]);\n Token.Info memory _withdrawInfo = _receipt.info;\n _withdrawInfo.quantity = _receipt.info.quantity - _feeInfo.quantity;\n\n _feeInfo.handleAssetTransfer(payable(msg.sender), _token, wrappedNativeToken);\n _withdrawInfo.handleAssetTransfer(payable(_receipt.mainchain.addr), _token, wrappedNativeToken);\n } else {\n _receipt.info.handleAssetTransfer(payable(_receipt.mainchain.addr), _token, wrappedNativeToken);\n }\n\n emit Withdrew(_receiptHash, _receipt);\n }\n\n /**\n * @inheritdoc IMainchainGatewayV2\n */\n function mapTokens(\n address[] calldata _mainchainTokens,\n address[] calldata _roninTokens,\n Token.Standard[] calldata _standards\n ) external virtual onlyAdmin {\n if (_mainchainTokens.length == 0) revert ErrEmptyArray();\n _mapTokens(_mainchainTokens, _roninTokens, _standards);\n }\n\n /**\n * @inheritdoc IMainchainGatewayV2\n */\n function mapTokensAndThresholds(\n address[] calldata _mainchainTokens,\n address[] calldata _roninTokens,\n Token.Standard[] calldata _standards,\n // _thresholds[0]: highTierThreshold\n // _thresholds[1]: lockedThreshold\n // _thresholds[2]: unlockFeePercentages\n // _thresholds[3]: dailyWithdrawalLimit\n uint256[][4] calldata _thresholds\n ) external virtual onlyAdmin {\n if (_mainchainTokens.length == 0) revert ErrEmptyArray();\n _mapTokens(_mainchainTokens, _roninTokens, _standards);\n _setHighTierThresholds(_mainchainTokens, _thresholds[0]);\n _setLockedThresholds(_mainchainTokens, _thresholds[1]);\n _setUnlockFeePercentages(_mainchainTokens, _thresholds[2]);\n _setDailyWithdrawalLimits(_mainchainTokens, _thresholds[3]);\n }\n\n /**\n * @inheritdoc IMainchainGatewayV2\n */\n function getRoninToken(address _mainchainToken) public view returns (MappedToken memory _token) {\n _token = _roninToken[_mainchainToken];\n if (_token.tokenAddr == address(0)) revert ErrUnsupportedToken();\n }\n\n /**\n * @dev Maps mainchain tokens to Ronin network.\n *\n * Requirement:\n * - The arrays have the same length.\n *\n * Emits the `TokenMapped` event.\n *\n */\n function _mapTokens(\n address[] calldata _mainchainTokens,\n address[] calldata _roninTokens,\n Token.Standard[] calldata _standards\n ) internal virtual {\n if (!(_mainchainTokens.length == _roninTokens.length && _mainchainTokens.length == _standards.length))\n revert ErrLengthMismatch(msg.sig);\n\n for (uint256 _i; _i < _mainchainTokens.length; ) {\n _roninToken[_mainchainTokens[_i]].tokenAddr = _roninTokens[_i];\n _roninToken[_mainchainTokens[_i]].erc = _standards[_i];\n\n unchecked {\n ++_i;\n }\n }\n\n emit TokenMapped(_mainchainTokens, _roninTokens, _standards);\n }\n\n /**\n * @dev Submits withdrawal receipt.\n *\n * Requirements:\n * - The receipt kind is withdrawal.\n * - The receipt is to withdraw on this chain.\n * - The receipt is not used to withdraw before.\n * - The withdrawal is not reached the limit threshold.\n * - The signer weight total is larger than or equal to the minimum threshold.\n * - The signature signers are in order.\n *\n * Emits the `Withdrew` once the assets are released.\n *\n */\n function _submitWithdrawal(\n Transfer.Receipt calldata _receipt,\n Signature[] memory _signatures\n ) internal virtual returns (bool _locked) {\n uint256 _id = _receipt.id;\n uint256 _quantity = _receipt.info.quantity;\n address _tokenAddr = _receipt.mainchain.tokenAddr;\n\n _receipt.info.validate();\n if (_receipt.kind != Transfer.Kind.Withdrawal) revert ErrInvalidReceiptKind();\n\n if (_receipt.mainchain.chainId != block.chainid) {\n revert ErrInvalidChainId(msg.sig, _receipt.mainchain.chainId, block.chainid);\n }\n\n MappedToken memory _token = getRoninToken(_receipt.mainchain.tokenAddr);\n\n if (!(_token.erc == _receipt.info.erc && _token.tokenAddr == _receipt.ronin.tokenAddr)) revert ErrInvalidReceipt();\n\n if (withdrawalHash[_id] != 0) revert ErrQueryForProcessedWithdrawal();\n\n if (!(_receipt.info.erc == Token.Standard.ERC721 || !_reachedWithdrawalLimit(_tokenAddr, _quantity))) {\n revert ErrReachedDailyWithdrawalLimit();\n }\n\n bytes32 _receiptHash = _receipt.hash();\n bytes32 _receiptDigest = Transfer.receiptDigest(_domainSeparator, _receiptHash);\n\n uint256 _minimumVoteWeight;\n (_minimumVoteWeight, _locked) = _computeMinVoteWeight(_receipt.info.erc, _tokenAddr, _quantity);\n\n {\n bool _passed;\n address _signer;\n address _lastSigner;\n Signature memory _sig;\n uint256 _weight;\n for (uint256 _i; _i < _signatures.length; ) {\n _sig = _signatures[_i];\n _signer = ecrecover(_receiptDigest, _sig.v, _sig.r, _sig.s);\n if (_lastSigner >= _signer) revert ErrInvalidOrder(msg.sig);\n\n _lastSigner = _signer;\n\n _weight += _getWeight(_signer);\n if (_weight >= _minimumVoteWeight) {\n _passed = true;\n break;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n if (!_passed) revert ErrQueryForInsufficientVoteWeight();\n withdrawalHash[_id] = _receiptHash;\n }\n\n if (_locked) {\n withdrawalLocked[_id] = true;\n emit WithdrawalLocked(_receiptHash, _receipt);\n return _locked;\n }\n\n _recordWithdrawal(_tokenAddr, _quantity);\n _receipt.info.handleAssetTransfer(payable(_receipt.mainchain.addr), _tokenAddr, wrappedNativeToken);\n emit Withdrew(_receiptHash, _receipt);\n }\n\n /**\n * @dev Requests deposit made by `_requester` address.\n *\n * Requirements:\n * - The token info is valid.\n * - The `msg.value` is 0 while depositing ERC20 token.\n * - The `msg.value` is equal to deposit quantity while depositing native token.\n *\n * Emits the `DepositRequested` event.\n *\n */\n function _requestDepositFor(Transfer.Request memory _request, address _requester) internal virtual {\n MappedToken memory _token;\n address _weth = address(wrappedNativeToken);\n\n _request.info.validate();\n if (_request.tokenAddr == address(0)) {\n if (_request.info.quantity != msg.value) revert ErrInvalidRequest();\n\n _token = getRoninToken(_weth);\n if (_token.erc != _request.info.erc) revert ErrInvalidTokenStandard();\n\n _request.tokenAddr = _weth;\n } else {\n if (msg.value != 0) revert ErrInvalidRequest();\n\n _token = getRoninToken(_request.tokenAddr);\n if (_token.erc != _request.info.erc) revert ErrInvalidTokenStandard();\n\n _request.info.transferFrom(_requester, address(this), _request.tokenAddr);\n // Withdraw if token is WETH\n if (_weth == _request.tokenAddr) {\n IWETH(_weth).withdraw(_request.info.quantity);\n }\n }\n\n uint256 _depositId = depositCount++;\n Transfer.Receipt memory _receipt = _request.into_deposit_receipt(\n _requester,\n _depositId,\n _token.tokenAddr,\n roninChainId\n );\n\n emit DepositRequested(_receipt.hash(), _receipt);\n }\n\n /**\n * @dev Returns the minimum vote weight for the token.\n */\n function _computeMinVoteWeight(\n Token.Standard _erc,\n address _token,\n uint256 _quantity\n ) internal virtual returns (uint256 _weight, bool _locked) {\n uint256 _totalWeight = _getTotalWeight();\n _weight = _minimumVoteWeight(_totalWeight);\n if (_erc == Token.Standard.ERC20) {\n if (highTierThreshold[_token] <= _quantity) {\n _weight = _highTierVoteWeight(_totalWeight);\n }\n _locked = _lockedWithdrawalRequest(_token, _quantity);\n }\n }\n\n /**\n * @dev Update domain seperator.\n */\n function _updateDomainSeparator() internal {\n /*\n * _domainSeparator = keccak256(\n * abi.encode(\n * keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n * keccak256(\"MainchainGatewayV2\"),\n * keccak256(\"2\"),\n * block.chainid,\n * address(this)\n * )\n * );\n */\n assembly {\n let ptr := mload(0x40)\n // keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")\n mstore(ptr, 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f)\n // keccak256(\"MainchainGatewayV2\")\n mstore(add(ptr, 0x20), 0x159f52c1e3a2b6a6aad3950adf713516211484e0516dad685ea662a094b7c43b)\n // keccak256(\"2\")\n mstore(add(ptr, 0x40), 0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5)\n mstore(add(ptr, 0x60), chainid())\n mstore(add(ptr, 0x80), address())\n sstore(_domainSeparator.slot, keccak256(ptr, 0xa0))\n }\n }\n\n /**\n * @dev Sets the WETH contract.\n *\n * Emits the `WrappedNativeTokenContractUpdated` event.\n *\n */\n function _setWrappedNativeTokenContract(IWETH _wrapedToken) internal {\n wrappedNativeToken = _wrapedToken;\n emit WrappedNativeTokenContractUpdated(_wrapedToken);\n }\n\n /**\n * @dev Receives ETH from WETH or creates deposit request.\n */\n function _fallback() internal virtual whenNotPaused {\n if (msg.sender != address(wrappedNativeToken)) {\n Transfer.Request memory _request;\n _request.recipientAddr = msg.sender;\n _request.info.quantity = msg.value;\n _requestDepositFor(_request, _request.recipientAddr);\n }\n }\n\n /**\n * @inheritdoc GatewayV2\n */\n function _getTotalWeight() internal view override returns (uint256) {\n return IBridgeManager(getContract(ContractType.BRIDGE_MANAGER)).getTotalWeight();\n }\n\n /**\n * @dev Returns the weight of an address.\n */\n function _getWeight(address _addr) internal view returns (uint256) {\n return IBridgeManager(getContract(ContractType.BRIDGE_MANAGER)).getBridgeOperatorWeight(_addr);\n }\n}\n" + }, + "contracts/mocks/forwarder/MockForwarderTarget.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../extensions/RONTransferHelper.sol\";\n\nimport \"../../utils/CommonErrors.sol\";\n\ncontract MockForwarderTarget is RONTransferHelper {\n address public owner;\n uint256 public data;\n\n event TargetWithdrawn(address indexed _origin, address indexed _caller, address indexed _recipient);\n\n /**\n * @dev Error thrown intentionally for a specific purpose.\n */\n error ErrIntentionally();\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN);\n _;\n }\n\n fallback() external payable {\n _fallback();\n }\n\n receive() external payable {\n _fallback();\n }\n\n constructor(address _owner, uint256 _data) payable {\n owner = _owner;\n data = _data;\n }\n\n function foo(uint256 _data) external onlyOwner {\n data = _data;\n }\n\n function fooPayable(uint256 _data) external payable onlyOwner {\n data = _data;\n }\n\n function fooSilentRevert() external view onlyOwner {\n revert();\n }\n\n function fooCustomErrorRevert() external view onlyOwner {\n revert ErrIntentionally();\n }\n\n function fooRevert() external view onlyOwner {\n revert(\"MockForwarderContract: revert intentionally\");\n }\n\n function getBalance() external view returns (uint256) {\n return address(this).balance;\n }\n\n function withdrawAll() external onlyOwner {\n emit TargetWithdrawn(tx.origin, msg.sender, msg.sender);\n _transferRON(payable(msg.sender), address(this).balance);\n }\n\n function _fallback() private pure {\n revert(\"MockForwardTarget: hello from fallback\");\n }\n}\n" + }, + "contracts/mocks/libraries/Sorting.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary Sorting {\n struct Node {\n uint key;\n uint value;\n }\n\n struct Node3 {\n uint key;\n uint value;\n uint otherKey;\n }\n\n ///////////////////////////////////////////////////////////////////////////////////////\n // VALUE SORTING //\n ///////////////////////////////////////////////////////////////////////////////////////\n\n function sort(uint[] memory data) internal pure returns (uint[] memory) {\n return _quickSort(data, int(0), int(data.length - 1));\n }\n\n function _quickSort(uint[] memory arr, int left, int right) private pure returns (uint[] memory) {\n int i = left;\n int j = right;\n if (i == j) return arr;\n uint pivot = arr[uint(left + (right - left) / 2)];\n while (i <= j) {\n while (arr[uint(i)] > pivot) i++;\n while (pivot > arr[uint(j)]) j--;\n if (i <= j) {\n (arr[uint(i)], arr[uint(j)]) = (arr[uint(j)], arr[uint(i)]);\n i++;\n j--;\n }\n }\n if (left < j) arr = _quickSort(arr, left, j);\n if (i < right) arr = _quickSort(arr, i, right);\n\n return arr;\n }\n\n ///////////////////////////////////////////////////////////////////////////////////////\n // NODE SORTING //\n ///////////////////////////////////////////////////////////////////////////////////////\n\n function sort(address[] memory _keys, uint256[] memory _values) internal pure returns (address[] memory) {\n require(_values.length == _keys.length, \"Sorting: invalid array length\");\n if (_keys.length == 0) {\n return _keys;\n }\n\n Node[] memory _nodes = new Node[](_keys.length);\n for (uint256 _i; _i < _nodes.length; _i++) {\n _nodes[_i] = Node(uint256(uint160(_keys[_i])), _values[_i]);\n }\n _quickSortNodes(_nodes, int(0), int(_nodes.length - 1));\n\n for (uint256 _i; _i < _nodes.length; _i++) {\n _keys[_i] = address(uint160(_nodes[_i].key)); // Casting?\n }\n\n return _keys;\n }\n\n function sort(uint256[] memory keys, uint256[] memory values) internal pure returns (uint256[] memory) {\n require(values.length == keys.length, \"Sorting: invalid array length\");\n if (keys.length == 0) {\n return keys;\n }\n\n Node[] memory _nodes = new Node[](keys.length);\n for (uint256 _i; _i < _nodes.length; _i++) {\n _nodes[_i] = Node(keys[_i], values[_i]);\n }\n _quickSortNodes(_nodes, int(0), int(_nodes.length - 1));\n\n for (uint256 _i; _i < _nodes.length; _i++) {\n keys[_i] = _nodes[_i].key; // Casting?\n }\n\n return keys;\n }\n\n function sortNodes(Node[] memory nodes) internal pure returns (Node[] memory) {\n return _quickSortNodes(nodes, int(0), int(nodes.length - 1));\n }\n\n function _quickSortNodes(Node[] memory nodes, int left, int right) private pure returns (Node[] memory) {\n int i = left;\n int j = right;\n if (i == j) return nodes;\n Node memory pivot = nodes[uint(left + (right - left) / 2)];\n while (i <= j) {\n while (nodes[uint(i)].value > pivot.value) i++;\n while (pivot.value > nodes[uint(j)].value) j--;\n if (i <= j) {\n (nodes[uint(i)], nodes[uint(j)]) = __swapNodes(nodes[uint(i)], nodes[uint(j)]);\n i++;\n j--;\n }\n }\n if (left < j) nodes = _quickSortNodes(nodes, left, j);\n if (i < right) nodes = _quickSortNodes(nodes, i, right);\n\n return nodes;\n }\n\n function _bubbleSortNodes(Node[] memory nodes) private pure returns (Node[] memory) {\n uint length = nodes.length;\n for (uint i = 0; i < length - 1; i++) {\n for (uint j = i + 1; j < length; j++) {\n if (nodes[j].value > nodes[i].value) {\n (nodes[i], nodes[j]) = __swapNodes(nodes[i], nodes[j]);\n }\n }\n }\n return nodes;\n }\n\n function __swapNodes(Node memory x, Node memory y) private pure returns (Node memory, Node memory) {\n Node memory tmp = x;\n (x, y) = (y, tmp);\n return (x, y);\n }\n\n ///////////////////////////////////////////////////////////////////////////////////////\n // NODE3 SORTING //\n ///////////////////////////////////////////////////////////////////////////////////////\n\n function sortWithExternalKeys(\n address[] memory _keys,\n uint256[] memory _values,\n uint256[] memory _otherKeys\n ) internal pure returns (address[] memory keys_, uint256[] memory otherKeys_) {\n require((_values.length == _keys.length) && (_otherKeys.length == _keys.length), \"Sorting: invalid array length\");\n if (_keys.length == 0) {\n return (_keys, _otherKeys);\n }\n\n Node3[] memory _nodes = new Node3[](_keys.length);\n for (uint256 _i; _i < _nodes.length; _i++) {\n _nodes[_i] = Node3(uint256(uint160(_keys[_i])), _values[_i], _otherKeys[_i]);\n }\n _quickSortNode3s(_nodes, int(0), int(_nodes.length - 1));\n\n for (uint256 _i; _i < _nodes.length; _i++) {\n _keys[_i] = address(uint160(_nodes[_i].key)); // Casting?\n }\n\n return (_keys, _otherKeys);\n }\n\n function sortNode3s(Node3[] memory nodes) internal pure returns (Node3[] memory) {\n return _quickSortNode3s(nodes, int(0), int(nodes.length - 1));\n }\n\n function _quickSortNode3s(Node3[] memory nodes, int left, int right) private pure returns (Node3[] memory) {\n int i = left;\n int j = right;\n if (i == j) return nodes;\n Node3 memory pivot = nodes[uint(left + (right - left) / 2)];\n while (i <= j) {\n while (nodes[uint(i)].value > pivot.value) i++;\n while (pivot.value > nodes[uint(j)].value) j--;\n if (i <= j) {\n (nodes[uint(i)], nodes[uint(j)]) = __swapNode3s(nodes[uint(i)], nodes[uint(j)]);\n i++;\n j--;\n }\n }\n if (left < j) nodes = _quickSortNode3s(nodes, left, j);\n if (i < right) nodes = _quickSortNode3s(nodes, i, right);\n\n return nodes;\n }\n\n function _bubbleSortNode3s(Node3[] memory nodes) private pure returns (Node3[] memory) {\n uint length = nodes.length;\n for (uint i = 0; i < length - 1; i++) {\n for (uint j = i + 1; j < length; j++) {\n if (nodes[j].value > nodes[i].value) {\n (nodes[i], nodes[j]) = __swapNode3s(nodes[i], nodes[j]);\n }\n }\n }\n return nodes;\n }\n\n function __swapNode3s(Node3 memory x, Node3 memory y) private pure returns (Node3 memory, Node3 memory) {\n Node3 memory tmp = x;\n (x, y) = (y, tmp);\n return (x, y);\n }\n}\n" + }, + "contracts/mocks/MockBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol\";\nimport \"../interfaces/IBridge.sol\";\n\ncontract MockBridge is IBridge {\n /// @dev Mapping from validator address => last block that the bridge operator is added\n mapping(address => uint256) public bridgeOperatorAddedBlock;\n /// @dev Bridge operators array\n address[] public bridgeOperators;\n\n function replaceBridgeOperators(address[] calldata _list) external {\n address _addr;\n for (uint256 _i = 0; _i < _list.length; _i++) {\n _addr = _list[_i];\n if (bridgeOperatorAddedBlock[_addr] == 0) {\n bridgeOperators.push(_addr);\n }\n bridgeOperatorAddedBlock[_addr] = block.number;\n }\n\n {\n uint256 _i;\n while (_i < bridgeOperators.length) {\n _addr = bridgeOperators[_i];\n if (bridgeOperatorAddedBlock[_addr] < block.number) {\n delete bridgeOperatorAddedBlock[_addr];\n bridgeOperators[_i] = bridgeOperators[bridgeOperators.length - 1];\n bridgeOperators.pop();\n continue;\n }\n _i++;\n }\n }\n }\n\n function getBridgeOperators() external view override returns (address[] memory) {\n return bridgeOperators;\n }\n}\n" + }, + "contracts/mocks/MockGatewayForTracking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../interfaces/bridge/IBridgeTracking.sol\";\nimport \"../extensions/collections/HasContracts.sol\";\nimport { HasBridgeTrackingDeprecated } from \"../utils/DeprecatedSlots.sol\";\n\ncontract MockGatewayForTracking is HasContracts, HasBridgeTrackingDeprecated {\n constructor(address bridgeTrackingContract) {\n _setContract(ContractType.BRIDGE_TRACKING, bridgeTrackingContract);\n }\n\n function sendBallot(IBridgeTracking.VoteKind kind, uint256 id, address[] memory voters) external {\n IBridgeTracking bridgeTrackingContract = IBridgeTracking(getContract(ContractType.BRIDGE_TRACKING));\n for (uint256 i; i < voters.length; i++) {\n bridgeTrackingContract.recordVote(kind, id, voters[i]);\n }\n }\n\n function sendApprovedVote(IBridgeTracking.VoteKind kind, uint256 id) external {\n IBridgeTracking(getContract(ContractType.BRIDGE_TRACKING)).handleVoteApproved(kind, id);\n }\n}\n" + }, + "contracts/mocks/MockPrecompile.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./libraries/Sorting.sol\";\nimport \"../libraries/Math.sol\";\n\ncontract MockPrecompile {\n function sortValidators(\n address[] memory _validators,\n uint256[] memory _weights\n ) public pure returns (address[] memory) {\n return Sorting.sort(_validators, _weights);\n }\n\n function validatingDoubleSignProof(\n address /*consensusAddr*/,\n bytes calldata /*_header1*/,\n bytes calldata /*_header2*/\n ) public pure returns (bool _validEvidence) {\n return true;\n }\n\n function validateFinalityVoteProof(\n bytes calldata,\n uint256,\n bytes32[2] calldata,\n bytes[][2] calldata,\n bytes[2] calldata\n ) public pure returns (bool) {\n return true;\n }\n\n function pickValidatorSet(\n address[] memory _candidates,\n uint256[] memory _weights,\n uint256[] memory _trustedWeights,\n uint256 _maxValidatorNumber,\n uint256 _maxPrioritizedValidatorNumber\n ) public pure returns (address[] memory _result) {\n (_result, _trustedWeights) = Sorting.sortWithExternalKeys(_candidates, _weights, _trustedWeights);\n uint256 _newValidatorCount = Math.min(_maxValidatorNumber, _result.length);\n _arrangeValidatorCandidates(_result, _trustedWeights, _newValidatorCount, _maxPrioritizedValidatorNumber);\n }\n\n /**\n * @dev Arranges the sorted candidates to list of validators, by asserting prioritized and non-prioritized candidates\n *\n * @param _candidates A sorted list of candidates\n */\n function _arrangeValidatorCandidates(\n address[] memory _candidates,\n uint256[] memory _trustedWeights,\n uint _newValidatorCount,\n uint _maxPrioritizedValidatorNumber\n ) internal pure {\n address[] memory _waitingCandidates = new address[](_candidates.length);\n uint _waitingCounter;\n uint _prioritySlotCounter;\n\n for (uint _i = 0; _i < _candidates.length; _i++) {\n if (_trustedWeights[_i] > 0 && _prioritySlotCounter < _maxPrioritizedValidatorNumber) {\n _candidates[_prioritySlotCounter++] = _candidates[_i];\n continue;\n }\n _waitingCandidates[_waitingCounter++] = _candidates[_i];\n }\n\n _waitingCounter = 0;\n for (uint _i = _prioritySlotCounter; _i < _newValidatorCount; _i++) {\n _candidates[_i] = _waitingCandidates[_waitingCounter++];\n }\n\n assembly {\n mstore(_candidates, _newValidatorCount)\n }\n }\n}\n" + }, + "contracts/mocks/MockSlashIndicatorExtended.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./MockPrecompile.sol\";\nimport \"../ronin/slash-indicator/SlashIndicator.sol\";\nimport \"../interfaces/validator/IRoninValidatorSet.sol\";\n\ncontract MockSlashIndicatorExtended is SlashIndicator, MockPrecompile {\n function slashFelony(address _validatorAddr) external {\n IRoninValidatorSet(getContract(ContractType.VALIDATOR)).execSlash(_validatorAddr, 0, 0, false);\n }\n\n function slashMisdemeanor(address _validatorAddr) external {\n IRoninValidatorSet(getContract(ContractType.VALIDATOR)).execSlash(_validatorAddr, 0, 0, false);\n }\n\n function _pcValidateEvidence(\n address _consensusAddr,\n bytes calldata _header1,\n bytes calldata _header2\n ) internal pure override returns (bool _validEvidence) {\n return validatingDoubleSignProof(_consensusAddr, _header1, _header2);\n }\n}\n" + }, + "contracts/mocks/MockStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../extensions/consumers/GlobalConfigConsumer.sol\";\nimport \"../ronin/staking/RewardCalculation.sol\";\n\ncontract MockStaking is RewardCalculation, GlobalConfigConsumer {\n /// @dev Mapping from user => staking balance\n mapping(address => uint256) internal _stakingAmount;\n /// @dev Mapping from period number => slashed\n mapping(uint256 => bool) internal _periodSlashed;\n\n uint256 internal _stakingTotal;\n\n uint256 public lastUpdatedPeriod;\n uint256 public pendingReward;\n address public poolAddr;\n\n constructor(address _poolAddr) {\n poolAddr = _poolAddr;\n }\n\n function firstEverWrapup() external {\n delete pendingReward;\n lastUpdatedPeriod = block.timestamp / PERIOD_DURATION + 1;\n }\n\n function endPeriod() external {\n address[] memory _addrs = new address[](1);\n uint256[] memory _rewards = new uint256[](1);\n _addrs[0] = poolAddr;\n _rewards[0] = pendingReward;\n this.execRecordRewards(_addrs, _rewards);\n\n pendingReward = 0;\n lastUpdatedPeriod++;\n }\n\n function increasePeriod() external {\n lastUpdatedPeriod++;\n }\n\n function stake(address _user, uint256 _amount) external {\n uint256 _lastStakingAmount = _stakingAmount[_user];\n uint256 _newStakingAmount = _lastStakingAmount + _amount;\n _syncUserReward(poolAddr, _user, _newStakingAmount);\n _stakingAmount[_user] = _newStakingAmount;\n _stakingTotal += _amount;\n }\n\n function unstake(address _user, uint256 _amount) external {\n uint256 _lastStakingAmount = _stakingAmount[_user];\n uint256 _newStakingAmount = _lastStakingAmount - _amount;\n _syncUserReward(poolAddr, _user, _newStakingAmount);\n _stakingAmount[_user] = _newStakingAmount;\n _stakingTotal -= _amount;\n }\n\n function increaseReward(uint256 _amount) external {\n pendingReward += _amount;\n }\n\n function decreaseReward(uint256 _amount) external {\n pendingReward -= _amount;\n }\n\n function execRecordRewards(address[] calldata _addrList, uint256[] calldata _rewards) external {\n _recordRewards(_addrList, _rewards, _currentPeriod());\n }\n\n function getPeriod() public view returns (uint256) {\n return _currentPeriod();\n }\n\n function claimReward(address _user) external returns (uint256 _amount) {\n _amount = _claimReward(poolAddr, _user, getPeriod());\n }\n\n function getStakingAmount(address, address _user) public view override returns (uint256) {\n return _stakingAmount[_user];\n }\n\n function getManyStakingAmounts(\n address[] calldata _poolAddrs,\n address[] calldata _userList\n ) external view override returns (uint256[] memory) {}\n\n function getStakingTotal(address _addr) public view virtual override returns (uint256) {\n return _addr == poolAddr ? _stakingTotal : 0;\n }\n\n function _currentPeriod() internal view override returns (uint256 _period) {\n return lastUpdatedPeriod;\n }\n\n function getManyStakingTotals(address[] calldata _poolAddr) external view override returns (uint256[] memory) {}\n}\n" + }, + "contracts/mocks/MockTransferFallback.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"../extensions/RONTransferHelper.sol\";\n\ncontract MockPaymentFallback {\n event SafeReceived(address indexed sender, uint256 value);\n\n /// @dev Fallback function accepts ether transactions.\n receive() external payable {\n emit SafeReceived(msg.sender, msg.value);\n }\n}\n\ncontract MockPaymentFallbackExpensive {\n uint[] public array;\n event SafeReceived(address indexed sender, uint256 value);\n\n constructor() {\n array.push(0);\n }\n\n /// @dev Fallback function accepts ether transactions and set non-zero value to a zero value slot.\n receive() external payable {\n array.push(block.number);\n emit SafeReceived(msg.sender, msg.value);\n }\n}\n\ncontract MockTransfer is RONTransferHelper {\n uint256 public track;\n\n constructor() payable {}\n\n function fooTransfer(address payable _recipient, uint256 _amount, uint256 _gas) external {\n if (_unsafeSendRONLimitGas(_recipient, _amount, _gas)) {\n track++;\n }\n }\n}\n" + }, + "contracts/mocks/precompile-usages/MockPCUPickValidatorSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../precompile-usages/PCUPickValidatorSet.sol\";\n\ncontract MockPCUPickValidatorSet is PCUPickValidatorSet {\n address internal _precompileSortValidatorAddress;\n\n constructor(address _precompile) {\n setPrecompileSortValidatorAddress(_precompile);\n }\n\n function setPrecompileSortValidatorAddress(address _addr) public {\n _precompileSortValidatorAddress = _addr;\n }\n\n function precompilePickValidatorSetAddress() public view override returns (address) {\n return _precompileSortValidatorAddress;\n }\n\n function callPrecompile(\n address[] memory _candidates,\n uint256[] memory _weights,\n uint256[] memory _trustedWeights,\n uint256 _maxValidatorNumber,\n uint256 _maxPrioritizedValidatorNumber\n ) public view returns (address[] memory _result) {\n (_result, ) = _pcPickValidatorSet(\n _candidates,\n _weights,\n _trustedWeights,\n _maxValidatorNumber,\n _maxPrioritizedValidatorNumber\n );\n }\n}\n" + }, + "contracts/mocks/precompile-usages/MockPCUSortValidators.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../precompile-usages/PCUSortValidators.sol\";\n\ncontract MockPCUSortValidators is PCUSortValidators {\n address internal _precompileSortValidatorAddress;\n\n constructor(address _precompile) {\n setPrecompileSortValidatorAddress(_precompile);\n }\n\n function setPrecompileSortValidatorAddress(address _addr) public {\n _precompileSortValidatorAddress = _addr;\n }\n\n function precompileSortValidatorsAddress() public view override returns (address) {\n return _precompileSortValidatorAddress;\n }\n\n function callPrecompile(\n address[] calldata _validators,\n uint256[] calldata _weights\n ) public view returns (address[] memory _result) {\n return _pcSortCandidates(_validators, _weights);\n }\n}\n" + }, + "contracts/mocks/precompile-usages/MockPCUValidateDoubleSign.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../precompile-usages/PCUValidateDoubleSign.sol\";\n\ncontract MockPCUValidateDoubleSign is PCUValidateDoubleSign {\n address internal _precompileValidateDoubleSignAddress;\n\n constructor(address _precompile) {\n setPrecompileValidateDoubleSignAddress(_precompile);\n }\n\n function setPrecompileValidateDoubleSignAddress(address _addr) public {\n _precompileValidateDoubleSignAddress = _addr;\n }\n\n function precompileValidateDoubleSignAddress() public view override returns (address) {\n return _precompileValidateDoubleSignAddress;\n }\n\n function callPrecompile(\n address _consensusAddr,\n bytes calldata _header1,\n bytes calldata _header2\n ) public view returns (bool) {\n return _pcValidateEvidence(_consensusAddr, _header1, _header2);\n }\n}\n" + }, + "contracts/mocks/precompile-usages/MockPCUValidateFastFinality.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../precompile-usages/PCUValidateFastFinality.sol\";\n\ncontract MockPCUValidateFastFinality is PCUValidateFastFinality {\n address internal _precompileValidateFastFinalityAddress;\n\n constructor(address _precompile) {\n setPrecompileValidateFastFinalityAddress(_precompile);\n }\n\n function setPrecompileValidateFastFinalityAddress(address _addr) public {\n _precompileValidateFastFinalityAddress = _addr;\n }\n\n function precompileValidateFastFinalityAddress() public view override returns (address) {\n return _precompileValidateFastFinalityAddress;\n }\n\n function callPrecompile(\n bytes memory voterPublicKey,\n uint256 targetBlockNumber,\n bytes32[2] memory targetBlockHash,\n bytes[][2] memory listOfPublicKey,\n bytes[2] memory aggregatedSignature\n ) public view returns (bool) {\n return\n _pcValidateFastFinalityEvidence(\n voterPublicKey,\n targetBlockNumber,\n targetBlockHash,\n listOfPublicKey,\n aggregatedSignature\n );\n }\n}\n" + }, + "contracts/mocks/ronin/MockBridgeManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { RoleAccess, ContractType, AddressArrayUtils, IBridgeManager, BridgeManager } from \"../../extensions/bridge-operator-governance/BridgeManager.sol\";\n\ncontract MockBridgeManager is BridgeManager {\n constructor(\n address[] memory bridgeOperators,\n address[] memory governors,\n uint96[] memory voteWeights\n ) payable BridgeManager(0, 0, 0, address(0), _getEmptyAddressArray(), bridgeOperators, governors, voteWeights) {}\n\n function _getEmptyAddressArray() internal pure returns (address[] memory arr) {}\n}\n" + }, + "contracts/mocks/ronin/MockBridgeReward.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IBridgeReward, BridgeReward } from \"../../ronin/gateway/BridgeReward.sol\";\n\ncontract MockBridgeReward is BridgeReward {\n function calcRewardAndCheckSlashedStatus(\n bool isValidTrackingResponse,\n uint256 numBridgeOperators,\n uint256 rewardPerPeriod,\n uint256 ballot,\n uint256 totalBallot,\n uint256 period,\n uint256 slashUntilPeriod\n ) external pure returns (uint256 reward, bool isSlashed) {\n return\n _calcRewardAndCheckSlashedStatus(\n isValidTrackingResponse,\n numBridgeOperators,\n rewardPerPeriod,\n ballot,\n totalBallot,\n period,\n slashUntilPeriod\n );\n }\n\n function calcReward(\n bool isValidTrackingResponse,\n uint256 numBridgeOperators,\n uint256 rewardPerPeriod,\n uint256 ballot,\n uint256 totalBallot\n ) external pure returns (uint256 reward) {\n reward = _calcReward(isValidTrackingResponse, numBridgeOperators, rewardPerPeriod, ballot, totalBallot);\n }\n\n function isValidBridgeTrackingResponse(\n uint256 totalBallot,\n uint256 totalVote,\n uint256[] memory ballots\n ) external pure returns (bool valid) {\n return _isValidBridgeTrackingResponse(totalBallot, totalVote, ballots);\n }\n\n function shouldShareEqually(\n uint256 totalBallot,\n uint256 totalVote,\n uint256[] memory ballots\n ) external returns (bool shareEqually) {\n return _shouldShareEqually(totalBallot, totalVote, ballots);\n }\n\n function shouldSlashedThisPeriod(uint256 period, uint256 slashUntilDuration) external pure returns (bool) {\n return _shouldSlashedThisPeriod(period, slashUntilDuration);\n }\n}\n" + }, + "contracts/mocks/ronin/MockBridgeSlash.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IBridgeSlash, BridgeSlash } from \"../../ronin/gateway/BridgeSlash.sol\";\n\ncontract MockBridgeSlash is BridgeSlash {\n function calcSlashUntilPeriod(\n Tier tier,\n uint256 period,\n uint256 slashUntilPeriod\n ) external pure returns (uint256 newSlashUntilPeriod) {\n newSlashUntilPeriod = _calcSlashUntilPeriod(tier, period, slashUntilPeriod, _getPenaltyDurations());\n }\n\n function isSlashDurationMetRemovalThreshold(uint256 slashUntilPeriod, uint256 period) external pure returns (bool) {\n return _isSlashDurationMetRemovalThreshold(slashUntilPeriod, period);\n }\n}\n" + }, + "contracts/mocks/ronin/MockBridgeTracking.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n" + }, + "contracts/mocks/ronin/MockRoninBridgeManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { RoninBridgeManager } from \"../../ronin/gateway/RoninBridgeManager.sol\";\nimport { GlobalProposal } from \"../../extensions/sequential-governance/governance-proposal/GovernanceProposal.sol\";\n\ncontract MockRoninBridgeManager is RoninBridgeManager {\n constructor(\n uint256 num,\n uint256 denom,\n uint256 roninChainId,\n uint256 expiryDuration,\n address bridgeContract,\n address[] memory callbackRegisters,\n address[] memory bridgeOperators,\n address[] memory governors,\n uint96[] memory voteWeights,\n GlobalProposal.TargetOption[] memory targetOptions,\n address[] memory targets\n )\n RoninBridgeManager(\n num,\n denom,\n roninChainId,\n expiryDuration,\n bridgeContract,\n callbackRegisters,\n bridgeOperators,\n governors,\n voteWeights,\n targetOptions,\n targets\n )\n {}\n}\n" + }, + "contracts/mocks/ronin/MockRoninGatewayV2Extended.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../../ronin/gateway/RoninGatewayV2.sol\";\n\ncontract MockRoninGatewayV2Extended is RoninGatewayV2 {\n /*\n * @dev Returns the vote weight for a deposit based on its corressponding hash.\n */\n function getDepositVoteWeight(\n uint256 _chainId,\n uint256 _depositId,\n bytes32 _hash\n ) external view returns (uint256 totalWeight) {\n totalWeight = _getVoteWeight(depositVote[_chainId][_depositId], _hash);\n }\n\n /**\n * @dev Returns the vote weight for a mainchain withdrew acknowledgement based on its corressponding hash.\n */\n function getMainchainWithdrewVoteWeight(\n uint256 _withdrawalId,\n bytes32 _hash\n ) external view returns (uint256 totalWeight) {\n totalWeight = _getVoteWeight(mainchainWithdrewVote[_withdrawalId], _hash);\n }\n\n /**\n * @dev Returns the vote weight for a withdraw stats based on its corressponding hash.\n */\n function getWithdrawalStatVoteWeight(\n uint256 _withdrawalId,\n bytes32 _hash\n ) external view returns (uint256 totalWeight) {\n totalWeight = _getVoteWeight(withdrawalStatVote[_withdrawalId], _hash);\n }\n}\n" + }, + "contracts/mocks/ronin/MockValidatorContract.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ncontract MockValidatorContract {\n uint256 private _currentPeriod;\n\n function currentPeriod() external view returns (uint256) {\n return _currentPeriod;\n }\n\n function setCurrentPeriod(uint256 period) external {\n _currentPeriod = period;\n }\n}\n" + }, + "contracts/mocks/sorting/MockSorting.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol\";\nimport \"../libraries/Sorting.sol\";\n\ncontract MockSorting {\n uint256[] public data;\n\n function addData(uint256[] memory _data) public {\n for (uint256 i; i < _data.length; i++) {\n data.push(_data[i]);\n }\n }\n\n function sort(uint256[] memory _data) public pure returns (uint256[] memory) {\n return Sorting.sort(_data);\n }\n\n function sortOnStorage() public returns (uint256[] memory, uint256) {\n uint256[] memory _tmpData = data;\n data = Sorting.sort(_tmpData);\n\n return (data, data.length);\n }\n\n function sortAddressesAndValues(\n address[] calldata _addrs,\n uint256[] calldata _values\n ) public pure returns (address[] memory) {\n return Sorting.sort(_addrs, _values);\n }\n}\n" + }, + "contracts/mocks/types/MockTUint256Slot.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { TUint256Slot } from \"../../types/Types.sol\";\n\ncontract MockTUint256Slot {\n TUint256Slot private constant CUSTOM_SLOT_UINT256 =\n TUint256Slot.wrap(keccak256(abi.encode(type(MockTUint256Slot).name)));\n\n uint256 private _primitiveUint256;\n\n function subPrimitive(uint256 val) external view returns (uint256 res) {\n res = _primitiveUint256 - val;\n }\n\n function subCustomSlot(uint256 val) external view returns (uint256 res) {\n res = CUSTOM_SLOT_UINT256.sub(val);\n }\n\n function divCustomSlot(uint256 val) external view returns (uint256 res) {\n res = CUSTOM_SLOT_UINT256.div(val);\n }\n\n function divPrimitive(uint256 val) external view returns (uint256 res) {\n res = _primitiveUint256 / val;\n }\n\n function mulCustomSlot(uint256 val) external view returns (uint256 res) {\n res = CUSTOM_SLOT_UINT256.mul(val);\n }\n\n function mulPrimitive(uint256 val) external view returns (uint256 res) {\n res = _primitiveUint256 * val;\n }\n\n function addPrimitive(uint256 val) external view returns (uint256 res) {\n res = _primitiveUint256 + val;\n }\n\n function addCustomSlot(uint256 val) external view returns (uint256 res) {\n res = CUSTOM_SLOT_UINT256.add(val);\n }\n\n function preIncrementPrimitive() external returns (uint256 res) {\n res = ++_primitiveUint256;\n }\n\n function preIncrementCustomSlot() external returns (uint256 res) {\n res = CUSTOM_SLOT_UINT256.preIncrement();\n }\n\n function postIncrementPrimitive() external returns (uint256 res) {\n res = _primitiveUint256++;\n }\n\n function postIncrementCustomSlot() external returns (uint256 res) {\n res = CUSTOM_SLOT_UINT256.postIncrement();\n }\n\n function preDecrementPrimitive() external returns (uint256 res) {\n res = --_primitiveUint256;\n }\n\n function preDecrementCustomSlot() external returns (uint256 res) {\n res = CUSTOM_SLOT_UINT256.preDecrement();\n }\n\n function postDecrementPrimitive() external returns (uint256 res) {\n res = _primitiveUint256--;\n }\n\n function postDecrementCustomSlot() external returns (uint256 res) {\n res = CUSTOM_SLOT_UINT256.postDecrement();\n }\n\n function setCustomSlot(uint256 val) external returns (uint256 stored) {\n CUSTOM_SLOT_UINT256.store(val);\n stored = CUSTOM_SLOT_UINT256.load();\n }\n\n function setPrimitive(uint256 val) external returns (uint256 stored) {\n _primitiveUint256 = val;\n stored = _primitiveUint256;\n }\n\n function subAssignCustomSlot(uint256 val) external returns (uint256 stored) {\n stored = CUSTOM_SLOT_UINT256.subAssign(val);\n }\n\n function subAssignPrimitive(uint256 val) external returns (uint256 stored) {\n stored = _primitiveUint256 -= val;\n }\n\n function addAssignCustomSlot(uint256 val) external returns (uint256 stored) {\n stored = CUSTOM_SLOT_UINT256.addAssign(val);\n }\n\n function addAssignPrimitive(uint256 val) external returns (uint256 stored) {\n stored = _primitiveUint256 += val;\n }\n\n function getPrimitive() external view returns (uint256) {\n return _primitiveUint256;\n }\n\n function getCustomSlot() external view returns (uint256) {\n return CUSTOM_SLOT_UINT256.load();\n }\n}\n" + }, + "contracts/mocks/utils/version-control/MockActor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ErrorHandler } from \"../../../libraries/ErrorHandler.sol\";\n\ncontract MockActor {\n using ErrorHandler for bool;\n\n address private _target;\n\n constructor(address target) {\n _target = target;\n }\n\n fallback() external payable {\n (bool success, bytes memory returnOrRevertData) = _target.call{ value: msg.value }(msg.data);\n success.handleRevert(msg.sig, returnOrRevertData);\n assembly {\n return(add(returnOrRevertData, 0x20), mload(returnOrRevertData))\n }\n }\n}\n" + }, + "contracts/mocks/utils/version-control/MockConditionalImplementControl.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ConditionalImplementControl } from \"../../../extensions/version-control/ConditionalImplementControl.sol\";\n\ncontract MockConditionalImplementControl is ConditionalImplementControl {\n uint256 public immutable UPGRADED_AT_BLOCK;\n\n constructor(\n address proxyStorage,\n address prevImpl,\n address newImpl,\n uint256 upgradedAtBlock\n ) ConditionalImplementControl(proxyStorage, prevImpl, newImpl) {\n UPGRADED_AT_BLOCK = upgradedAtBlock;\n }\n\n function _isConditionMet() internal view override returns (bool) {\n return block.number >= UPGRADED_AT_BLOCK;\n }\n}\n" + }, + "contracts/mocks/utils/version-control/MockLogic.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ILogic {\n event Received(uint256 version);\n\n function name() external pure returns (string memory);\n\n function magicNumber() external view returns (uint256);\n\n function get() external view returns (uint256);\n\n function set() external;\n\n function setAndGet() external returns (uint256);\n}\n\nabstract contract MockLogicBase is ILogic {\n uint256 internal _value;\n\n function magicNumber() public view virtual override returns (uint256) {}\n\n receive() external payable virtual {\n emit Received(0);\n }\n\n function get() public view returns (uint256) {\n return _value;\n }\n\n function set() public override {\n _value = magicNumber();\n }\n\n function setAndGet() public returns (uint256) {\n set();\n return get();\n }\n}\n\ncontract MockLogicV1 is MockLogicBase {\n receive() external payable override {\n emit Received(1);\n }\n\n function name() external pure returns (string memory) {\n return \"LogicV1\";\n }\n\n function magicNumber() public pure override returns (uint256) {\n return 1;\n }\n}\n\ncontract MockLogicV2 is MockLogicBase {\n receive() external payable override {\n emit Received(2);\n }\n\n function name() external pure returns (string memory) {\n return \"LogicV2\";\n }\n\n function magicNumber() public pure override returns (uint256) {\n return 2;\n }\n}\n" + }, + "contracts/mocks/utils/version-control/MockLogicValidatorSet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ILogicValidatorSet {\n event Received(string version);\n\n function wrapUpEpoch() external payable;\n\n function version() external view returns (string memory);\n\n function currentPeriod() external view returns (uint256);\n}\n\nabstract contract MockLogicValidatorSetCore is ILogicValidatorSet {\n uint256 private _lastUpdatedPeriod;\n\n receive() external payable virtual {\n emit Received(\"0\");\n }\n\n function wrapUpEpoch() external payable {\n if (block.number % 100 == 0) {\n _lastUpdatedPeriod += 1;\n }\n }\n\n function currentPeriod() external view returns (uint256) {\n return _lastUpdatedPeriod;\n }\n}\n\ncontract MockLogicValidatorSetV1 is MockLogicValidatorSetCore {\n receive() external payable override {\n emit Received(version());\n }\n\n function version() public pure returns (string memory) {\n return \"V1\";\n }\n}\n\ncontract MockLogicValidatorSetV2 is MockLogicValidatorSetCore {\n receive() external payable override {\n emit Received(version());\n }\n\n function version() public pure returns (string memory) {\n return \"V2\";\n }\n}\n" + }, + "contracts/mocks/validator/MockRoninValidatorSetExtended.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./MockRoninValidatorSetOverridePrecompile.sol\";\nimport \"../../libraries/EnumFlags.sol\";\n\ncontract MockRoninValidatorSetExtended is MockRoninValidatorSetOverridePrecompile {\n bool private _initialized;\n uint256[] internal _epochs;\n\n constructor() {}\n\n function initEpoch() public {\n if (!_initialized) {\n _epochs.push(0);\n _initialized = true;\n }\n }\n\n function endEpoch() external {\n _epochs.push(block.number);\n }\n\n function epochOf(uint256 _block) public view override returns (uint256 _epoch) {\n for (uint256 _i = _epochs.length; _i > 0; _i--) {\n if (_block > _epochs[_i - 1]) {\n return _i;\n }\n }\n }\n\n function epochEndingAt(uint256 _block) public view override(ITimingInfo, TimingStorage) returns (bool) {\n for (uint _i = 0; _i < _epochs.length; _i++) {\n if (_block == _epochs[_i]) {\n return true;\n }\n }\n return false;\n }\n\n function getJailUntils(address[] calldata _addrs) public view returns (uint256[] memory jailUntils_) {\n jailUntils_ = new uint256[](_addrs.length);\n for (uint _i = 0; _i < _addrs.length; _i++) {\n jailUntils_[_i] = _blockProducerJailedBlock[_addrs[_i]];\n }\n }\n\n function addValidators(address[] calldata _addrs) public {\n for (uint _i = 0; _i < _addrs.length; _i++) {\n _validators[_i] = _addrs[_i];\n _validatorMap[_addrs[_i]] = EnumFlags.ValidatorFlag.Both;\n }\n }\n}\n" + }, + "contracts/mocks/validator/MockRoninValidatorSetOverridePrecompile.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../MockPrecompile.sol\";\nimport \"../../ronin/validator/RoninValidatorSet.sol\";\n\ncontract MockRoninValidatorSetOverridePrecompile is RoninValidatorSet, MockPrecompile {\n constructor() {}\n\n function arrangeValidatorCandidates(\n address[] memory _candidates,\n uint256[] memory _trustedWeights,\n uint _newValidatorCount,\n uint _maxPrioritizedValidatorNumber\n ) external pure returns (address[] memory) {\n _arrangeValidatorCandidates(_candidates, _trustedWeights, _newValidatorCount, _maxPrioritizedValidatorNumber);\n return _candidates;\n }\n\n function _pcSortCandidates(\n address[] memory _candidates,\n uint256[] memory _weights\n ) internal pure override returns (address[] memory _result) {\n return sortValidators(_candidates, _weights);\n }\n\n function _pcPickValidatorSet(\n address[] memory _candidates,\n uint256[] memory _weights,\n uint256[] memory _trustedWeights,\n uint256 _maxValidatorNumber,\n uint256 _maxPrioritizedValidatorNumber\n ) internal pure override returns (address[] memory _result, uint256 _newValidatorCount) {\n _result = pickValidatorSet(\n _candidates,\n _weights,\n _trustedWeights,\n _maxValidatorNumber,\n _maxPrioritizedValidatorNumber\n );\n\n _newValidatorCount = _result.length;\n }\n}\n" + }, + "contracts/mocks/validator/MockValidatorSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../ronin/validator/CandidateManager.sol\";\nimport { HasStakingVestingDeprecated, HasSlashIndicatorDeprecated } from \"../../utils/DeprecatedSlots.sol\";\n\ncontract MockValidatorSet is\n IRoninValidatorSet,\n CandidateManager,\n HasStakingVestingDeprecated,\n HasSlashIndicatorDeprecated\n{\n uint256 internal _lastUpdatedPeriod;\n uint256 internal _numberOfBlocksInEpoch;\n /// @dev Mapping from period number => slashed\n mapping(uint256 => bool) internal _periodSlashed;\n\n constructor(\n address __stakingContract,\n address _slashIndicatorContract,\n address _stakingVestingContract,\n uint256 __maxValidatorCandidate,\n uint256 __numberOfBlocksInEpoch,\n uint256 __minEffectiveDaysOnwards\n ) {\n _setContract(ContractType.STAKING, __stakingContract);\n _setContract(ContractType.SLASH_INDICATOR, _slashIndicatorContract);\n _setContract(ContractType.STAKING_VESTING, _stakingVestingContract);\n _setMaxValidatorCandidate(__maxValidatorCandidate);\n _numberOfBlocksInEpoch = __numberOfBlocksInEpoch;\n _minEffectiveDaysOnwards = __minEffectiveDaysOnwards;\n }\n\n function submitBlockReward() external payable override {}\n\n function wrapUpEpoch() external payable override {\n _syncCandidateSet(_lastUpdatedPeriod + 1);\n _lastUpdatedPeriod = currentPeriod();\n }\n\n function getLastUpdatedBlock() external view override returns (uint256) {}\n\n function checkManyJailed(address[] calldata) external view override returns (bool[] memory) {}\n\n function checkMiningRewardDeprecatedAtPeriod(address, uint256 _period) external view override returns (bool) {}\n\n function checkMiningRewardDeprecated(address) external view override returns (bool) {}\n\n function checkBridgeRewardDeprecatedAtPeriod(\n address _consensusAddr,\n uint256 _period\n ) external view returns (bool _result) {}\n\n function epochOf(uint256 _block) external view override returns (uint256) {}\n\n function getValidators() external view override returns (address[] memory) {}\n\n function epochEndingAt(uint256 _block) external view override returns (bool) {}\n\n function execSlash(\n address validatorAddr,\n uint256 newJailedUntil,\n uint256 slashAmount,\n bool cannotBailout\n ) external override {}\n\n function execBailOut(address, uint256) external override {}\n\n function setMaxValidatorNumber(uint256 _maxValidatorNumber) external override {}\n\n function setMaxPrioritizedValidatorNumber(uint256 _maxPrioritizedValidatorNumber) external override {}\n\n function maxValidatorNumber() external view override returns (uint256 _maximumValidatorNumber) {}\n\n function maxPrioritizedValidatorNumber()\n external\n view\n override\n returns (uint256 _maximumPrioritizedValidatorNumber)\n {}\n\n function numberOfBlocksInEpoch() public view override returns (uint256) {\n return _numberOfBlocksInEpoch;\n }\n\n function getBlockProducers() external view override returns (address[] memory) {}\n\n function isBlockProducer(address) external pure override returns (bool) {\n return true;\n }\n\n function totalBlockProducer() external view override returns (uint256) {}\n\n function tryGetPeriodOfEpoch(uint256) external view returns (bool, uint256) {}\n\n function isPeriodEnding() public view virtual returns (bool) {\n return currentPeriod() > _lastUpdatedPeriod;\n }\n\n function currentPeriod() public view override returns (uint256) {\n return block.timestamp / 86400;\n }\n\n function checkJailed(address) external view override returns (bool) {}\n\n function getJailedTimeLeft(address) external view override returns (bool, uint256, uint256) {}\n\n function currentPeriodStartAtBlock() external view override returns (uint256) {}\n\n function checkJailedAtBlock(address _addr, uint256 _blockNum) external view override returns (bool) {}\n\n function getJailedTimeLeftAtBlock(\n address _addr,\n uint256 _blockNum\n ) external view override returns (bool isJailed_, uint256 blockLeft_, uint256 epochLeft_) {}\n\n function totalDeprecatedReward() external view override returns (uint256) {}\n\n function execReleaseLockedFundForEmergencyExitRequest(\n address _consensusAddr,\n address payable _recipient\n ) external override {}\n\n function emergencyExitLockedAmount() external override returns (uint256) {}\n\n function emergencyExpiryDuration() external override returns (uint256) {}\n\n function setEmergencyExitLockedAmount(uint256 _emergencyExitLockedAmount) external override {}\n\n function setEmergencyExpiryDuration(uint256 _emergencyExpiryDuration) external override {}\n\n function getEmergencyExitInfo(address _consensusAddr) external view override returns (EmergencyExitInfo memory) {}\n\n function execEmergencyExit(address, uint256) external {}\n\n function isOperatingBridge(address) external view returns (bool) {}\n\n function _emergencyExitLockedFundReleased(address _consensusAddr) internal virtual override returns (bool) {}\n\n function _isTrustedOrg(address _consensusAddr) internal virtual override returns (bool) {}\n}\n" + }, + "contracts/multi-chains/RoninTrustedOrganization.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../libraries/AddressArrayUtils.sol\";\nimport \"../interfaces/IRoninTrustedOrganization.sol\";\nimport \"../extensions/collections/HasProxyAdmin.sol\";\n\ncontract RoninTrustedOrganization is IRoninTrustedOrganization, HasProxyAdmin, Initializable {\n uint256 internal _num;\n uint256 internal _denom;\n uint256 internal _totalWeight;\n uint256 internal _nonce;\n\n /// @dev Mapping from consensus address => weight\n mapping(address => uint256) internal _consensusWeight;\n /// @dev Mapping from governor address => weight\n mapping(address => uint256) internal _governorWeight;\n /// @dev Mapping from bridge voter address => weight\n mapping(address => uint256) internal _bridgeVoterWeight;\n\n /// @dev Mapping from consensus address => added block\n mapping(address => uint256) internal _addedBlock;\n\n /// @dev Consensus array\n address[] internal _consensusList;\n /// @dev Governors array\n address[] internal _governorList;\n /// @dev Bridge voters array\n address[] internal _bridgeVoterList;\n\n /**\n * @dev Initializes the contract storage.\n */\n function initialize(\n TrustedOrganization[] calldata _trustedOrgs,\n uint256 __num,\n uint256 __denom\n ) external initializer {\n if (_trustedOrgs.length > 0) {\n _addTrustedOrganizations(_trustedOrgs);\n }\n _setThreshold(__num, __denom);\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function getThreshold() external view virtual returns (uint256 num_, uint256 denom_) {\n return (_num, _denom);\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function checkThreshold(uint256 _voteWeight) external view virtual returns (bool) {\n return _voteWeight * _denom >= _num * _totalWeight;\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function minimumVoteWeight() external view virtual returns (uint256) {\n return (_num * _totalWeight + _denom - 1) / _denom;\n }\n\n /**\n * @inheritdoc IQuorum\n */\n function setThreshold(\n uint256 _numerator,\n uint256 _denominator\n ) external override onlyAdmin returns (uint256, uint256) {\n return _setThreshold(_numerator, _denominator);\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function addTrustedOrganizations(TrustedOrganization[] calldata _list) external override onlyAdmin {\n _addTrustedOrganizations(_list);\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function updateTrustedOrganizations(TrustedOrganization[] calldata _list) external override onlyAdmin {\n if (_list.length == 0) revert ErrEmptyArray();\n for (uint256 _i; _i < _list.length; ) {\n _updateTrustedOrganization(_list[_i]);\n\n unchecked {\n ++_i;\n }\n }\n emit TrustedOrganizationsUpdated(_list);\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function removeTrustedOrganizations(address[] calldata _list) external override onlyAdmin {\n if (_list.length == 0) revert ErrEmptyArray();\n\n for (uint _i = 0; _i < _list.length; ) {\n _removeTrustedOrganization(_list[_i]);\n\n unchecked {\n ++_i;\n }\n }\n emit TrustedOrganizationsRemoved(_list);\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function totalWeight() external view virtual returns (uint256) {\n return _totalWeight;\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getConsensusWeight(address _consensusAddr) external view returns (uint256) {\n return _consensusWeight[_consensusAddr];\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getGovernorWeight(address _governor) external view returns (uint256) {\n return _governorWeight[_governor];\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getBridgeVoterWeight(address _addr) external view returns (uint256) {\n return _bridgeVoterWeight[_addr];\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getConsensusWeights(address[] calldata _list) external view returns (uint256[] memory _res) {\n _res = new uint256[](_list.length);\n for (uint _i = 0; _i < _res.length; ) {\n _res[_i] = _consensusWeight[_list[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getGovernorWeights(address[] calldata _list) external view returns (uint256[] memory _res) {\n _res = new uint256[](_list.length);\n for (uint _i = 0; _i < _res.length; ) {\n _res[_i] = _governorWeight[_list[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getBridgeVoterWeights(address[] calldata _list) external view returns (uint256[] memory _res) {\n _res = new uint256[](_list.length);\n for (uint _i = 0; _i < _res.length; ) {\n _res[_i] = _bridgeVoterWeight[_list[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function sumConsensusWeight(address[] calldata _list) external view returns (uint256 _res) {\n for (uint _i = 0; _i < _list.length; ) {\n _res += _consensusWeight[_list[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function sumGovernorWeight(address[] calldata _list) external view returns (uint256 _res) {\n for (uint _i = 0; _i < _list.length; ) {\n _res += _governorWeight[_list[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function sumBridgeVoterWeight(address[] calldata _list) external view returns (uint256 _res) {\n for (uint _i = 0; _i < _list.length; ) {\n _res += _bridgeVoterWeight[_list[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function countTrustedOrganization() external view override returns (uint256) {\n return _consensusList.length;\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getAllTrustedOrganizations() external view override returns (TrustedOrganization[] memory _list) {\n _list = new TrustedOrganization[](_consensusList.length);\n address _addr;\n for (uint256 _i; _i < _list.length; ) {\n _addr = _consensusList[_i];\n _list[_i].consensusAddr = _addr;\n _list[_i].governor = _governorList[_i];\n _list[_i].bridgeVoter = _bridgeVoterList[_i];\n _list[_i].weight = _consensusWeight[_addr];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getTrustedOrganization(address _consensusAddr) external view returns (TrustedOrganization memory) {\n for (uint _i = 0; _i < _consensusList.length; ) {\n if (_consensusList[_i] == _consensusAddr) {\n return getTrustedOrganizationAt(_i);\n }\n\n unchecked {\n ++_i;\n }\n }\n revert ErrQueryForNonExistentConsensusAddress();\n }\n\n /**\n * @inheritdoc IRoninTrustedOrganization\n */\n function getTrustedOrganizationAt(uint256 _idx) public view override returns (TrustedOrganization memory) {\n address _addr = _consensusList[_idx];\n return\n TrustedOrganization(\n _addr,\n _governorList[_idx],\n _bridgeVoterList[_idx],\n _consensusWeight[_addr],\n _addedBlock[_addr]\n );\n }\n\n /**\n * @dev Adds a list of trusted organizations.\n */\n function _addTrustedOrganizations(TrustedOrganization[] calldata _list) internal virtual {\n for (uint256 _i; _i < _list.length; ) {\n _addTrustedOrganization(_list[_i]);\n\n unchecked {\n ++_i;\n }\n }\n emit TrustedOrganizationsAdded(_list);\n }\n\n /**\n * @dev Adds a trusted organization.\n *\n * Requirements:\n * - The weight is larger than 0.\n * - The consensus address is not added.\n * - The govenor address is not added.\n * - The bridge voter address is not added.\n *\n */\n function _addTrustedOrganization(TrustedOrganization memory _v) internal virtual {\n if (_v.addedBlock != 0) revert ErrInvalidRequest();\n _sanityCheckTrustedOrganizationData(_v);\n\n if (_consensusWeight[_v.consensusAddr] > 0) revert ErrConsensusAddressIsAlreadyAdded(_v.consensusAddr);\n\n if (_governorWeight[_v.governor] > 0) revert ErrGovernorAddressIsAlreadyAdded(_v.governor);\n\n if (_bridgeVoterWeight[_v.bridgeVoter] > 0) revert ErrBridgeVoterIsAlreadyAdded(_v.bridgeVoter);\n\n _consensusList.push(_v.consensusAddr);\n _consensusWeight[_v.consensusAddr] = _v.weight;\n\n _governorList.push(_v.governor);\n _governorWeight[_v.governor] = _v.weight;\n\n _bridgeVoterList.push(_v.bridgeVoter);\n _bridgeVoterWeight[_v.bridgeVoter] = _v.weight;\n\n _addedBlock[_v.consensusAddr] = block.number;\n\n _totalWeight += _v.weight;\n }\n\n /**\n * @dev Updates a trusted organization.\n *\n * Requirements:\n * - The weight is larger than 0.\n * - The consensus address is already added.\n *\n */\n function _updateTrustedOrganization(TrustedOrganization memory _v) internal virtual {\n _sanityCheckTrustedOrganizationData(_v);\n\n uint256 _weight = _consensusWeight[_v.consensusAddr];\n if (_weight == 0) revert ErrConsensusAddressIsNotAdded(_v.consensusAddr);\n\n uint256 _count = _consensusList.length;\n for (uint256 _i = 0; _i < _count; ) {\n if (_consensusList[_i] == _v.consensusAddr) {\n _totalWeight -= _weight;\n _totalWeight += _v.weight;\n\n if (_governorList[_i] != _v.governor) {\n if (_governorWeight[_v.governor] != 0) revert ErrQueryForDupplicated();\n\n delete _governorWeight[_governorList[_i]];\n _governorList[_i] = _v.governor;\n }\n\n if (_bridgeVoterList[_i] != _v.bridgeVoter) {\n if (_bridgeVoterWeight[_v.bridgeVoter] != 0) revert ErrQueryForDupplicated();\n\n delete _bridgeVoterWeight[_bridgeVoterList[_i]];\n _bridgeVoterList[_i] = _v.bridgeVoter;\n }\n\n _consensusWeight[_v.consensusAddr] = _v.weight;\n _governorWeight[_v.governor] = _v.weight;\n _bridgeVoterWeight[_v.bridgeVoter] = _v.weight;\n return;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @dev Removes a trusted organization.\n *\n * Requirements:\n * - The consensus address is added.\n *\n */\n function _removeTrustedOrganization(address _addr) internal virtual {\n uint256 _weight = _consensusWeight[_addr];\n if (_weight == 0) revert ErrConsensusAddressIsNotAdded(_addr);\n\n uint256 _index;\n uint256 _count = _consensusList.length;\n for (uint256 _i = 0; _i < _count; ) {\n if (_consensusList[_i] == _addr) {\n _index = _i;\n break;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n _totalWeight -= _weight;\n\n delete _addedBlock[_addr];\n delete _consensusWeight[_addr];\n _consensusList[_index] = _consensusList[_count - 1];\n _consensusList.pop();\n\n delete _governorWeight[_governorList[_index]];\n _governorList[_index] = _governorList[_count - 1];\n _governorList.pop();\n\n delete _bridgeVoterWeight[_bridgeVoterList[_index]];\n _bridgeVoterList[_index] = _bridgeVoterList[_count - 1];\n _bridgeVoterList.pop();\n }\n\n /**\n * @dev Sets threshold and returns the old one.\n *\n * Emits the `ThresholdUpdated` event.\n *\n */\n function _setThreshold(\n uint256 _numerator,\n uint256 _denominator\n ) internal virtual returns (uint256 _previousNum, uint256 _previousDenom) {\n if (_numerator > _denominator) revert ErrInvalidThreshold(msg.sig);\n\n _previousNum = _num;\n _previousDenom = _denom;\n _num = _numerator;\n _denom = _denominator;\n unchecked {\n emit ThresholdUpdated(_nonce++, _numerator, _denominator, _previousNum, _previousDenom);\n }\n }\n\n /**\n * @dev Hook that checks trusted organization's data. Reverts if the requirements are not met.\n *\n * Requirements:\n * - The weight must be larger than 0.\n * - The consensus address, governor address, and bridge voter address are different.\n */\n function _sanityCheckTrustedOrganizationData(TrustedOrganization memory _v) private pure {\n if (_v.weight == 0) revert ErrInvalidVoteWeight(msg.sig);\n\n address[] memory _addresses = new address[](3);\n _addresses[0] = _v.consensusAddr;\n _addresses[1] = _v.governor;\n _addresses[2] = _v.bridgeVoter;\n\n if (AddressArrayUtils.hasDuplicate(_addresses)) revert AddressArrayUtils.ErrDuplicated(msg.sig);\n }\n}\n" + }, + "contracts/precompile-usages/PCUPickValidatorSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./PrecompiledUsage.sol\";\n\nabstract contract PCUPickValidatorSet is PrecompiledUsage {\n /// @dev Gets the address of the precompile of picking validator set\n function precompilePickValidatorSetAddress() public view virtual returns (address) {\n return address(0x68);\n }\n\n /**\n * @dev Sorts and arranges to return a new validator set.\n *\n * Note: The recover process is done by pre-compiled contract. This function is marked as\n * virtual for implementing mocking contract for testing purpose.\n */\n function _pcPickValidatorSet(\n address[] memory _candidates,\n uint256[] memory _weights,\n uint256[] memory _trustedWeights,\n uint256 _maxValidatorNumber,\n uint256 _maxPrioritizedValidatorNumber\n ) internal view virtual returns (address[] memory _result, uint256 _newValidatorCount) {\n address _smc = precompilePickValidatorSetAddress();\n bytes memory _payload = abi.encodeWithSignature(\n \"pickValidatorSet(address[],uint256[],uint256[],uint256,uint256)\",\n _candidates,\n _weights,\n _trustedWeights,\n _maxValidatorNumber,\n _maxPrioritizedValidatorNumber\n );\n bool _success = true;\n\n uint256 _payloadLength = _payload.length;\n uint256 _resultLength = 0x20 * _candidates.length + 0x40;\n\n assembly {\n let _payloadStart := add(_payload, 0x20)\n\n if iszero(staticcall(gas(), _smc, _payloadStart, _payloadLength, _result, _resultLength)) {\n _success := 0\n }\n\n if iszero(returndatasize()) {\n _success := 0\n }\n\n _result := add(_result, 0x20)\n }\n\n if (!_success) revert ErrCallPrecompiled();\n\n _newValidatorCount = _result.length;\n }\n}\n" + }, + "contracts/precompile-usages/PCUSortValidators.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./PrecompiledUsage.sol\";\n\nabstract contract PCUSortValidators is PrecompiledUsage {\n /// @dev Gets the address of the precompile of sorting validators\n function precompileSortValidatorsAddress() public view virtual returns (address) {\n return address(0x66);\n }\n\n /**\n * @dev Sorts candidates descending by their weights by calling precompile contract.\n *\n * Note: This function is marked as virtual for being wrapping in mock contract for testing purpose.\n */\n function _pcSortCandidates(\n address[] memory _candidates,\n uint256[] memory _weights\n ) internal view virtual returns (address[] memory _result) {\n address _smc = precompileSortValidatorsAddress();\n bool _success = true;\n\n bytes memory _payload = abi.encodeWithSignature(\"sortValidators(address[],uint256[])\", _candidates, _weights);\n uint256 _payloadLength = _payload.length;\n uint256 _resultLength = 0x20 * _candidates.length + 0x40;\n\n assembly {\n let _payloadStart := add(_payload, 0x20)\n\n if iszero(staticcall(gas(), _smc, _payloadStart, _payloadLength, _result, _resultLength)) {\n _success := 0\n }\n\n if iszero(returndatasize()) {\n _success := 0\n }\n\n _result := add(_result, 0x20)\n }\n\n if (!_success) revert ErrCallPrecompiled();\n }\n}\n" + }, + "contracts/precompile-usages/PCUValidateDoubleSign.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./PrecompiledUsage.sol\";\n\nabstract contract PCUValidateDoubleSign is PrecompiledUsage {\n /// @dev Gets the address of the precompile of validating double sign evidence\n function precompileValidateDoubleSignAddress() public view virtual returns (address) {\n return address(0x67);\n }\n\n /**\n * @dev Validates the two submitted block header if they are produced by the same address\n *\n * Note: The recover process is done by pre-compiled contract. This function is marked as\n * virtual for implementing mocking contract for testing purpose.\n */\n function _pcValidateEvidence(\n address _consensusAddr,\n bytes calldata _header1,\n bytes calldata _header2\n ) internal view virtual returns (bool _validEvidence) {\n address _smc = precompileValidateDoubleSignAddress();\n bool _success = true;\n\n bytes memory _payload = abi.encodeWithSignature(\n \"validatingDoubleSignProof(address,bytes,bytes)\",\n _consensusAddr,\n _header1,\n _header2\n );\n uint _payloadLength = _payload.length;\n uint[1] memory _output;\n\n assembly {\n let _payloadStart := add(_payload, 0x20)\n if iszero(staticcall(gas(), _smc, _payloadStart, _payloadLength, _output, 0x20)) {\n _success := 0\n }\n\n if iszero(returndatasize()) {\n _success := 0\n }\n }\n\n if (!_success) revert ErrCallPrecompiled();\n return (_output[0] != 0);\n }\n}\n" + }, + "contracts/precompile-usages/PCUValidateFastFinality.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./PrecompiledUsage.sol\";\n\nabstract contract PCUValidateFastFinality is PrecompiledUsage {\n /// @dev Gets the address of the precompile of validating double sign evidence\n function precompileValidateFastFinalityAddress() public view virtual returns (address) {\n return address(0x69);\n }\n\n /**\n * @dev Validates the proof of malicious voting on fast finality\n *\n * Note: The recover process is done by pre-compiled contract. This function is marked as\n * virtual for implementing mocking contract for testing purpose.\n */\n function _pcValidateFastFinalityEvidence(\n bytes memory voterPublicKey,\n uint256 targetBlockNumber,\n bytes32[2] memory targetBlockHash,\n bytes[][2] memory listOfPublicKey,\n bytes[2] memory aggregatedSignature\n ) internal view virtual returns (bool validEvidence) {\n address smc = precompileValidateFastFinalityAddress();\n bool success = true;\n\n bytes memory payload = abi.encodeWithSignature(\n \"validateFinalityVoteProof(bytes,uint256,bytes32[2],bytes[][2],bytes[2])\",\n voterPublicKey,\n targetBlockNumber,\n targetBlockHash,\n listOfPublicKey,\n aggregatedSignature\n );\n uint payloadLength = payload.length;\n uint[1] memory output;\n\n assembly {\n let payloadStart := add(payload, 0x20)\n if iszero(staticcall(gas(), smc, payloadStart, payloadLength, output, 0x20)) {\n success := 0\n }\n\n if iszero(returndatasize()) {\n success := 0\n }\n }\n\n if (!success) revert ErrCallPrecompiled();\n return (output[0] != 0);\n }\n}\n" + }, + "contracts/precompile-usages/PrecompiledUsage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./PrecompiledUsage.sol\";\n\nabstract contract PrecompiledUsage {\n /// @dev Error of call to precompile fails.\n error ErrCallPrecompiled();\n}\n" + }, + "contracts/ronin/fast-finality/FastFinalityTracking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { IRoninValidatorSet } from \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport { IFastFinalityTracking } from \"../..//interfaces/IFastFinalityTracking.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../utils/CommonErrors.sol\";\n\ncontract FastFinalityTracking is IFastFinalityTracking, Initializable, HasContracts {\n /// @dev Mapping from epoch number => consensus address => number of QC vote\n mapping(uint256 => mapping(address => uint256)) internal _tracker;\n /// @dev The latest block that tracked the QC vote\n uint256 internal _latestTrackingBlock;\n\n modifier oncePerBlock() {\n if (block.number <= _latestTrackingBlock) {\n revert ErrOncePerBlock();\n }\n\n _latestTrackingBlock = block.number;\n _;\n }\n\n modifier onlyCoinbase() {\n if (msg.sender != block.coinbase) revert ErrCallerMustBeCoinbase();\n _;\n }\n\n constructor() {\n _disableInitializers();\n }\n\n function initialize(address validatorContract) external initializer {\n _setContract(ContractType.VALIDATOR, validatorContract);\n }\n\n /**\n * @inheritdoc IFastFinalityTracking\n */\n function recordFinality(address[] calldata voters) external override oncePerBlock onlyCoinbase {\n uint256 currentEpoch = IRoninValidatorSet(getContract(ContractType.VALIDATOR)).epochOf(block.number);\n\n for (uint i; i < voters.length; ) {\n unchecked {\n ++_tracker[currentEpoch][voters[i]];\n ++i;\n }\n }\n }\n\n /**\n * @inheritdoc IFastFinalityTracking\n */\n function getManyFinalityVoteCounts(\n uint256 epoch,\n address[] calldata addrs\n ) external view override returns (uint256[] memory voteCounts) {\n uint256 length = addrs.length;\n voteCounts = new uint256[](length);\n for (uint i; i < length; ) {\n voteCounts[i] = _tracker[epoch][addrs[i]];\n unchecked {\n ++i;\n }\n }\n }\n}\n" + }, + "contracts/ronin/gateway/BridgeReward.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { BridgeTrackingHelper } from \"../../extensions/bridge-operator-governance/BridgeTrackingHelper.sol\";\nimport { ContractType, HasContracts } from \"../../extensions/collections/HasContracts.sol\";\nimport { RONTransferHelper } from \"../../extensions/RONTransferHelper.sol\";\nimport { IRoninValidatorSet } from \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport { IBridgeManager } from \"../../interfaces/bridge/IBridgeManager.sol\";\nimport { IBridgeTracking } from \"../../interfaces/bridge/IBridgeTracking.sol\";\nimport { IBridgeReward } from \"../../interfaces/bridge/IBridgeReward.sol\";\nimport { IBridgeSlash } from \"../../interfaces/bridge/IBridgeSlash.sol\";\nimport { Math } from \"../../libraries/Math.sol\";\nimport { TUint256Slot } from \"../../types/Types.sol\";\nimport { ErrSyncTooFarPeriod, ErrInvalidArguments, ErrLengthMismatch, ErrUnauthorizedCall } from \"../../utils/CommonErrors.sol\";\n\ncontract BridgeReward is IBridgeReward, BridgeTrackingHelper, HasContracts, RONTransferHelper, Initializable {\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeReward.rewardInfo.slot\") - 1\n bytes32 private constant REWARD_INFO_SLOT = 0x518cfd198acbffe95e740cfce1af28a3f7de51f0d784893d3d72c5cc59d7062a;\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeReward.rewardPerPeriod.slot\") - 1\n TUint256Slot private constant REWARD_PER_PERIOD_SLOT =\n TUint256Slot.wrap(0x90f7d557245e5dd9485f463e58974fa7cdc93c0abbd0a1afebb8f9640ec73910);\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeReward.latestRewardedPeriod.slot\") - 1\n TUint256Slot private constant LATEST_REWARDED_PERIOD_SLOT =\n TUint256Slot.wrap(0x2417f25874c1cdc139a787dd21df976d40d767090442b3a2496917ecfc93b619);\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeReward.totalRewardToppedUp.slot\") - 1\n TUint256Slot private constant TOTAL_REWARDS_TOPPED_UP_SLOT =\n TUint256Slot.wrap(0x9a8c9f129792436c37b7bd2d79c56132fc05bf26cc8070794648517c2a0c6c64);\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeReward.totalRewardScattered.slot\") - 1\n TUint256Slot private constant TOTAL_REWARDS_SCATTERED_SLOT =\n TUint256Slot.wrap(0x3663384f6436b31a97d9c9a02f64ab8b73ead575c5b6224fa0800a6bd57f62f4);\n\n address private immutable _self;\n\n constructor() payable {\n _self = address(this);\n _disableInitializers();\n }\n\n function initialize(\n address bridgeManagerContract,\n address bridgeTrackingContract,\n address bridgeSlashContract,\n address validatorSetContract,\n uint256 rewardPerPeriod\n ) external payable initializer {\n _setContract(ContractType.BRIDGE_MANAGER, bridgeManagerContract);\n _setContract(ContractType.BRIDGE_TRACKING, bridgeTrackingContract);\n _setContract(ContractType.BRIDGE_SLASH, bridgeSlashContract);\n _setContract(ContractType.VALIDATOR, validatorSetContract);\n _setRewardPerPeriod(rewardPerPeriod);\n _syncLatestRewardedPeriod();\n _receiveRON();\n }\n\n /**\n * @inheritdoc IBridgeReward\n */\n function receiveRON() external payable {\n _receiveRON();\n }\n\n /**\n * @inheritdoc IBridgeReward\n */\n function syncReward(uint256 periodLength) external {\n if (!_isBridgeOperator(msg.sender)) revert ErrUnauthorizedCall(msg.sig);\n\n uint256 latestRewardedPeriod = getLatestRewardedPeriod();\n uint256 currentPeriod = IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod();\n\n if (currentPeriod <= latestRewardedPeriod) revert ErrInvalidArguments(msg.sig);\n if (latestRewardedPeriod + periodLength > currentPeriod) revert ErrInvalidArguments(msg.sig);\n\n LATEST_REWARDED_PERIOD_SLOT.addAssign(periodLength);\n\n address[] memory operators = IBridgeManager(getContract(ContractType.BRIDGE_MANAGER)).getBridgeOperators();\n IBridgeTracking bridgeTrackingContract = IBridgeTracking(getContract(ContractType.BRIDGE_TRACKING));\n\n for (uint256 i = 1; i <= periodLength; ) {\n unchecked {\n _syncReward({\n operators: operators,\n ballots: bridgeTrackingContract.getManyTotalBallots(latestRewardedPeriod, operators),\n totalBallot: bridgeTrackingContract.totalBallot(latestRewardedPeriod),\n totalVote: bridgeTrackingContract.totalVote(latestRewardedPeriod),\n period: latestRewardedPeriod += i\n });\n\n ++i;\n }\n }\n }\n\n /**\n * @inheritdoc IBridgeReward\n */\n function execSyncReward(\n address[] calldata operators,\n uint256[] calldata ballots,\n uint256 totalBallot,\n uint256 totalVote,\n uint256 period\n ) external onlyContract(ContractType.BRIDGE_TRACKING) {\n if (operators.length != ballots.length) revert ErrLengthMismatch(msg.sig);\n if (operators.length == 0) return;\n\n // Only sync the period that is after the latest rewarded period.\n unchecked {\n uint256 latestRewardedPeriod = getLatestRewardedPeriod();\n if (period < latestRewardedPeriod + 1) revert ErrInvalidArguments(msg.sig);\n else if (period > latestRewardedPeriod + 1) revert ErrSyncTooFarPeriod(period, latestRewardedPeriod);\n }\n LATEST_REWARDED_PERIOD_SLOT.store(period);\n\n _syncReward({\n operators: operators,\n ballots: ballots,\n totalBallot: totalBallot,\n totalVote: totalVote,\n period: period\n });\n }\n\n /**\n * @inheritdoc IBridgeReward\n */\n function getTotalRewardToppedUp() external view returns (uint256) {\n return TOTAL_REWARDS_TOPPED_UP_SLOT.load();\n }\n\n /**\n * @inheritdoc IBridgeReward\n */\n function getTotalRewardScattered() external view returns (uint256) {\n return TOTAL_REWARDS_SCATTERED_SLOT.load();\n }\n\n /**\n * @dev Internal function to receive RON tokens as rewards and update the total topped-up rewards amount.\n */\n function _receiveRON() internal {\n // prevent transfer RON directly to logic contract\n if (address(this) == _self) revert ErrUnauthorizedCall(msg.sig);\n\n emit SafeReceived(msg.sender, TOTAL_REWARDS_TOPPED_UP_SLOT.load(), msg.value);\n TOTAL_REWARDS_TOPPED_UP_SLOT.addAssign(msg.value);\n }\n\n /**\n * @dev Internal function to synchronize and distribute rewards to bridge operators for a given period.\n * @param operators An array containing the addresses of bridge operators to receive rewards.\n * @param ballots An array containing the individual ballot counts for each bridge operator.\n * @param totalBallot The total number of available ballots for the period.\n * @param totalVote The total number of votes recorded for the period.\n * @param period The period for which the rewards are being synchronized.\n */\n function _syncReward(\n address[] memory operators,\n uint256[] memory ballots,\n uint256 totalBallot,\n uint256 totalVote,\n uint256 period\n ) internal {\n uint256 numBridgeOperators = operators.length;\n uint256 rewardPerPeriod = getRewardPerPeriod();\n uint256[] memory slashedDurationList = _getSlashInfo(operators);\n // Validate should share the reward equally\n bool shouldShareEqually = _shouldShareEqually(totalBallot, totalVote, ballots);\n\n uint256 reward;\n bool shouldSlash;\n uint256 sumRewards;\n\n for (uint256 i; i < numBridgeOperators; ) {\n (reward, shouldSlash) = _calcRewardAndCheckSlashedStatus({\n shouldShareEqually: shouldShareEqually,\n numBridgeOperators: numBridgeOperators,\n rewardPerPeriod: rewardPerPeriod,\n ballot: ballots[i],\n totalBallot: totalBallot,\n period: period,\n slashUntilPeriod: slashedDurationList[i]\n });\n\n sumRewards += shouldSlash ? 0 : reward;\n _updateRewardAndTransfer({ period: period, operator: operators[i], reward: reward, shouldSlash: shouldSlash });\n\n unchecked {\n ++i;\n }\n }\n\n TOTAL_REWARDS_SCATTERED_SLOT.addAssign(sumRewards);\n }\n\n /**\n * @dev Internal function to synchronize the latest rewarded period based on the current period of the validator set contract.\n * @notice This function is used internally to synchronize the latest rewarded period with the current period of the validator set contract.\n * @notice The `currentPeriod` of the validator set contract is retrieved and stored in the `LATEST_REWARDED_PERIOD_SLOT`.\n * @notice This function ensures that the latest rewarded period is updated to reflect the current period in the validator set contract.\n */\n function _syncLatestRewardedPeriod() internal {\n LATEST_REWARDED_PERIOD_SLOT.store(IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod());\n }\n\n /**\n * @dev Returns whether should share the reward equally, in case of bridge tracking returns\n * informed data or there is no ballot in a day.\n *\n * Emit a {BridgeTrackingIncorrectlyResponded} event when in case of incorrect data.\n */\n function _shouldShareEqually(\n uint256 totalBallot,\n uint256 totalVote,\n uint256[] memory ballots\n ) internal returns (bool shareEqually) {\n bool valid = _isValidBridgeTrackingResponse(totalBallot, totalVote, ballots);\n if (!valid) {\n emit BridgeTrackingIncorrectlyResponded();\n }\n\n return !valid || totalBallot == 0;\n }\n\n /**\n * @dev Internal function to calculate the reward for a bridge operator and check its slashing status.\n * @param shouldShareEqually A boolean indicating whether the reward should be shared equally among bridge operators.\n * @param numBridgeOperators The total number of bridge operators for proportional reward calculation.\n * @param rewardPerPeriod The total reward available for the period.\n * @param ballot The individual ballot count of the bridge operator for the period.\n * @param totalBallot The total number of available ballots for the period.\n * @param period The period for which the reward is being calculated.\n * @param slashUntilPeriod The period until which slashing is effective for the bridge operator.\n * @return reward The calculated reward for the bridge operator.\n * @return shouldSlash A boolean indicating whether the bridge operator should be slashed for the current period.\n */\n function _calcRewardAndCheckSlashedStatus(\n bool shouldShareEqually,\n uint256 numBridgeOperators,\n uint256 rewardPerPeriod,\n uint256 ballot,\n uint256 totalBallot,\n uint256 period,\n uint256 slashUntilPeriod\n ) internal pure returns (uint256 reward, bool shouldSlash) {\n shouldSlash = _shouldSlashedThisPeriod(period, slashUntilPeriod);\n reward = _calcReward(shouldShareEqually, numBridgeOperators, rewardPerPeriod, ballot, totalBallot);\n }\n\n /**\n * @dev Internal function to check if a specific period should be considered as slashed based on the slash duration.\n * @param period The period to check if it should be slashed.\n * @param slashDuration The duration until which periods should be considered as slashed.\n * @return shouldSlashed A boolean indicating whether the specified period should be slashed.\n * @notice This function is used internally to determine if a particular period should be marked as slashed based on the slash duration.\n */\n function _shouldSlashedThisPeriod(uint256 period, uint256 slashDuration) internal pure returns (bool) {\n return period <= slashDuration;\n }\n\n /**\n * @dev Internal function to calculate the reward for a bridge operator based on the provided parameters.\n * @param shouldShareEqually A boolean indicating whether the reward should be shared equally among bridge operators.\n * @param numBridgeOperators The total number of bridge operators for proportional reward calculation.\n * @param rewardPerPeriod The total reward available for the period.\n * @param ballot The individual ballot count of the bridge operator for the period.\n * @param totalBallot The total number of available ballots for the period.\n * @return reward The calculated reward for the bridge operator.\n */\n function _calcReward(\n bool shouldShareEqually,\n uint256 numBridgeOperators,\n uint256 rewardPerPeriod,\n uint256 ballot,\n uint256 totalBallot\n ) internal pure returns (uint256 reward) {\n // Shares equally in case the bridge has nothing to vote or bridge tracking response is incorrect\n // Else shares the bridge operators reward proportionally\n reward = shouldShareEqually ? rewardPerPeriod / numBridgeOperators : (rewardPerPeriod * ballot) / totalBallot;\n }\n\n /**\n * @dev Transfer `reward` to a `operator` or only emit event based on the operator `slashed` status.\n */\n function _updateRewardAndTransfer(uint256 period, address operator, uint256 reward, bool shouldSlash) private {\n BridgeRewardInfo storage _iRewardInfo = _getRewardInfo()[operator];\n\n if (shouldSlash) {\n _iRewardInfo.slashed += reward;\n emit BridgeRewardSlashed(period, operator, reward);\n } else {\n _iRewardInfo.claimed += reward;\n if (_unsafeSendRONLimitGas({ recipient: payable(operator), amount: reward, gas: 0 })) {\n emit BridgeRewardScattered(period, operator, reward);\n } else {\n emit BridgeRewardScatterFailed(period, operator, reward);\n }\n }\n }\n\n /**\n * @inheritdoc IBridgeReward\n */\n function getRewardPerPeriod() public view returns (uint256) {\n return REWARD_PER_PERIOD_SLOT.load();\n }\n\n /**\n * @inheritdoc IBridgeReward\n */\n function getLatestRewardedPeriod() public view returns (uint256) {\n return LATEST_REWARDED_PERIOD_SLOT.load();\n }\n\n /**\n * @inheritdoc IBridgeReward\n */\n function setRewardPerPeriod(uint256 rewardPerPeriod) external onlyContract(ContractType.BRIDGE_MANAGER) {\n _setRewardPerPeriod(rewardPerPeriod);\n }\n\n /**\n * @dev Internal function for setting the total reward per period.\n * Emit an {UpdatedRewardPerPeriod} event after set.\n */\n function _setRewardPerPeriod(uint256 rewardPerPeriod) internal {\n REWARD_PER_PERIOD_SLOT.store(rewardPerPeriod);\n emit UpdatedRewardPerPeriod(rewardPerPeriod);\n }\n\n /**\n * @dev Internal helper for querying slash info of a list of operators.\n */\n function _getSlashInfo(address[] memory operatorList) internal returns (uint256[] memory _slashedDuration) {\n return IBridgeSlash(getContract(ContractType.BRIDGE_SLASH)).getSlashUntilPeriodOf(operatorList);\n }\n\n /**\n * @dev Internal helper for querying whether an address is an operator.\n */\n function _isBridgeOperator(address operator) internal view returns (bool) {\n return IBridgeManager(getContract(ContractType.BRIDGE_MANAGER)).isBridgeOperator(operator);\n }\n\n /**\n * @dev Internal function to access the mapping from bridge operator => BridgeRewardInfo.\n * @return rewardInfo the mapping from bridge operator => BridgeRewardInfo.\n */\n function _getRewardInfo() internal pure returns (mapping(address => BridgeRewardInfo) storage rewardInfo) {\n assembly (\"memory-safe\") {\n rewardInfo.slot := REWARD_INFO_SLOT\n }\n }\n}\n" + }, + "contracts/ronin/gateway/BridgeSlash.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { BridgeTrackingHelper } from \"../../extensions/bridge-operator-governance/BridgeTrackingHelper.sol\";\nimport { IHasContracts, HasContracts } from \"../../extensions/collections/HasContracts.sol\";\nimport { IBridgeSlash } from \"../../interfaces/bridge/IBridgeSlash.sol\";\nimport { IERC165, IBridgeManagerCallback } from \"../../interfaces/bridge/IBridgeManagerCallback.sol\";\nimport { IBridgeTracking } from \"../../interfaces/bridge/IBridgeTracking.sol\";\nimport { IRoninValidatorSet } from \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport { Math } from \"../../libraries/Math.sol\";\nimport { ContractType } from \"../../utils/ContractType.sol\";\nimport { IdentityGuard } from \"../../utils/IdentityGuard.sol\";\nimport { ErrLengthMismatch } from \"../../utils/CommonErrors.sol\";\n\n/**\n * @title BridgeSlash\n * @dev A contract that implements slashing functionality for bridge operators based on their availability.\n */\ncontract BridgeSlash is\n IBridgeSlash,\n IBridgeManagerCallback,\n BridgeTrackingHelper,\n IdentityGuard,\n Initializable,\n HasContracts\n{\n /// @inheritdoc IBridgeSlash\n uint256 public constant TIER_1_PENALTY_DURATION = 1;\n /// @inheritdoc IBridgeSlash\n uint256 public constant TIER_2_PENALTY_DURATION = 5;\n /// @inheritdoc IBridgeSlash\n uint256 public constant MINIMUM_VOTE_THRESHOLD = 50;\n /// @inheritdoc IBridgeSlash\n uint256 public constant REMOVE_DURATION_THRESHOLD = 30;\n\n /// @dev Tier 1 slashing threshold ratio is 10%\n uint256 private constant TIER_1_THRESHOLD = 10_00;\n /// @dev Tier 2 slashing threshold ratio is 30%\n uint256 private constant TIER_2_THRESHOLD = 30_00;\n /// @dev Max percentage 100%. Values [0; 100_00] reflexes [0; 100%]\n uint256 private constant PERCENTAGE_FRACTION = 100_00;\n /// @dev This value is set to the maximum value of uint128 to indicate a permanent slash duration.\n uint256 private constant SLASH_PERMANENT_DURATION = type(uint128).max;\n /// @dev value is equal to keccak256(\"@ronin.dpos.gateway.BridgeSlash.bridgeSlashInfos.slot\") - 1\n bytes32 private constant BRIDGE_SLASH_INFOS_SLOT = 0xd08d185790a07c7b9b721e2713c8580010a57f31c72c16f6e80b831d0ee45bfe;\n\n /**\n * @dev The modifier verifies if the `totalVote` is non-zero, indicating the presence of ballots for the period.\n * @param totalVote The total number of ballots for the period.\n */\n modifier onlyPeriodHasEnoughVotes(uint256 totalVote) {\n if (totalVote <= MINIMUM_VOTE_THRESHOLD) return;\n _;\n }\n\n constructor() payable {\n _disableInitializers();\n }\n\n function initialize(\n address validatorContract,\n address bridgeManagerContract,\n address bridgeTrackingContract\n ) external initializer {\n _setContract(ContractType.VALIDATOR, validatorContract);\n _setContract(ContractType.BRIDGE_MANAGER, bridgeManagerContract);\n _setContract(ContractType.BRIDGE_TRACKING, bridgeTrackingContract);\n }\n\n /**\n * @inheritdoc IBridgeManagerCallback\n */\n function onBridgeOperatorsAdded(\n address[] calldata bridgeOperators,\n bool[] memory addeds\n ) external onlyContract(ContractType.BRIDGE_MANAGER) returns (bytes4) {\n uint256 length = bridgeOperators.length;\n if (length != addeds.length) revert ErrLengthMismatch(msg.sig);\n if (length == 0) {\n return IBridgeManagerCallback.onBridgeOperatorsAdded.selector;\n }\n\n mapping(address => BridgeSlashInfo) storage _bridgeSlashInfos = _getBridgeSlashInfos();\n uint256 currentPeriod = IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod();\n\n for (uint256 i; i < length; ) {\n unchecked {\n if (addeds[i]) {\n _bridgeSlashInfos[bridgeOperators[i]].newlyAddedAtPeriod = uint128(currentPeriod);\n }\n\n ++i;\n }\n }\n\n return IBridgeManagerCallback.onBridgeOperatorsAdded.selector;\n }\n\n /**\n * @inheritdoc IBridgeManagerCallback\n */\n function onBridgeOperatorUpdated(\n address currentBridgeOperator,\n address newBridgeOperator\n ) external onlyContract(ContractType.BRIDGE_MANAGER) returns (bytes4) {\n mapping(address => BridgeSlashInfo) storage _bridgeSlashInfos = _getBridgeSlashInfos();\n\n _bridgeSlashInfos[newBridgeOperator] = _bridgeSlashInfos[currentBridgeOperator];\n delete _bridgeSlashInfos[currentBridgeOperator];\n\n return IBridgeManagerCallback.onBridgeOperatorUpdated.selector;\n }\n\n /**\n * @inheritdoc IBridgeSlash\n */\n function execSlashBridgeOperators(\n address[] memory allBridgeOperators,\n uint256[] memory ballots,\n uint256 totalBallot,\n uint256 totalVote,\n uint256 period\n ) external onlyContract(ContractType.BRIDGE_TRACKING) onlyPeriodHasEnoughVotes(totalVote) returns (bool slashed) {\n uint256 length = allBridgeOperators.length;\n if (length != ballots.length) revert ErrLengthMismatch(msg.sig);\n if (length == 0) return false;\n if (!_isValidBridgeTrackingResponse(totalBallot, totalVote, ballots)) {\n emit BridgeTrackingIncorrectlyResponded();\n return false;\n }\n\n // Get penalty durations for each slash tier.\n uint256[] memory penaltyDurations = _getPenaltyDurations();\n // Get the storage mapping for bridge slash information.\n mapping(address => BridgeSlashInfo) storage _bridgeSlashInfos = _getBridgeSlashInfos();\n\n // Declare variables for iteration.\n BridgeSlashInfo memory status;\n uint256 slashUntilPeriod;\n address bridgeOperator;\n Tier tier;\n\n for (uint256 i; i < length; ) {\n bridgeOperator = allBridgeOperators[i];\n status = _bridgeSlashInfos[bridgeOperator];\n\n // Check if the bridge operator was added before the current period.\n // Bridge operators added in current period will not be slashed.\n if (status.newlyAddedAtPeriod < period) {\n // Determine the slash tier for the bridge operator based on their ballots.\n tier = _getSlashTier(ballots[i], totalVote);\n\n slashUntilPeriod = _calcSlashUntilPeriod(tier, period, status.slashUntilPeriod, penaltyDurations);\n\n // Check if the slash duration exceeds the threshold for removal.\n if (_isSlashDurationMetRemovalThreshold(slashUntilPeriod, period)) {\n slashUntilPeriod = SLASH_PERMANENT_DURATION;\n emit RemovalRequested(period, bridgeOperator);\n }\n\n // Emit the Slashed event if the tier is not Tier 0 and bridge operator will not be removed.\n // Update the slash until period number for the bridge operator if the tier is not Tier 0.\n if (tier != Tier.Tier0) {\n slashed = true;\n\n if (slashUntilPeriod != SLASH_PERMANENT_DURATION) {\n emit Slashed(tier, bridgeOperator, period, slashUntilPeriod);\n }\n\n // Store updated slash until period\n _bridgeSlashInfos[bridgeOperator].slashUntilPeriod = uint128(slashUntilPeriod);\n }\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @inheritdoc IBridgeManagerCallback\n */\n function onBridgeOperatorsRemoved(\n address[] calldata,\n bool[] calldata\n ) external view onlyContract(ContractType.BRIDGE_MANAGER) returns (bytes4) {\n return IBridgeManagerCallback.onBridgeOperatorsAdded.selector;\n }\n\n /**\n * @inheritdoc IERC165\n */\n function supportsInterface(bytes4 interfaceId) external pure returns (bool) {\n return interfaceId == type(IBridgeManagerCallback).interfaceId || interfaceId == type(IERC165).interfaceId;\n }\n\n /**\n * @inheritdoc IBridgeSlash\n */\n function getSlashUntilPeriodOf(\n address[] calldata bridgeOperators\n ) external view returns (uint256[] memory untilPeriods) {\n uint256 length = bridgeOperators.length;\n untilPeriods = new uint256[](length);\n mapping(address => BridgeSlashInfo) storage _bridgeSlashInfos = _getBridgeSlashInfos();\n\n for (uint256 i; i < length; ) {\n untilPeriods[i] = _bridgeSlashInfos[bridgeOperators[i]].slashUntilPeriod;\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @inheritdoc IBridgeSlash\n */\n function getAddedPeriodOf(address[] calldata bridgeOperators) external view returns (uint256[] memory addedPeriods) {\n uint256 length = bridgeOperators.length;\n addedPeriods = new uint256[](length);\n mapping(address => BridgeSlashInfo) storage _bridgeSlashInfos = _getBridgeSlashInfos();\n\n for (uint256 i; i < length; ) {\n addedPeriods[i] = _bridgeSlashInfos[bridgeOperators[i]].newlyAddedAtPeriod;\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @inheritdoc IBridgeSlash\n */\n function getPenaltyDurations() external pure returns (uint256[] memory penaltyDurations) {\n penaltyDurations = _getPenaltyDurations();\n }\n\n /**\n * @inheritdoc IBridgeSlash\n */\n function getSlashTier(uint256 ballot, uint256 totalVote) external pure returns (Tier tier) {\n tier = _getSlashTier(ballot, totalVote);\n }\n\n /**\n * @dev Checks if the slash duration exceeds the threshold for removal and handles it accordingly.\n * @param slashUntilPeriod The slash until period number.\n * @param period The current period.\n * @return met A boolean indicates that the threshold for removal is met.\n */\n function _isSlashDurationMetRemovalThreshold(\n uint256 slashUntilPeriod,\n uint256 period\n ) internal pure returns (bool met) {\n met = slashUntilPeriod - (period - 1) >= REMOVE_DURATION_THRESHOLD;\n }\n\n /**\n * @dev Calculates the slash until period based on the specified tier, current period, and slash until period.\n * @param tier The slash tier representing the severity of the slash.\n * @param period The current period in which the calculation is performed.\n * @param slashUntilPeriod The existing slash until period.\n * @param penaltyDurations An array of penalty durations for each slash tier.\n * @return newSlashUntilPeriod The newly calculated slash until period.\n */\n function _calcSlashUntilPeriod(\n Tier tier,\n uint256 period,\n uint256 slashUntilPeriod,\n uint256[] memory penaltyDurations\n ) internal pure returns (uint256 newSlashUntilPeriod) {\n // Calculate the slash until period number.\n newSlashUntilPeriod = penaltyDurations[uint8(tier)] + Math.max(period - 1, slashUntilPeriod);\n }\n\n /**\n * @dev Internal function to determine the slashing tier based on the given ballot count and total votes.\n * @param ballot The individual ballot count of a bridge operator.\n * @param totalVote The total number of votes recorded for the bridge operator.\n * @return tier The calculated slashing tier for the bridge operator.\n * @notice The `ratio` is calculated as the percentage of uncast votes (totalVote - ballot) relative to the total votes.\n */\n function _getSlashTier(uint256 ballot, uint256 totalVote) internal pure virtual returns (Tier tier) {\n uint256 ratio = ((totalVote - ballot) * PERCENTAGE_FRACTION) / totalVote;\n tier = ratio > TIER_2_THRESHOLD ? Tier.Tier2 : ratio > TIER_1_THRESHOLD ? Tier.Tier1 : Tier.Tier0;\n }\n\n /**\n * @dev Internal function to access the mapping from bridge operator => BridgeSlashInfo.\n * @return bridgeSlashInfos the mapping from bridge operator => BridgeSlashInfo.\n */\n function _getBridgeSlashInfos() internal pure returns (mapping(address => BridgeSlashInfo) storage bridgeSlashInfos) {\n assembly (\"memory-safe\") {\n bridgeSlashInfos.slot := BRIDGE_SLASH_INFOS_SLOT\n }\n }\n\n /**\n * @dev Internal function to retrieve the penalty durations for each slashing tier.\n * @return penaltyDurations An array containing the penalty durations for Tier0, Tier1, and Tier2 in that order.\n */\n function _getPenaltyDurations() internal pure virtual returns (uint256[] memory penaltyDurations) {\n // reserve index 0\n penaltyDurations = new uint256[](3);\n penaltyDurations[uint8(Tier.Tier1)] = TIER_1_PENALTY_DURATION;\n penaltyDurations[uint8(Tier.Tier2)] = TIER_2_PENALTY_DURATION;\n }\n}\n" + }, + "contracts/ronin/gateway/BridgeTracking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../interfaces/bridge/IBridgeTracking.sol\";\nimport { IBridgeManager } from \"../../interfaces/bridge/IBridgeManager.sol\";\nimport { IBridgeSlash } from \"../../interfaces/bridge/IBridgeSlash.sol\";\nimport { IBridgeReward } from \"../../interfaces/bridge/IBridgeReward.sol\";\nimport { IRoninValidatorSet } from \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport { HasBridgeDeprecated, HasValidatorDeprecated } from \"../../utils/DeprecatedSlots.sol\";\n\ncontract BridgeTracking is HasBridgeDeprecated, HasValidatorDeprecated, HasContracts, Initializable, IBridgeTracking {\n struct PeriodVotingMetric {\n /// @dev Total requests that are tracked in the period. This value is 0 until the {_bufferMetric.requests[]} gets added into a period metric.\n uint256 totalRequest;\n uint256 totalBallot;\n mapping(address => uint256) totalBallotOf;\n address[] voters;\n }\n\n struct PeriodVotingMetricTimeWrapper {\n uint256 lastEpoch;\n Request[] requests;\n PeriodVotingMetric data;\n }\n\n struct ReceiptTrackingInfo {\n /// @dev The period that the receipt is approved. Value 0 means the receipt is not approved yet.\n uint256 approvedPeriod;\n /// @dev The address list of voters\n address[] voters;\n /// @dev Mapping from voter => flag indicating the voter casts vote for this receipt\n mapping(address => bool) voted;\n /// @dev The period that the receipt is tracked, i.e. the metric is transferred from buffer to the period. Value 0 means the receipt is currently in buffer or not tracked yet.\n uint256 trackedPeriod;\n }\n\n /// @dev The block that the contract allows incoming mutable calls.\n uint256 internal _startedAtBlock;\n\n /// @dev The temporary info of votes and ballots\n PeriodVotingMetricTimeWrapper internal _bufferMetric;\n /// @dev Mapping from period number => vote stats based on period\n mapping(uint256 => PeriodVotingMetric) internal _periodMetric;\n /// @dev Mapping from vote kind => receipt id => receipt stats\n mapping(VoteKind => mapping(uint256 => ReceiptTrackingInfo)) internal _receiptTrackingInfo;\n /// @dev The latest period that get synced with bridge's slashing and rewarding contract\n uint256 internal _lastSyncPeriod;\n\n modifier skipOnUnstarted() {\n _skipOnUnstarted();\n _;\n }\n\n /**\n * @dev Returns the whole transaction in case the current block is less than start block.\n */\n function _skipOnUnstarted() private view {\n if (block.number < _startedAtBlock) {\n assembly {\n return(0, 0)\n }\n }\n }\n\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the contract storage.\n */\n function initialize(address bridgeContract, address validatorContract, uint256 startedAtBlock_) external initializer {\n _setContract(ContractType.BRIDGE, bridgeContract);\n _setContract(ContractType.VALIDATOR, validatorContract);\n _startedAtBlock = startedAtBlock_;\n }\n\n function initializeV2() external reinitializer(2) {\n _setContract(ContractType.BRIDGE, ______deprecatedBridge);\n _setContract(ContractType.VALIDATOR, ______deprecatedValidator);\n\n delete ______deprecatedBridge;\n delete ______deprecatedValidator;\n }\n\n function initializeV3(address bridgeManager, address bridgeSlash, address bridgeReward) external reinitializer(3) {\n _setContract(ContractType.BRIDGE_MANAGER, bridgeManager);\n _setContract(ContractType.BRIDGE_SLASH, bridgeSlash);\n _setContract(ContractType.BRIDGE_REWARD, bridgeReward);\n _lastSyncPeriod = IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod() - 1;\n }\n\n /**\n * @inheritdoc IBridgeTracking\n */\n function startedAtBlock() external view override returns (uint256) {\n return _startedAtBlock;\n }\n\n /**\n * @inheritdoc IBridgeTracking\n */\n function totalVote(uint256 period) public view override returns (uint256 totalVote_) {\n totalVote_ = _periodMetric[period].totalRequest;\n if (_isBufferCountedForPeriod(period)) {\n totalVote_ += _bufferMetric.requests.length;\n }\n }\n\n /**\n * @inheritdoc IBridgeTracking\n */\n function totalBallot(uint256 period) public view override returns (uint256 totalBallot_) {\n totalBallot_ = _periodMetric[period].totalBallot;\n if (_isBufferCountedForPeriod(period)) {\n totalBallot_ += _bufferMetric.data.totalBallot;\n }\n }\n\n /**\n * @inheritdoc IBridgeTracking\n */\n function getManyTotalBallots(\n uint256 period,\n address[] calldata operators\n ) external view override returns (uint256[] memory _res) {\n _res = _getManyTotalBallots(period, operators);\n }\n\n function _getManyTotalBallots(\n uint256 period,\n address[] memory operators\n ) internal view returns (uint256[] memory res) {\n uint256 length = operators.length;\n res = new uint256[](length);\n bool isBufferCounted = _isBufferCountedForPeriod(period);\n for (uint i = 0; i < length; ) {\n res[i] = _totalBallotOf(period, operators[i], isBufferCounted);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @inheritdoc IBridgeTracking\n */\n function totalBallotOf(uint256 period, address bridgeOperator) public view override returns (uint256) {\n return _totalBallotOf(period, bridgeOperator, _isBufferCountedForPeriod(period));\n }\n\n /**\n * @inheritdoc IBridgeTracking\n */\n function handleVoteApproved(\n VoteKind kind,\n uint256 requestId\n ) external override onlyContract(ContractType.BRIDGE) skipOnUnstarted {\n ReceiptTrackingInfo storage _receiptInfo = _receiptTrackingInfo[kind][requestId];\n\n // Only records for the receipt which not approved\n if (_receiptInfo.approvedPeriod == 0) {\n _trySyncBuffer();\n uint256 currentPeriod = IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod();\n _receiptInfo.approvedPeriod = currentPeriod;\n\n Request storage _bufferRequest = _bufferMetric.requests.push();\n _bufferRequest.kind = kind;\n _bufferRequest.id = requestId;\n\n address[] storage _voters = _receiptInfo.voters;\n for (uint i = 0; i < _voters.length; ) {\n _increaseBallot(kind, requestId, _voters[i], currentPeriod);\n\n unchecked {\n ++i;\n }\n }\n\n delete _receiptInfo.voters;\n }\n }\n\n /**\n * @inheritdoc IBridgeTracking\n */\n function recordVote(\n VoteKind kind,\n uint256 requestId,\n address operator\n ) external override onlyContract(ContractType.BRIDGE) skipOnUnstarted {\n uint256 period = IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod();\n _trySyncBuffer();\n ReceiptTrackingInfo storage _receiptInfo = _receiptTrackingInfo[kind][requestId];\n\n // When the vote is not approved yet, the voters are saved in the receipt info, and not increase ballot metric.\n // The ballot metric will be increased later in the {handleVoteApproved} method.\n if (_receiptInfo.approvedPeriod == 0) {\n _receiptInfo.voters.push(operator);\n return;\n }\n\n _increaseBallot(kind, requestId, operator, period);\n\n uint256 lastSyncPeriod = _lastSyncPeriod;\n // When switching to new period, wrap up vote info, then slash and distribute reward accordingly.\n if (lastSyncPeriod < period) {\n _lastSyncPeriod = period;\n\n address[] memory allOperators = IBridgeManager(getContract(ContractType.BRIDGE_MANAGER)).getBridgeOperators();\n uint256[] memory ballots = _getManyTotalBallots(lastSyncPeriod, allOperators);\n\n uint256 totalVote_ = totalVote(lastSyncPeriod);\n uint256 totalBallot_ = totalBallot(lastSyncPeriod);\n\n address bridgeSlashContract = getContract(ContractType.BRIDGE_SLASH);\n (bool success, bytes memory returnOrRevertData) = bridgeSlashContract.call(\n abi.encodeCall(\n IBridgeSlash.execSlashBridgeOperators,\n (allOperators, ballots, totalBallot_, totalVote_, lastSyncPeriod)\n )\n );\n if (!success) {\n emit ExternalCallFailed(\n bridgeSlashContract,\n IBridgeSlash.execSlashBridgeOperators.selector,\n returnOrRevertData\n );\n }\n\n address bridgeRewardContract = getContract(ContractType.BRIDGE_REWARD);\n (success, returnOrRevertData) = bridgeRewardContract.call(\n abi.encodeCall(IBridgeReward.execSyncReward, (allOperators, ballots, totalBallot_, totalVote_, lastSyncPeriod))\n );\n if (!success) {\n emit ExternalCallFailed(bridgeRewardContract, IBridgeReward.execSyncReward.selector, returnOrRevertData);\n }\n }\n }\n\n /**\n * @dev Increases the ballot for the operator at a period.\n */\n function _increaseBallot(VoteKind kind, uint256 requestId, address operator, uint256 currentPeriod) internal {\n ReceiptTrackingInfo storage _receiptInfo = _receiptTrackingInfo[kind][requestId];\n if (_receiptInfo.voted[operator]) {\n return;\n }\n\n _receiptInfo.voted[operator] = true;\n\n uint256 trackedPeriod = _receiptInfo.trackedPeriod;\n\n // Do not increase ballot for receipt that is neither in the buffer, nor in the most current tracked period.\n // If the receipt is not tracked in a period, increase metric in buffer.\n unchecked {\n if (trackedPeriod == 0) {\n if (_bufferMetric.data.totalBallotOf[operator] == 0) {\n _bufferMetric.data.voters.push(operator);\n }\n _bufferMetric.data.totalBallot++;\n _bufferMetric.data.totalBallotOf[operator]++;\n }\n // If the receipt is tracked in the most current tracked period, increase metric in the period.\n else if (trackedPeriod == currentPeriod) {\n PeriodVotingMetric storage _metric = _periodMetric[trackedPeriod];\n _metric.totalBallot++;\n _metric.totalBallotOf[operator]++;\n }\n }\n }\n\n /**\n * @dev See `totalBallotOf`.\n */\n function _totalBallotOf(\n uint256 period,\n address operator,\n bool mustCountLastStats\n ) internal view returns (uint256 _totalBallot) {\n _totalBallot = _periodMetric[period].totalBallotOf[operator];\n if (mustCountLastStats) {\n _totalBallot += _bufferMetric.data.totalBallotOf[operator];\n }\n }\n\n /**\n * @dev Syncs period stats. Move all data from the buffer metric to the period metric.\n *\n * Requirements:\n * - The epoch after the buffer epoch is wrapped up.\n */\n function _trySyncBuffer() internal {\n IRoninValidatorSet validatorContract = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n uint256 currentEpoch = validatorContract.epochOf(block.number);\n if (_bufferMetric.lastEpoch < currentEpoch) {\n (, uint256 trackedPeriod) = validatorContract.tryGetPeriodOfEpoch(_bufferMetric.lastEpoch + 1);\n _bufferMetric.lastEpoch = currentEpoch;\n\n // Copy numbers of totals\n PeriodVotingMetric storage _metric = _periodMetric[trackedPeriod];\n _metric.totalRequest += _bufferMetric.requests.length;\n _metric.totalBallot += _bufferMetric.data.totalBallot;\n\n // Copy voters info and voters' ballot\n for (uint i = 0; i < _bufferMetric.data.voters.length; ) {\n address voter = _bufferMetric.data.voters[i];\n _metric.totalBallotOf[voter] += _bufferMetric.data.totalBallotOf[voter];\n delete _bufferMetric.data.totalBallotOf[voter]; // need to manually delete each element, due to mapping\n\n unchecked {\n ++i;\n }\n }\n\n // Mark all receipts in the buffer as tracked. Keep total number of receipts and delete receipt details.\n for (uint i = 0; i < _bufferMetric.requests.length; ) {\n Request storage _bufferRequest = _bufferMetric.requests[i];\n ReceiptTrackingInfo storage _receiptInfo = _receiptTrackingInfo[_bufferRequest.kind][_bufferRequest.id];\n _receiptInfo.trackedPeriod = trackedPeriod;\n\n unchecked {\n ++i;\n }\n }\n\n delete _bufferMetric.requests;\n delete _bufferMetric.data;\n }\n }\n\n /**\n * @dev Returns whether the buffer stats must be counted or not.\n */\n function _isBufferCountedForPeriod(uint256 queriedPeriod) internal view returns (bool) {\n IRoninValidatorSet validatorContract = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n uint256 currentEpoch = validatorContract.epochOf(block.number);\n (bool filled, uint256 periodOfNextTemporaryEpoch) = validatorContract.tryGetPeriodOfEpoch(\n _bufferMetric.lastEpoch + 1\n );\n return filled && queriedPeriod == periodOfNextTemporaryEpoch && _bufferMetric.lastEpoch < currentEpoch;\n }\n}\n" + }, + "contracts/ronin/gateway/PauseEnforcer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/AccessControlEnumerable.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../../interfaces/IPauseTarget.sol\";\n\ncontract PauseEnforcer is AccessControlEnumerable, Initializable {\n /**\n * @dev Error thrown when the target is already on paused state.\n */\n error ErrTargetIsOnPaused();\n\n /**\n * @dev Error thrown when the target is not on paused state.\n */\n error ErrTargetIsNotOnPaused();\n\n /**\n * @dev Error thrown when the contract is not on emergency pause.\n */\n error ErrNotOnEmergencyPause();\n\n bytes32 public constant SENTRY_ROLE = keccak256(\"SENTRY_ROLE\");\n\n /// @dev The contract that can be paused or unpaused by the SENTRY_ROLE.\n IPauseTarget public target;\n /// @dev Indicating whether or not the target contract is paused in emergency mode.\n bool public emergency;\n\n /// @dev Emitted when the emergency ppause is triggered by `account`.\n event EmergencyPaused(address account);\n /// @dev Emitted when the emergency unpause is triggered by `account`.\n event EmergencyUnpaused(address account);\n /// @dev Emitted when the target is changed.\n event TargetChanged(IPauseTarget target);\n\n modifier onEmergency() {\n if (!emergency) revert ErrNotOnEmergencyPause();\n\n _;\n }\n\n modifier targetPaused() {\n if (!target.paused()) revert ErrTargetIsOnPaused();\n\n _;\n }\n\n modifier targetNotPaused() {\n if (target.paused()) revert ErrTargetIsNotOnPaused();\n\n _;\n }\n\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the contract storage.\n */\n function initialize(IPauseTarget _target, address _admin, address[] memory _sentries) external initializer {\n _changeTarget(_target);\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n for (uint _i; _i < _sentries.length; ) {\n _grantRole(SENTRY_ROLE, _sentries[_i]);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @dev Grants the SENTRY_ROLE to the specified address.\n */\n function grantSentry(address _sentry) external onlyRole(DEFAULT_ADMIN_ROLE) {\n _grantRole(SENTRY_ROLE, _sentry);\n }\n\n /**\n * @dev Revokes the SENTRY_ROLE from the specified address.\n */\n function revokeSentry(address _sentry) external onlyRole(DEFAULT_ADMIN_ROLE) {\n _revokeRole(SENTRY_ROLE, _sentry);\n }\n\n /**\n * @dev Triggers a pause on the target contract.\n *\n * Requirements:\n * - Only be called by accounts with the SENTRY_ROLE,\n * - The target contract is not already paused.\n */\n function triggerPause() external onlyRole(SENTRY_ROLE) targetNotPaused {\n emergency = true;\n target.pause();\n emit EmergencyPaused(msg.sender);\n }\n\n /**\n * @dev Triggers an unpause on the target contract.\n *\n * Requirements:\n * - Only be called by accounts with the SENTRY_ROLE,\n * - The target contract is already paused.\n * - The target contract is paused in emergency mode.\n */\n function triggerUnpause() external onlyRole(SENTRY_ROLE) onEmergency targetPaused {\n emergency = false;\n target.unpause();\n emit EmergencyUnpaused(msg.sender);\n }\n\n /**\n * @dev Setter for `target`.\n *\n * Requirements:\n * - Only admin can call this method.\n */\n function changeTarget(IPauseTarget _target) external onlyRole(DEFAULT_ADMIN_ROLE) {\n _changeTarget(_target);\n }\n\n /**\n * @dev Internal helper for setting value to `target`.\n */\n function _changeTarget(IPauseTarget _target) internal {\n target = _target;\n emit TargetChanged(_target);\n }\n}\n" + }, + "contracts/ronin/gateway/RoninBridgeManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ContractType, RoleAccess, ErrUnauthorized, BridgeManager } from \"../../extensions/bridge-operator-governance/BridgeManager.sol\";\nimport { Ballot, GlobalProposal, Proposal, GovernanceProposal } from \"../../extensions/sequential-governance/governance-proposal/GovernanceProposal.sol\";\nimport { CoreGovernance, GlobalCoreGovernance, GlobalGovernanceProposal } from \"../../extensions/sequential-governance/governance-proposal/GlobalGovernanceProposal.sol\";\nimport { VoteStatusConsumer } from \"../../interfaces/consumers/VoteStatusConsumer.sol\";\nimport { ErrQueryForEmptyVote } from \"../../utils/CommonErrors.sol\";\n\ncontract RoninBridgeManager is BridgeManager, GovernanceProposal, GlobalGovernanceProposal {\n constructor(\n uint256 num,\n uint256 denom,\n uint256 roninChainId,\n uint256 expiryDuration,\n address bridgeContract,\n address[] memory callbackRegisters,\n address[] memory bridgeOperators,\n address[] memory governors,\n uint96[] memory voteWeights,\n GlobalProposal.TargetOption[] memory targetOptions,\n address[] memory targets\n )\n payable\n CoreGovernance(expiryDuration)\n GlobalCoreGovernance(targetOptions, targets)\n BridgeManager(num, denom, roninChainId, bridgeContract, callbackRegisters, bridgeOperators, governors, voteWeights)\n {}\n\n /**\n * CURRENT NETWORK\n */\n\n /**\n * @dev See `CoreGovernance-_proposeProposal`.\n *\n * Requirements:\n * - The method caller is governor.\n *\n */\n function propose(\n uint256 _chainId,\n uint256 _expiryTimestamp,\n address[] calldata _targets,\n uint256[] calldata _values,\n bytes[] calldata _calldatas,\n uint256[] calldata _gasAmounts\n ) external onlyGovernor {\n _proposeProposal(_chainId, _expiryTimestamp, _targets, _values, _calldatas, _gasAmounts, msg.sender);\n }\n\n /**\n * @dev See `GovernanceProposal-_proposeProposalStructAndCastVotes`.\n *\n * Requirements:\n * - The method caller is governor.\n * - The proposal is for the current network.\n *\n */\n function proposeProposalStructAndCastVotes(\n Proposal.ProposalDetail calldata _proposal,\n Ballot.VoteType[] calldata _supports,\n Signature[] calldata _signatures\n ) external onlyGovernor {\n _proposeProposalStructAndCastVotes(_proposal, _supports, _signatures, DOMAIN_SEPARATOR, msg.sender);\n }\n\n /**\n * @dev Proposes and casts vote for a proposal on the current network.\n *\n * Requirements:\n * - The method caller is governor.\n * - The proposal is for the current network.\n *\n */\n function proposeProposalForCurrentNetwork(\n uint256 expiryTimestamp,\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata calldatas,\n uint256[] calldata gasAmounts,\n Ballot.VoteType support\n ) external onlyGovernor {\n address _voter = msg.sender;\n Proposal.ProposalDetail memory _proposal = _proposeProposal({\n chainId: block.chainid,\n expiryTimestamp: expiryTimestamp,\n targets: targets,\n values: values,\n calldatas: calldatas,\n gasAmounts: gasAmounts,\n creator: _voter\n });\n _castProposalVoteForCurrentNetwork(_voter, _proposal, support);\n }\n\n /**\n * @dev Casts vote for a proposal on the current network.\n *\n * Requirements:\n * - The method caller is governor.\n *\n */\n function castProposalVoteForCurrentNetwork(\n Proposal.ProposalDetail calldata proposal,\n Ballot.VoteType support\n ) external onlyGovernor {\n _castProposalVoteForCurrentNetwork(msg.sender, proposal, support);\n }\n\n /**\n * @dev See `GovernanceProposal-_castProposalBySignatures`.\n */\n function castProposalBySignatures(\n Proposal.ProposalDetail calldata proposal,\n Ballot.VoteType[] calldata supports_,\n Signature[] calldata signatures\n ) external {\n _castProposalBySignatures(proposal, supports_, signatures, DOMAIN_SEPARATOR);\n }\n\n /**\n * GLOBAL NETWORK\n */\n\n /**\n * @dev See `CoreGovernance-_proposeGlobal`.\n *\n * Requirements:\n * - The method caller is governor.\n *\n */\n function proposeGlobal(\n uint256 expiryTimestamp,\n GlobalProposal.TargetOption[] calldata targetOptions,\n uint256[] calldata values,\n bytes[] calldata calldatas,\n uint256[] calldata gasAmounts\n ) external onlyGovernor {\n _proposeGlobal({\n expiryTimestamp: expiryTimestamp,\n targetOptions: targetOptions,\n values: values,\n calldatas: calldatas,\n gasAmounts: gasAmounts,\n creator: msg.sender\n });\n }\n\n /**\n * @dev See `GovernanceProposal-_proposeGlobalProposalStructAndCastVotes`.\n *\n * Requirements:\n * - The method caller is governor.\n *\n */\n function proposeGlobalProposalStructAndCastVotes(\n GlobalProposal.GlobalProposalDetail calldata globalProposal,\n Ballot.VoteType[] calldata supports_,\n Signature[] calldata signatures\n ) external onlyGovernor {\n _proposeGlobalProposalStructAndCastVotes({\n globalProposal: globalProposal,\n supports_: supports_,\n signatures: signatures,\n domainSeparator: DOMAIN_SEPARATOR,\n creator: msg.sender\n });\n }\n\n /**\n * @dev See `GovernanceProposal-_castGlobalProposalBySignatures`.\n */\n function castGlobalProposalBySignatures(\n GlobalProposal.GlobalProposalDetail calldata globalProposal,\n Ballot.VoteType[] calldata supports_,\n Signature[] calldata signatures\n ) external {\n _castGlobalProposalBySignatures({\n globalProposal: globalProposal,\n supports_: supports_,\n signatures: signatures,\n domainSeparator: DOMAIN_SEPARATOR\n });\n }\n\n /**\n * COMMON METHODS\n */\n\n /**\n * @dev Deletes the expired proposal by its chainId and nonce, without creating a new proposal.\n *\n * Requirements:\n * - The proposal is already created.\n *\n */\n function deleteExpired(uint256 _chainId, uint256 _round) external {\n ProposalVote storage _vote = vote[_chainId][_round];\n if (_vote.hash == 0) revert ErrQueryForEmptyVote();\n\n _tryDeleteExpiredVotingRound(_vote);\n }\n\n /**\n * @dev Returns the expiry duration for a new proposal.\n */\n function getProposalExpiryDuration() external view returns (uint256) {\n return _getProposalExpiryDuration();\n }\n\n /**\n * @dev Internal function to get the chain type of the contract.\n * @return The chain type, indicating the type of the chain the contract operates on (e.g., RoninChain).\n */\n function _getChainType() internal pure override returns (ChainType) {\n return ChainType.RoninChain;\n }\n\n /**\n * @dev Internal function to get the total weights of all governors.\n * @return The total weights of all governors combined.\n */\n function _getTotalWeight() internal view virtual override returns (uint256) {\n return getTotalWeight();\n }\n\n /**\n * @dev Internal function to get the minimum vote weight required for governance actions.\n * @return The minimum vote weight required for governance actions.\n */\n function _getMinimumVoteWeight() internal view virtual override returns (uint256) {\n return minimumVoteWeight();\n }\n\n /**\n * @dev Internal function to get the vote weight of a specific governor.\n * @param _governor The address of the governor to get the vote weight for.\n * @return The vote weight of the specified governor.\n */\n function _getWeight(address _governor) internal view virtual override returns (uint256) {\n return _getGovernorWeight(_governor);\n }\n}\n" + }, + "contracts/ronin/gateway/RoninGatewayV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/AccessControlEnumerable.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../../extensions/GatewayV2.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../extensions/MinimumWithdrawal.sol\";\nimport \"../../interfaces/IERC20Mintable.sol\";\nimport \"../../interfaces/IERC721Mintable.sol\";\nimport \"../../interfaces/bridge/IBridgeTracking.sol\";\nimport \"../../interfaces/IRoninGatewayV2.sol\";\nimport \"../../interfaces/IRoninTrustedOrganization.sol\";\nimport \"../../interfaces/consumers/VoteStatusConsumer.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../libraries/IsolatedGovernance.sol\";\nimport \"../../interfaces/bridge/IBridgeManager.sol\";\n\ncontract RoninGatewayV2 is\n GatewayV2,\n Initializable,\n MinimumWithdrawal,\n AccessControlEnumerable,\n VoteStatusConsumer,\n IRoninGatewayV2,\n HasContracts\n{\n using Token for Token.Info;\n using Transfer for Transfer.Request;\n using Transfer for Transfer.Receipt;\n using IsolatedGovernance for IsolatedGovernance.Vote;\n\n /// @dev Withdrawal unlocker role hash\n bytes32 public constant WITHDRAWAL_MIGRATOR = keccak256(\"WITHDRAWAL_MIGRATOR\");\n\n /// @dev Flag indicating whether the withdrawal migrate progress is done\n bool public withdrawalMigrated;\n /// @dev Total withdrawal\n uint256 public withdrawalCount;\n /// @dev Mapping from chain id => deposit id => deposit vote\n mapping(uint256 => mapping(uint256 => IsolatedGovernance.Vote)) public depositVote;\n /// @dev Mapping from withdrawal id => mainchain withdrew vote\n mapping(uint256 => IsolatedGovernance.Vote) public mainchainWithdrewVote;\n /// @dev Mapping from withdrawal id => withdrawal receipt\n mapping(uint256 => Transfer.Receipt) public withdrawal;\n /// @dev Mapping from withdrawal id => validator address => signatures\n mapping(uint256 => mapping(address => bytes)) internal _withdrawalSig;\n /// @dev Mapping from token address => chain id => mainchain token address\n mapping(address => mapping(uint256 => MappedToken)) internal _mainchainToken;\n\n /// @custom:deprecated Previously `_validatorContract` (non-zero value)\n address private ____deprecated0;\n /// @custom:deprecated Previously `_bridgeTrackingContract` (non-zero value)\n address private ____deprecated1;\n\n /// @dev Mapping from withdrawal id => vote for recording withdrawal stats\n mapping(uint256 => IsolatedGovernance.Vote) public withdrawalStatVote;\n\n /// @custom:deprecated Previously `_trustedOrgContract` (non-zero value)\n address private ____deprecated2;\n\n uint256 internal _trustedNum;\n uint256 internal _trustedDenom;\n\n fallback() external payable {\n _fallback();\n }\n\n receive() external payable {\n _fallback();\n }\n\n modifier onlyBridgeOperator() {\n _requireBridgeOperator();\n _;\n }\n\n /**\n * @dev Reverts if the method caller is not bridge operator.\n */\n function _requireBridgeOperator() internal view {\n if (!IBridgeManager(getContract(ContractType.BRIDGE_MANAGER)).isBridgeOperator(msg.sender))\n revert ErrUnauthorized(msg.sig, RoleAccess.__DEPRECATED_BRIDGE_OPERATOR);\n }\n\n /**\n * @dev Initializes contract storage.\n */\n function initialize(\n address _roleSetter,\n uint256 _numerator,\n uint256 _denominator,\n uint256 _trustedNumerator,\n uint256 _trustedDenominator,\n address[] calldata _withdrawalMigrators,\n // _packedAddresses[0]: roninTokens\n // _packedAddresses[1]: mainchainTokens\n address[][2] calldata _packedAddresses,\n // _packedNumbers[0]: chainIds\n // _packedNumbers[1]: minimumThresholds\n uint256[][2] calldata _packedNumbers,\n Token.Standard[] calldata _standards\n ) external virtual initializer {\n _setupRole(DEFAULT_ADMIN_ROLE, _roleSetter);\n _setThreshold(_numerator, _denominator);\n _setTrustedThreshold(_trustedNumerator, _trustedDenominator);\n if (_packedAddresses[0].length > 0) {\n _mapTokens(_packedAddresses[0], _packedAddresses[1], _packedNumbers[0], _standards);\n _setMinimumThresholds(_packedAddresses[0], _packedNumbers[1]);\n }\n\n for (uint256 _i; _i < _withdrawalMigrators.length; ) {\n _grantRole(WITHDRAWAL_MIGRATOR, _withdrawalMigrators[_i]);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n function initializeV2() external reinitializer(2) {\n _setContract(ContractType.VALIDATOR, ____deprecated0);\n _setContract(ContractType.BRIDGE_TRACKING, ____deprecated1);\n _setContract(ContractType.RONIN_TRUSTED_ORGANIZATION, ____deprecated2);\n delete ____deprecated0;\n delete ____deprecated1;\n delete ____deprecated2;\n }\n\n function initializeV3(address bridgeAdmin) external reinitializer(3) {\n _setContract(ContractType.BRIDGE_MANAGER, bridgeAdmin);\n }\n\n /**\n * @dev Migrates withdrawals.\n *\n * Requirements:\n * - The method caller is the migrator.\n * - The arrays have the same length and its length larger than 0.\n *\n */\n function migrateWithdrawals(\n Transfer.Request[] calldata _requests,\n address[] calldata _requesters\n ) external onlyRole(WITHDRAWAL_MIGRATOR) {\n if (withdrawalMigrated) revert ErrWithdrawalsMigrated();\n if (!(_requesters.length == _requests.length && _requests.length > 0)) revert ErrLengthMismatch(msg.sig);\n\n for (uint256 _i; _i < _requests.length; ) {\n MappedToken memory _token = getMainchainToken(_requests[_i].tokenAddr, 1);\n if (_requests[_i].info.erc != _token.erc) revert ErrInvalidTokenStandard();\n\n _storeAsReceipt(_requests[_i], 1, _requesters[_i], _token.tokenAddr);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @dev Mark the migration as done.\n */\n function markWithdrawalMigrated() external {\n if (!(hasRole(DEFAULT_ADMIN_ROLE, msg.sender) || hasRole(WITHDRAWAL_MIGRATOR, msg.sender))) {\n revert ErrUnauthorized(msg.sig, RoleAccess.WITHDRAWAL_MIGRATOR);\n }\n if (withdrawalMigrated) revert ErrWithdrawalsMigrated();\n\n withdrawalMigrated = true;\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function getWithdrawalSignatures(\n uint256 _withdrawalId,\n address[] calldata _validators\n ) external view returns (bytes[] memory _signatures) {\n _signatures = new bytes[](_validators.length);\n for (uint256 _i = 0; _i < _validators.length; ) {\n _signatures[_i] = _withdrawalSig[_withdrawalId][_validators[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function depositFor(Transfer.Receipt calldata _receipt) external whenNotPaused onlyBridgeOperator {\n address _sender = msg.sender;\n _depositFor(_receipt, _sender, minimumVoteWeight());\n IBridgeTracking(getContract(ContractType.BRIDGE_TRACKING)).recordVote(\n IBridgeTracking.VoteKind.Deposit,\n _receipt.id,\n _sender\n );\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function tryBulkAcknowledgeMainchainWithdrew(\n uint256[] calldata _withdrawalIds\n ) external onlyBridgeOperator returns (bool[] memory _executedReceipts) {\n address _governor = msg.sender;\n uint256 _minVoteWeight = minimumVoteWeight();\n\n uint256 _withdrawalId;\n _executedReceipts = new bool[](_withdrawalIds.length);\n IBridgeTracking _bridgeTrackingContract = IBridgeTracking(getContract(ContractType.BRIDGE_TRACKING));\n for (uint256 _i; _i < _withdrawalIds.length; ) {\n _withdrawalId = _withdrawalIds[_i];\n _bridgeTrackingContract.recordVote(IBridgeTracking.VoteKind.MainchainWithdrawal, _withdrawalId, _governor);\n if (mainchainWithdrew(_withdrawalId)) {\n _executedReceipts[_i] = true;\n } else {\n IsolatedGovernance.Vote storage _vote = mainchainWithdrewVote[_withdrawalId];\n Transfer.Receipt memory _withdrawal = withdrawal[_withdrawalId];\n bytes32 _hash = _withdrawal.hash();\n VoteStatus _status = _castIsolatedVote(_vote, _governor, _minVoteWeight, _hash);\n if (_status == VoteStatus.Approved) {\n _vote.status = VoteStatus.Executed;\n _bridgeTrackingContract.handleVoteApproved(IBridgeTracking.VoteKind.MainchainWithdrawal, _withdrawalId);\n emit MainchainWithdrew(_hash, _withdrawal);\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function tryBulkDepositFor(\n Transfer.Receipt[] calldata _receipts\n ) external whenNotPaused onlyBridgeOperator returns (bool[] memory _executedReceipts) {\n address _sender = msg.sender;\n\n Transfer.Receipt memory _receipt;\n _executedReceipts = new bool[](_receipts.length);\n uint256 _minVoteWeight = minimumVoteWeight();\n IBridgeTracking _bridgeTrackingContract = IBridgeTracking(getContract(ContractType.BRIDGE_TRACKING));\n for (uint256 _i; _i < _receipts.length; ) {\n _receipt = _receipts[_i];\n _bridgeTrackingContract.recordVote(IBridgeTracking.VoteKind.Deposit, _receipt.id, _sender);\n if (depositVote[_receipt.mainchain.chainId][_receipt.id].status == VoteStatus.Executed) {\n _executedReceipts[_i] = true;\n } else {\n _depositFor(_receipt, _sender, _minVoteWeight);\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function requestWithdrawalFor(Transfer.Request calldata _request, uint256 _chainId) external whenNotPaused {\n _requestWithdrawalFor(_request, msg.sender, _chainId);\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function bulkRequestWithdrawalFor(Transfer.Request[] calldata _requests, uint256 _chainId) external whenNotPaused {\n if (_requests.length == 0) revert ErrEmptyArray();\n\n for (uint256 _i; _i < _requests.length; ) {\n _requestWithdrawalFor(_requests[_i], msg.sender, _chainId);\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function requestWithdrawalSignatures(uint256 _withdrawalId) external whenNotPaused {\n if (mainchainWithdrew(_withdrawalId)) revert ErrWithdrawnOnMainchainAlready();\n\n Transfer.Receipt memory _receipt = withdrawal[_withdrawalId];\n if (_receipt.ronin.chainId != block.chainid) {\n revert ErrInvalidChainId(msg.sig, _receipt.ronin.chainId, block.chainid);\n }\n\n emit WithdrawalSignaturesRequested(_receipt.hash(), _receipt);\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function bulkSubmitWithdrawalSignatures(\n uint256[] calldata _withdrawals,\n bytes[] calldata _signatures\n ) external whenNotPaused onlyBridgeOperator {\n address _validator = msg.sender;\n\n if (!(_withdrawals.length > 0 && _withdrawals.length == _signatures.length)) {\n revert ErrLengthMismatch(msg.sig);\n }\n\n uint256 _minVoteWeight = minimumVoteWeight();\n\n uint256 _id;\n IBridgeTracking _bridgeTrackingContract = IBridgeTracking(getContract(ContractType.BRIDGE_TRACKING));\n for (uint256 _i; _i < _withdrawals.length; ) {\n _id = _withdrawals[_i];\n _withdrawalSig[_id][_validator] = _signatures[_i];\n _bridgeTrackingContract.recordVote(IBridgeTracking.VoteKind.Withdrawal, _id, _validator);\n\n IsolatedGovernance.Vote storage _proposal = withdrawalStatVote[_id];\n VoteStatus _status = _castIsolatedVote(_proposal, _validator, _minVoteWeight, bytes32(_id));\n if (_status == VoteStatus.Approved) {\n _proposal.status = VoteStatus.Executed;\n _bridgeTrackingContract.handleVoteApproved(IBridgeTracking.VoteKind.Withdrawal, _id);\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function mapTokens(\n address[] calldata _roninTokens,\n address[] calldata _mainchainTokens,\n uint256[] calldata _chainIds,\n Token.Standard[] calldata _standards\n ) external onlyAdmin {\n if (_roninTokens.length == 0) revert ErrLengthMismatch(msg.sig);\n _mapTokens(_roninTokens, _mainchainTokens, _chainIds, _standards);\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function depositVoted(uint256 _chainId, uint256 _depositId, address _voter) external view returns (bool) {\n return depositVote[_chainId][_depositId].voted(_voter);\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function mainchainWithdrewVoted(uint256 _withdrawalId, address _voter) external view returns (bool) {\n return mainchainWithdrewVote[_withdrawalId].voted(_voter);\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function mainchainWithdrew(uint256 _withdrawalId) public view returns (bool) {\n return mainchainWithdrewVote[_withdrawalId].status == VoteStatus.Executed;\n }\n\n /**\n * @inheritdoc IRoninGatewayV2\n */\n function getMainchainToken(address _roninToken, uint256 _chainId) public view returns (MappedToken memory _token) {\n _token = _mainchainToken[_roninToken][_chainId];\n if (_token.tokenAddr == address(0)) revert ErrUnsupportedToken();\n }\n\n /**\n * @dev Maps Ronin tokens to mainchain networks.\n *\n * Requirement:\n * - The arrays have the same length.\n *\n * Emits the `TokenMapped` event.\n *\n */\n function _mapTokens(\n address[] calldata _roninTokens,\n address[] calldata _mainchainTokens,\n uint256[] calldata _chainIds,\n Token.Standard[] calldata _standards\n ) internal {\n if (!(_roninTokens.length == _mainchainTokens.length && _roninTokens.length == _chainIds.length))\n revert ErrLengthMismatch(msg.sig);\n\n for (uint256 _i; _i < _roninTokens.length; ) {\n _mainchainToken[_roninTokens[_i]][_chainIds[_i]].tokenAddr = _mainchainTokens[_i];\n _mainchainToken[_roninTokens[_i]][_chainIds[_i]].erc = _standards[_i];\n\n unchecked {\n ++_i;\n }\n }\n\n emit TokenMapped(_roninTokens, _mainchainTokens, _chainIds, _standards);\n }\n\n /**\n * @dev Deposits based on the receipt.\n *\n * Emits the `Deposited` once the assets are released.\n *\n */\n function _depositFor(Transfer.Receipt memory _receipt, address _validator, uint256 _minVoteWeight) internal {\n uint256 _id = _receipt.id;\n _receipt.info.validate();\n if (_receipt.kind != Transfer.Kind.Deposit) revert ErrInvalidReceiptKind();\n\n if (_receipt.ronin.chainId != block.chainid)\n revert ErrInvalidChainId(msg.sig, _receipt.ronin.chainId, block.chainid);\n\n MappedToken memory _token = getMainchainToken(_receipt.ronin.tokenAddr, _receipt.mainchain.chainId);\n\n if (!(_token.erc == _receipt.info.erc && _token.tokenAddr == _receipt.mainchain.tokenAddr))\n revert ErrInvalidReceipt();\n\n IsolatedGovernance.Vote storage _proposal = depositVote[_receipt.mainchain.chainId][_id];\n bytes32 _receiptHash = _receipt.hash();\n VoteStatus _status = _castIsolatedVote(_proposal, _validator, _minVoteWeight, _receiptHash);\n emit DepositVoted(_validator, _id, _receipt.mainchain.chainId, _receiptHash);\n if (_status == VoteStatus.Approved) {\n _proposal.status = VoteStatus.Executed;\n _receipt.info.handleAssetTransfer(payable(_receipt.ronin.addr), _receipt.ronin.tokenAddr, IWETH(address(0)));\n IBridgeTracking(getContract(ContractType.BRIDGE_TRACKING)).handleVoteApproved(\n IBridgeTracking.VoteKind.Deposit,\n _receipt.id\n );\n emit Deposited(_receiptHash, _receipt);\n }\n }\n\n /**\n * @dev Locks the assets and request withdrawal.\n *\n * Requirements:\n * - The token info is valid.\n *\n * Emits the `WithdrawalRequested` event.\n *\n */\n function _requestWithdrawalFor(Transfer.Request calldata _request, address _requester, uint256 _chainId) internal {\n _request.info.validate();\n _checkWithdrawal(_request);\n MappedToken memory _token = getMainchainToken(_request.tokenAddr, _chainId);\n if (_request.info.erc != _token.erc) revert ErrInvalidTokenStandard();\n\n _request.info.transferFrom(_requester, address(this), _request.tokenAddr);\n _storeAsReceipt(_request, _chainId, _requester, _token.tokenAddr);\n }\n\n /**\n * @dev Stores the withdrawal request as a receipt.\n *\n * Emits the `WithdrawalRequested` event.\n *\n */\n function _storeAsReceipt(\n Transfer.Request calldata _request,\n uint256 _chainId,\n address _requester,\n address _mainchainTokenAddr\n ) internal returns (uint256 _withdrawalId) {\n _withdrawalId = withdrawalCount++;\n Transfer.Receipt memory _receipt = _request.into_withdrawal_receipt(\n _requester,\n _withdrawalId,\n _mainchainTokenAddr,\n _chainId\n );\n withdrawal[_withdrawalId] = _receipt;\n emit WithdrawalRequested(_receipt.hash(), _receipt);\n }\n\n /**\n * @dev Don't send me RON.\n */\n function _fallback() internal virtual {\n revert ErrInvalidRequest();\n }\n\n /**\n * @inheritdoc GatewayV2\n */\n function _getTotalWeight() internal view virtual override returns (uint256) {\n return IBridgeManager(getContract(ContractType.BRIDGE_MANAGER)).getTotalWeight();\n }\n\n /**\n * @dev Casts and updates the vote result.\n *\n * Requirements:\n * - The vote is not finalized.\n * - The voter has not voted for the round.\n *\n */\n function _castIsolatedVote(\n IsolatedGovernance.Vote storage _v,\n address _voter,\n uint256 _minVoteWeight,\n bytes32 _hash\n ) internal virtual returns (VoteStatus _status) {\n _v.castVote(_voter, _hash);\n uint256 _totalWeight = _getVoteWeight(_v, _hash);\n return _v.syncVoteStatus(_minVoteWeight, _totalWeight, _hash);\n }\n\n /**\n * @dev Returns the vote weight for a specified hash.\n */\n function _getVoteWeight(\n IsolatedGovernance.Vote storage _v,\n bytes32 _hash\n ) internal view returns (uint256 _totalWeight) {\n (, address[] memory bridgeOperators, uint96[] memory weights) = IBridgeManager(\n getContract(ContractType.BRIDGE_MANAGER)\n ).getFullBridgeOperatorInfos();\n uint256 length = bridgeOperators.length;\n unchecked {\n for (uint _i; _i < length; ++_i) {\n if (_v.voteHashOf[bridgeOperators[_i]] == _hash) {\n _totalWeight += weights[_i];\n }\n }\n }\n }\n\n function setTrustedThreshold(\n uint256 _trustedNumerator,\n uint256 _trustedDenominator\n ) external virtual onlyAdmin returns (uint256, uint256) {\n return _setTrustedThreshold(_trustedNumerator, _trustedDenominator);\n }\n\n /**\n * @dev Returns the threshold about trusted org.\n */\n function getTrustedThreshold() external view virtual returns (uint256 trustedNum_, uint256 trustedDenom_) {\n return (_trustedNum, _trustedDenom);\n }\n\n /**\n * @dev Sets trusted threshold and returns the old one.\n *\n * Emits the `TrustedThresholdUpdated` event.\n *\n */\n function _setTrustedThreshold(\n uint256 _trustedNumerator,\n uint256 _trustedDenominator\n ) internal virtual returns (uint256 _previousTrustedNum, uint256 _previousTrustedDenom) {\n if (_trustedNumerator > _trustedDenominator) revert ErrInvalidTrustedThreshold();\n\n _previousTrustedNum = _num;\n _previousTrustedDenom = _denom;\n _trustedNum = _trustedNumerator;\n _trustedDenom = _trustedDenominator;\n unchecked {\n emit TrustedThresholdUpdated(\n nonce++,\n _trustedNumerator,\n _trustedDenominator,\n _previousTrustedNum,\n _previousTrustedDenom\n );\n }\n }\n\n /**\n * @dev Returns minimum trusted vote weight.\n */\n function _minimumTrustedVoteWeight(uint256 _totalTrustedWeight) internal view virtual returns (uint256) {\n return (_trustedNum * _totalTrustedWeight + _trustedDenom - 1) / _trustedDenom;\n }\n}\n" + }, + "contracts/ronin/Maintenance.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../interfaces/IMaintenance.sol\";\nimport \"../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../extensions/collections/HasContracts.sol\";\nimport \"../libraries/Math.sol\";\nimport { HasValidatorDeprecated } from \"../utils/DeprecatedSlots.sol\";\nimport { ErrUnauthorized, RoleAccess } from \"../utils/CommonErrors.sol\";\n\ncontract Maintenance is IMaintenance, HasContracts, HasValidatorDeprecated, Initializable {\n using Math for uint256;\n\n /// @dev Mapping from consensus address => maintenance schedule.\n mapping(address => Schedule) internal _schedule;\n\n /// @dev The min duration to maintenance in blocks.\n uint256 public minMaintenanceDurationInBlock;\n /// @dev The max duration to maintenance in blocks.\n uint256 public maxMaintenanceDurationInBlock;\n /// @dev The offset to the min block number that the schedule can start.\n uint256 public minOffsetToStartSchedule;\n /// @dev The offset to the max block number that the schedule can start.\n uint256 public maxOffsetToStartSchedule;\n /// @dev The max number of scheduled maintenances.\n uint256 public maxSchedule;\n /// @dev The cooldown time to request new schedule.\n uint256 public cooldownSecsToMaintain;\n\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the contract storage.\n */\n function initialize(\n address __validatorContract,\n uint256 _minMaintenanceDurationInBlock,\n uint256 _maxMaintenanceDurationInBlock,\n uint256 _minOffsetToStartSchedule,\n uint256 _maxOffsetToStartSchedule,\n uint256 _maxSchedules,\n uint256 _cooldownSecsToMaintain\n ) external initializer {\n _setContract(ContractType.VALIDATOR, __validatorContract);\n _setMaintenanceConfig(\n _minMaintenanceDurationInBlock,\n _maxMaintenanceDurationInBlock,\n _minOffsetToStartSchedule,\n _maxOffsetToStartSchedule,\n _maxSchedules,\n _cooldownSecsToMaintain\n );\n }\n\n function initializeV2() external reinitializer(2) {\n _setContract(ContractType.VALIDATOR, ______deprecatedValidator);\n delete ______deprecatedValidator;\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function setMaintenanceConfig(\n uint256 _minMaintenanceDurationInBlock,\n uint256 _maxMaintenanceDurationInBlock,\n uint256 _minOffsetToStartSchedule,\n uint256 _maxOffsetToStartSchedule,\n uint256 _maxSchedules,\n uint256 _cooldownSecsToMaintain\n ) external onlyAdmin {\n _setMaintenanceConfig(\n _minMaintenanceDurationInBlock,\n _maxMaintenanceDurationInBlock,\n _minOffsetToStartSchedule,\n _maxOffsetToStartSchedule,\n _maxSchedules,\n _cooldownSecsToMaintain\n );\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function schedule(address _consensusAddr, uint256 _startedAtBlock, uint256 _endedAtBlock) external override {\n IRoninValidatorSet _validator = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n\n if (!_validator.isBlockProducer(_consensusAddr)) revert ErrUnauthorized(msg.sig, RoleAccess.BLOCK_PRODUCER);\n if (!_validator.isCandidateAdmin(_consensusAddr, msg.sender))\n revert ErrUnauthorized(msg.sig, RoleAccess.CANDIDATE_ADMIN);\n if (checkScheduled(_consensusAddr)) revert ErrAlreadyScheduled();\n if (!checkCooldownEnded(_consensusAddr)) revert ErrCooldownTimeNotYetEnded();\n if (totalSchedule() >= maxSchedule) revert ErrTotalOfSchedulesExceeded();\n if (!_startedAtBlock.inRange(block.number + minOffsetToStartSchedule, block.number + maxOffsetToStartSchedule)) {\n revert ErrStartBlockOutOfRange();\n }\n if (_startedAtBlock >= _endedAtBlock) revert ErrStartBlockOutOfRange();\n\n uint256 _maintenanceElapsed = _endedAtBlock - _startedAtBlock + 1;\n\n if (!_maintenanceElapsed.inRange(minMaintenanceDurationInBlock, maxMaintenanceDurationInBlock)) {\n revert ErrInvalidMaintenanceDuration();\n }\n if (!_validator.epochEndingAt(_startedAtBlock - 1)) revert ErrStartBlockOutOfRange();\n if (!_validator.epochEndingAt(_endedAtBlock)) revert ErrEndBlockOutOfRange();\n\n Schedule storage _sSchedule = _schedule[_consensusAddr];\n _sSchedule.from = _startedAtBlock;\n _sSchedule.to = _endedAtBlock;\n _sSchedule.lastUpdatedBlock = block.number;\n _sSchedule.requestTimestamp = block.timestamp;\n emit MaintenanceScheduled(_consensusAddr, _sSchedule);\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function cancelSchedule(address _consensusAddr) external override {\n if (!IRoninValidatorSet(getContract(ContractType.VALIDATOR)).isCandidateAdmin(_consensusAddr, msg.sender)) {\n revert ErrUnauthorized(msg.sig, RoleAccess.CANDIDATE_ADMIN);\n }\n if (!checkScheduled(_consensusAddr)) revert ErrUnexistedSchedule();\n if (checkMaintained(_consensusAddr, block.number)) revert ErrAlreadyOnMaintenance();\n\n Schedule storage _sSchedule = _schedule[_consensusAddr];\n delete _sSchedule.from;\n delete _sSchedule.to;\n _sSchedule.lastUpdatedBlock = block.number;\n emit MaintenanceScheduleCancelled(_consensusAddr);\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function getSchedule(address _consensusAddr) external view override returns (Schedule memory) {\n return _schedule[_consensusAddr];\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function checkManyMaintained(\n address[] calldata _addrList,\n uint256 _block\n ) external view override returns (bool[] memory _resList) {\n _resList = new bool[](_addrList.length);\n for (uint _i = 0; _i < _addrList.length; ) {\n _resList[_i] = checkMaintained(_addrList[_i], _block);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function checkManyMaintainedInBlockRange(\n address[] calldata _addrList,\n uint256 _fromBlock,\n uint256 _toBlock\n ) external view override returns (bool[] memory _resList) {\n _resList = new bool[](_addrList.length);\n for (uint _i = 0; _i < _addrList.length; ) {\n _resList[_i] = _maintainingInBlockRange(_addrList[_i], _fromBlock, _toBlock);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function totalSchedule() public view override returns (uint256 _count) {\n address[] memory _validators = IRoninValidatorSet(getContract(ContractType.VALIDATOR)).getValidators();\n unchecked {\n for (uint _i = 0; _i < _validators.length; _i++) {\n if (checkScheduled(_validators[_i])) {\n _count++;\n }\n }\n }\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function checkMaintained(address _consensusAddr, uint256 _block) public view override returns (bool) {\n Schedule storage _s = _schedule[_consensusAddr];\n return _s.from <= _block && _block <= _s.to;\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function checkMaintainedInBlockRange(\n address _consensusAddr,\n uint256 _fromBlock,\n uint256 _toBlock\n ) public view override returns (bool) {\n return _maintainingInBlockRange(_consensusAddr, _fromBlock, _toBlock);\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function checkScheduled(address _consensusAddr) public view override returns (bool) {\n return block.number <= _schedule[_consensusAddr].to;\n }\n\n /**\n * @inheritdoc IMaintenance\n */\n function checkCooldownEnded(address _consensusAddr) public view override returns (bool) {\n return block.timestamp > _schedule[_consensusAddr].requestTimestamp + cooldownSecsToMaintain;\n }\n\n /**\n * @dev Sets the min block period and max block period to maintenance.\n *\n * Requirements:\n * - The max period is larger than the min period.\n *\n * Emits the event `MaintenanceConfigUpdated`.\n *\n */\n function _setMaintenanceConfig(\n uint256 _minMaintenanceDurationInBlock,\n uint256 _maxMaintenanceDurationInBlock,\n uint256 _minOffsetToStartSchedule,\n uint256 _maxOffsetToStartSchedule,\n uint256 _maxSchedule,\n uint256 _cooldownSecsToMaintain\n ) internal {\n if (_minMaintenanceDurationInBlock >= _maxMaintenanceDurationInBlock) revert ErrInvalidMaintenanceDurationConfig();\n if (_minOffsetToStartSchedule >= _maxOffsetToStartSchedule) revert ErrInvalidOffsetToStartScheduleConfigs();\n\n minMaintenanceDurationInBlock = _minMaintenanceDurationInBlock;\n maxMaintenanceDurationInBlock = _maxMaintenanceDurationInBlock;\n minOffsetToStartSchedule = _minOffsetToStartSchedule;\n maxOffsetToStartSchedule = _maxOffsetToStartSchedule;\n maxSchedule = _maxSchedule;\n cooldownSecsToMaintain = _cooldownSecsToMaintain;\n emit MaintenanceConfigUpdated(\n _minMaintenanceDurationInBlock,\n _maxMaintenanceDurationInBlock,\n _minOffsetToStartSchedule,\n _maxOffsetToStartSchedule,\n _maxSchedule,\n _cooldownSecsToMaintain\n );\n }\n\n /**\n * @dev Check if the validator was maintaining in the current period.\n *\n * Note: This method should be called at the end of the period.\n */\n function _maintainingInBlockRange(\n address _consensusAddr,\n uint256 _fromBlock,\n uint256 _toBlock\n ) private view returns (bool) {\n Schedule storage _s = _schedule[_consensusAddr];\n return Math.twoRangeOverlap(_fromBlock, _toBlock, _s.from, _s.to);\n }\n}\n" + }, + "contracts/ronin/profile/Profile.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../interfaces/IProfile.sol\";\nimport { ErrUnauthorized, RoleAccess } from \"../../utils/CommonErrors.sol\";\nimport \"./ProfileStorage.sol\";\n\npragma solidity ^0.8.9;\n\ncontract Profile is IProfile, ProfileStorage, Initializable {\n constructor() {\n _disableInitializers();\n }\n\n function initialize(address validatorContract) external initializer {\n _setContract(ContractType.VALIDATOR, validatorContract);\n }\n\n /**\n * @inheritdoc IProfile\n */\n function getId2Profile(address id) external view returns (CandidateProfile memory) {\n return _id2Profile[id];\n }\n\n /**\n * @inheritdoc IProfile\n */\n function addNewProfile(CandidateProfile memory profile) external onlyAdmin {\n CandidateProfile storage _profile = _id2Profile[profile.id];\n if (_profile.id != address(0)) revert ErrExistentProfile();\n _addNewProfile(_profile, profile);\n }\n\n /**\n * @inheritdoc IProfile\n */\n function registerProfile(CandidateProfile memory profile) external {\n CandidateProfile storage _profile = _id2Profile[profile.id];\n if (_profile.id != address(0)) revert ErrExistentProfile();\n if (\n msg.sender != profile.admin ||\n !IRoninValidatorSet(getContract(ContractType.VALIDATOR)).isCandidateAdmin(profile.consensus, profile.admin)\n ) revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN);\n\n _addNewProfile(_profile, profile);\n }\n}\n" + }, + "contracts/ronin/profile/ProfileStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../extensions/collections/HasContracts.sol\";\nimport { IProfile } from \"../../interfaces/IProfile.sol\";\n\nabstract contract ProfileStorage is IProfile, HasContracts {\n /// @dev Mapping from id address => candidate profile.\n mapping(address => CandidateProfile) internal _id2Profile;\n /// @dev Upgradeable gap.\n bytes32[50] __gap;\n\n /**\n * @dev Add a profile from memory to storage.\n */\n function _addNewProfile(CandidateProfile storage _profile, CandidateProfile memory newProfile) internal {\n _profile.id = newProfile.id;\n _profile.consensus = newProfile.consensus;\n _profile.admin = newProfile.admin;\n _profile.treasury = newProfile.treasury;\n _profile.governor = newProfile.governor;\n _profile.pubkey = newProfile.pubkey;\n\n emit ProfileAdded(newProfile.id);\n }\n\n /**\n * @dev Get an existed profile struct from id. Revert if the profile does not exists.\n */\n function _getId2ProfileHelper(address id) internal view returns (CandidateProfile storage _profile) {\n _profile = _id2Profile[id];\n if (_profile.id == address(0)) revert ErrNonExistentProfile();\n }\n}\n" + }, + "contracts/ronin/RoninGovernanceAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../extensions/sequential-governance/governance-proposal/GovernanceProposal.sol\";\nimport \"../extensions/collections/HasContracts.sol\";\nimport \"../extensions/GovernanceAdmin.sol\";\nimport \"../libraries/EmergencyExitBallot.sol\";\nimport { ErrorHandler } from \"../libraries/ErrorHandler.sol\";\nimport { IsolatedGovernance } from \"../libraries/IsolatedGovernance.sol\";\nimport { HasValidatorDeprecated } from \"../utils/DeprecatedSlots.sol\";\nimport \"../interfaces/IRoninTrustedOrganization.sol\";\nimport \"../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../interfaces/IRoninGovernanceAdmin.sol\";\n\ncontract RoninGovernanceAdmin is\n HasContracts,\n IRoninGovernanceAdmin,\n GovernanceAdmin,\n GovernanceProposal,\n HasValidatorDeprecated\n{\n using ErrorHandler for bool;\n using Proposal for Proposal.ProposalDetail;\n using IsolatedGovernance for IsolatedGovernance.Vote;\n\n /// @dev Mapping from request hash => emergency poll\n mapping(bytes32 => IsolatedGovernance.Vote) internal _emergencyExitPoll;\n\n modifier onlyGovernor() {\n _requireGorvernor();\n _;\n }\n\n constructor(\n uint256 _roninChainId,\n address _roninTrustedOrganizationContract,\n address _validatorContract,\n uint256 _expiryDuration\n ) CoreGovernance(_expiryDuration) GovernanceAdmin(_roninChainId, _roninTrustedOrganizationContract) {\n _setContract(ContractType.VALIDATOR, _validatorContract);\n }\n\n function _requireGorvernor() private view {\n if (_getWeight(msg.sender) == 0) revert ErrUnauthorized(msg.sig, RoleAccess.GOVERNOR);\n }\n\n /**\n * @inheritdoc IHasContracts\n */\n function setContract(\n ContractType contractType,\n address addr\n ) external override(HasContracts, GovernanceAdmin) onlySelfCall {\n _requireHasCode(addr);\n _setContract(contractType, addr);\n }\n\n /**\n * @dev Returns whether the voter casted vote for emergency exit poll.\n */\n function emergencyPollVoted(bytes32 _voteHash, address _voter) external view returns (bool) {\n return _emergencyExitPoll[_voteHash].voted(_voter);\n }\n\n /**\n * @dev See `CoreGovernance-_proposeProposal`.\n *\n * Requirements:\n * - The method caller is governor.\n *\n */\n function propose(\n uint256 _chainId,\n uint256 _expiryTimestamp,\n address[] calldata _targets,\n uint256[] calldata _values,\n bytes[] calldata _calldatas,\n uint256[] calldata _gasAmounts\n ) external onlyGovernor {\n _proposeProposal(_chainId, _expiryTimestamp, _targets, _values, _calldatas, _gasAmounts, msg.sender);\n }\n\n /**\n * @dev See `GovernanceProposal-_proposeProposalStructAndCastVotes`.\n *\n * Requirements:\n * - The method caller is governor.\n * - The proposal is for the current network.\n *\n */\n function proposeProposalStructAndCastVotes(\n Proposal.ProposalDetail calldata _proposal,\n Ballot.VoteType[] calldata _supports,\n Signature[] calldata _signatures\n ) external onlyGovernor {\n _proposeProposalStructAndCastVotes(_proposal, _supports, _signatures, DOMAIN_SEPARATOR, msg.sender);\n }\n\n /**\n * @dev Proposes and casts vote for a proposal on the current network.\n *\n * Requirements:\n * - The method caller is governor.\n * - The proposal is for the current network.\n *\n */\n function proposeProposalForCurrentNetwork(\n uint256 _expiryTimestamp,\n address[] calldata _targets,\n uint256[] calldata _values,\n bytes[] calldata _calldatas,\n uint256[] calldata _gasAmounts,\n Ballot.VoteType _support\n ) external onlyGovernor {\n address _voter = msg.sender;\n Proposal.ProposalDetail memory _proposal = _proposeProposal(\n block.chainid,\n _expiryTimestamp,\n _targets,\n _values,\n _calldatas,\n _gasAmounts,\n _voter\n );\n _castProposalVoteForCurrentNetwork(_voter, _proposal, _support);\n }\n\n /**\n * @dev Casts vote for a proposal on the current network.\n *\n * Requirements:\n * - The method caller is governor.\n *\n */\n function castProposalVoteForCurrentNetwork(\n Proposal.ProposalDetail calldata _proposal,\n Ballot.VoteType _support\n ) external onlyGovernor {\n _castProposalVoteForCurrentNetwork(msg.sender, _proposal, _support);\n }\n\n /**\n * @dev See `GovernanceProposal-_castProposalBySignatures`.\n */\n function castProposalBySignatures(\n Proposal.ProposalDetail calldata _proposal,\n Ballot.VoteType[] calldata _supports,\n Signature[] calldata _signatures\n ) external {\n _castProposalBySignatures(_proposal, _supports, _signatures, DOMAIN_SEPARATOR);\n }\n\n /**\n * @dev Deletes the expired proposal by its chainId and nonce, without creating a new proposal.\n *\n * Requirements:\n * - The proposal is already created.\n *\n */\n function deleteExpired(uint256 _chainId, uint256 _round) external {\n ProposalVote storage _vote = vote[_chainId][_round];\n if (_vote.hash == 0) revert ErrQueryForEmptyVote();\n\n _tryDeleteExpiredVotingRound(_vote);\n }\n\n /**\n * @inheritdoc IRoninGovernanceAdmin\n */\n function createEmergencyExitPoll(\n address _consensusAddr,\n address _recipientAfterUnlockedFund,\n uint256 _requestedAt,\n uint256 _expiredAt\n ) external onlyContract(ContractType.VALIDATOR) {\n bytes32 _hash = EmergencyExitBallot.hash(_consensusAddr, _recipientAfterUnlockedFund, _requestedAt, _expiredAt);\n IsolatedGovernance.Vote storage _v = _emergencyExitPoll[_hash];\n _v.createdAt = block.timestamp;\n _v.expiredAt = _expiredAt;\n emit EmergencyExitPollCreated(_hash, _consensusAddr, _recipientAfterUnlockedFund, _requestedAt, _expiredAt);\n }\n\n /**\n * @dev Votes for an emergency exit. Executes to unlock fund for the emergency exit's requester.\n *\n * Requirements:\n * - The voter is governor.\n * - The voting is existent.\n * - The voting is not expired yet.\n *\n */\n function voteEmergencyExit(\n bytes32 _voteHash,\n address _consensusAddr,\n address _recipientAfterUnlockedFund,\n uint256 _requestedAt,\n uint256 _expiredAt\n ) external onlyGovernor {\n address _voter = msg.sender;\n bytes32 _hash = EmergencyExitBallot.hash(_consensusAddr, _recipientAfterUnlockedFund, _requestedAt, _expiredAt);\n if (_voteHash != _hash) revert ErrInvalidVoteHash();\n\n IsolatedGovernance.Vote storage _v = _emergencyExitPoll[_hash];\n if (_v.createdAt == 0) revert ErrQueryForNonExistentVote();\n if (_v.status == VoteStatus.Expired) revert ErrQueryForExpiredVote();\n\n _v.castVote(_voter, _hash);\n emit EmergencyExitPollVoted(_hash, _voter);\n\n address[] memory _voters = _v.filterByHash(_hash);\n VoteStatus _stt = _v.syncVoteStatus(_getMinimumVoteWeight(), _sumGovernorWeight(_voters), _hash);\n if (_stt == VoteStatus.Approved) {\n _execReleaseLockedFundForEmergencyExitRequest(_consensusAddr, _recipientAfterUnlockedFund);\n emit EmergencyExitPollApproved(_hash);\n _v.status = VoteStatus.Executed;\n } else if (_stt == VoteStatus.Expired) {\n emit EmergencyExitPollExpired(_hash);\n }\n }\n\n /**\n * @dev Returns weight of a govenor.\n */\n function _getWeight(address _governor) internal view virtual override returns (uint256) {\n bytes4 _selector = IRoninTrustedOrganization.getGovernorWeight.selector;\n (bool _success, bytes memory _returndata) = getContract(ContractType.RONIN_TRUSTED_ORGANIZATION).staticcall(\n abi.encodeWithSelector(\n // TransparentUpgradeableProxyV2.functionDelegateCall.selector,\n 0x4bb5274a,\n abi.encodeWithSelector(_selector, _governor)\n )\n );\n _success.handleRevert(_selector, _returndata);\n return abi.decode(_returndata, (uint256));\n }\n\n /**\n * @dev Returns the total weight of a list address of governors.\n */\n function _sumGovernorWeight(address[] memory _governors) internal view virtual returns (uint256) {\n bytes4 _selector = IRoninTrustedOrganization.sumGovernorWeight.selector;\n (bool _success, bytes memory _returndata) = getContract(ContractType.RONIN_TRUSTED_ORGANIZATION).staticcall(\n abi.encodeWithSelector(\n // TransparentUpgradeableProxyV2.functionDelegateCall.selector,\n 0x4bb5274a,\n abi.encodeWithSelector(_selector, _governors)\n )\n );\n\n _success.handleRevert(_selector, _returndata);\n return abi.decode(_returndata, (uint256));\n }\n\n /**\n * @dev Trigger function from validator contract to unlock fund for emeregency exit request.\n */\n function _execReleaseLockedFundForEmergencyExitRequest(\n address _consensusAddr,\n address _recipientAfterUnlockedFund\n ) internal virtual {\n bytes4 _selector = IEmergencyExit.execReleaseLockedFundForEmergencyExitRequest.selector;\n (bool _success, bytes memory _returndata) = getContract(ContractType.VALIDATOR).call(\n abi.encodeWithSelector(\n // TransparentUpgradeableProxyV2.functionDelegateCall.selector,\n 0x4bb5274a,\n abi.encodeWithSelector(_selector, _consensusAddr, _recipientAfterUnlockedFund)\n )\n );\n _success.handleRevert(_selector, _returndata);\n }\n\n /**\n * @dev See `CoreGovernance-_getChainType`.\n */\n function _getChainType() internal pure override returns (ChainType) {\n return ChainType.RoninChain;\n }\n}\n" + }, + "contracts/ronin/slash-indicator/CreditScore.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../interfaces/IMaintenance.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../interfaces/slash-indicator/ICreditScore.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../extensions/consumers/PercentageConsumer.sol\";\nimport \"../../libraries/Math.sol\";\nimport { HasValidatorDeprecated, HasMaintenanceDeprecated } from \"../../utils/DeprecatedSlots.sol\";\nimport { ErrUnauthorized, RoleAccess } from \"../../utils/CommonErrors.sol\";\n\nabstract contract CreditScore is\n ICreditScore,\n HasContracts,\n HasValidatorDeprecated,\n HasMaintenanceDeprecated,\n PercentageConsumer\n{\n /// @dev Mapping from validator address => period index => whether bailed out before\n mapping(address => mapping(uint256 => bool)) internal _checkBailedOutAtPeriod;\n /// @dev Mapping from validator address => credit score\n mapping(address => uint256) internal _creditScore;\n\n /// @dev The max gained number of credit score per period.\n uint256 internal _gainCreditScore;\n /// @dev The max number of credit score that a validator can hold.\n uint256 internal _maxCreditScore;\n /// @dev The number that will be multiplied with the remaining jailed time to get the cost of bailing out.\n uint256 internal _bailOutCostMultiplier;\n /// @dev The percentage of reward to be cut off from the validator in the rest of the period after bailed out.\n uint256 internal _cutOffPercentageAfterBailout;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @inheritdoc ICreditScore\n */\n function updateCreditScores(\n address[] calldata _validators,\n uint256 _period\n ) external override onlyContract(ContractType.VALIDATOR) {\n IRoninValidatorSet _validatorContract = IRoninValidatorSet(msg.sender);\n uint256 _periodStartAtBlock = _validatorContract.currentPeriodStartAtBlock();\n\n bool[] memory _jaileds = _validatorContract.checkManyJailed(_validators);\n bool[] memory _maintaineds = IMaintenance(getContract(ContractType.MAINTENANCE)).checkManyMaintainedInBlockRange(\n _validators,\n _periodStartAtBlock,\n block.number\n );\n uint256[] memory _updatedCreditScores = new uint256[](_validators.length);\n\n for (uint _i = 0; _i < _validators.length; ) {\n address _validator = _validators[_i];\n\n uint256 _indicator = getUnavailabilityIndicator(_validator, _period);\n bool _isJailedInPeriod = _jaileds[_i];\n bool _isMaintainingInPeriod = _maintaineds[_i];\n\n uint256 _actualGain = (_isJailedInPeriod || _isMaintainingInPeriod)\n ? 0\n : Math.subNonNegative(_gainCreditScore, _indicator);\n\n _creditScore[_validator] = Math.addWithUpperbound(_creditScore[_validator], _actualGain, _maxCreditScore);\n _updatedCreditScores[_i] = _creditScore[_validator];\n unchecked {\n ++_i;\n }\n }\n\n emit CreditScoresUpdated(_validators, _updatedCreditScores);\n }\n\n function execResetCreditScores(\n address[] calldata _validators\n ) external override onlyContract(ContractType.VALIDATOR) {\n uint256[] memory _updatedCreditScores = new uint256[](_validators.length);\n for (uint _i = 0; _i < _validators.length; ) {\n address _validator = _validators[_i];\n delete _creditScore[_validator];\n delete _updatedCreditScores[_i];\n\n unchecked {\n ++_i;\n }\n }\n emit CreditScoresUpdated(_validators, _updatedCreditScores);\n }\n\n /**\n * @inheritdoc ICreditScore\n */\n function bailOut(address _consensusAddr) external override {\n IRoninValidatorSet _validatorContract = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n if (!_validatorContract.isValidatorCandidate(_consensusAddr))\n revert ErrUnauthorized(msg.sig, RoleAccess.VALIDATOR_CANDIDATE);\n\n if (!_validatorContract.isCandidateAdmin(_consensusAddr, msg.sender))\n revert ErrUnauthorized(msg.sig, RoleAccess.CANDIDATE_ADMIN);\n\n (bool _isJailed, , uint256 _jailedEpochLeft) = _validatorContract.getJailedTimeLeft(_consensusAddr);\n if (!_isJailed) revert ErrCallerMustBeJailedInTheCurrentPeriod();\n\n uint256 _period = _validatorContract.currentPeriod();\n if (_checkBailedOutAtPeriod[_consensusAddr][_period]) revert ErrValidatorHasBailedOutPreviously();\n\n uint256 _score = _creditScore[_consensusAddr];\n uint256 _cost = _jailedEpochLeft * _bailOutCostMultiplier;\n if (_score < _cost) revert ErrInsufficientCreditScoreToBailOut();\n\n _validatorContract.execBailOut(_consensusAddr, _period);\n\n _creditScore[_consensusAddr] -= _cost;\n _setUnavailabilityIndicator(_consensusAddr, _period, 0);\n _checkBailedOutAtPeriod[_consensusAddr][_period] = true;\n emit BailedOut(_consensusAddr, _period, _cost);\n }\n\n /**\n * @inheritdoc ICreditScore\n */\n function setCreditScoreConfigs(\n uint256 _gainScore,\n uint256 _maxScore,\n uint256 _bailOutMultiplier,\n uint256 _cutOffPercentage\n ) external override onlyAdmin {\n _setCreditScoreConfigs(_gainScore, _maxScore, _bailOutMultiplier, _cutOffPercentage);\n }\n\n /**\n * @dev See `ISlashUnavailability`\n */\n function getUnavailabilityIndicator(address _validator, uint256 _period) public view virtual returns (uint256);\n\n /**\n * @inheritdoc ICreditScore\n */\n function getCreditScoreConfigs()\n external\n view\n override\n returns (\n uint256 gainCreditScore_,\n uint256 maxCreditScore_,\n uint256 bailOutCostMultiplier_,\n uint256 cutOffPercentageAfterBailout_\n )\n {\n return (_gainCreditScore, _maxCreditScore, _bailOutCostMultiplier, _cutOffPercentageAfterBailout);\n }\n\n /**\n * @inheritdoc ICreditScore\n */\n function getCreditScore(address _validator) external view override returns (uint256) {\n return _creditScore[_validator];\n }\n\n /**\n * @inheritdoc ICreditScore\n */\n function getManyCreditScores(\n address[] calldata _validators\n ) public view override returns (uint256[] memory _resultList) {\n _resultList = new uint256[](_validators.length);\n\n for (uint _i = 0; _i < _resultList.length; ) {\n _resultList[_i] = _creditScore[_validators[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc ICreditScore\n */\n function checkBailedOutAtPeriod(address _validator, uint256 _period) public view virtual override returns (bool) {\n return _checkBailedOutAtPeriod[_validator][_period];\n }\n\n /**\n * @dev See `SlashUnavailability`.\n */\n function _setUnavailabilityIndicator(address _validator, uint256 _period, uint256 _indicator) internal virtual;\n\n /**\n * @dev See `ICreditScore-setCreditScoreConfigs`.\n */\n function _setCreditScoreConfigs(\n uint256 _gainScore,\n uint256 _maxScore,\n uint256 _bailOutMultiplier,\n uint256 _cutOffPercentage\n ) internal {\n if (_gainScore > _maxScore) revert ErrInvalidCreditScoreConfig();\n if (_cutOffPercentage > _MAX_PERCENTAGE) revert ErrInvalidCutOffPercentageConfig();\n\n _gainCreditScore = _gainScore;\n _maxCreditScore = _maxScore;\n _bailOutCostMultiplier = _bailOutMultiplier;\n _cutOffPercentageAfterBailout = _cutOffPercentage;\n emit CreditScoreConfigsUpdated(_gainScore, _maxScore, _bailOutMultiplier, _cutOffPercentage);\n }\n}\n" + }, + "contracts/ronin/slash-indicator/SlashBridgeOperator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../extensions/consumers/PercentageConsumer.sol\";\nimport \"../../extensions/collections/HasProxyAdmin.sol\";\nimport \"../../interfaces/slash-indicator/ISlashBridgeOperator.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport { HasValidatorDeprecated } from \"../../utils/DeprecatedSlots.sol\";\n\nabstract contract SlashBridgeOperator is\n ISlashBridgeOperator,\n HasProxyAdmin,\n HasContracts,\n HasValidatorDeprecated,\n PercentageConsumer\n{\n /**\n * @dev The bridge operators will be deprecated reward if (s)he missed more than the ratio.\n * Values 0-10,000 map to 0%-100%.\n */\n uint256 internal _missingVotesRatioTier1;\n /**\n * @dev The bridge operators will be deprecated all rewards including bridge reward and mining reward if (s)he missed\n * more than the ratio. Values 0-10,000 map to 0%-100%.\n */\n uint256 internal _missingVotesRatioTier2;\n /// @dev The number of blocks to jail the corresponding block producer when its bridge operator is slashed tier-2.\n uint256 internal _jailDurationForMissingVotesRatioTier2;\n /// @dev The threshold to skip slashing the bridge operator in case the total number of votes in the bridge is too small.\n uint256 internal _skipBridgeOperatorSlashingThreshold;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @inheritdoc ISlashBridgeOperator\n */\n function getBridgeOperatorSlashingConfigs()\n external\n view\n override\n returns (\n uint256 missingVotesRatioTier1_,\n uint256 missingVotesRatioTier2_,\n uint256 jailDurationForMissingVotesRatioTier2_,\n uint256 skipBridgeOperatorSlashingThreshold_\n )\n {\n return (\n _missingVotesRatioTier1,\n _missingVotesRatioTier2,\n _jailDurationForMissingVotesRatioTier2,\n _skipBridgeOperatorSlashingThreshold\n );\n }\n\n /**\n * @inheritdoc ISlashBridgeOperator\n */\n function setBridgeOperatorSlashingConfigs(\n uint256 _ratioTier1,\n uint256 _ratioTier2,\n uint256 _jailDurationTier2,\n uint256 _skipSlashingThreshold\n ) external override onlyAdmin {\n _setBridgeOperatorSlashingConfigs(_ratioTier1, _ratioTier2, _jailDurationTier2, _skipSlashingThreshold);\n }\n\n /**\n * @inheritdoc ISlashBridgeOperator\n */\n function execSlashBridgeOperator(\n address _consensusAddr,\n uint256 _tier,\n uint256 _period\n ) external onlyContract(ContractType.VALIDATOR) {\n if (_tier == 1) {\n emit Slashed(_consensusAddr, SlashType.BRIDGE_OPERATOR_MISSING_VOTE_TIER_1, _period);\n } else if (_tier == 2) {\n emit Slashed(_consensusAddr, SlashType.BRIDGE_OPERATOR_MISSING_VOTE_TIER_2, _period);\n }\n }\n\n /**\n * @dev See `ISlashBridgeOperator-setBridgeOperatorSlashingConfigs`.\n */\n function _setBridgeOperatorSlashingConfigs(\n uint256 _ratioTier1,\n uint256 _ratioTier2,\n uint256 _jailDurationTier2,\n uint256 _skipSlashingThreshold\n ) internal {\n if (_ratioTier1 > _ratioTier2 || _ratioTier1 > _MAX_PERCENTAGE || _ratioTier2 > _MAX_PERCENTAGE) {\n revert ErrInvalidRatios();\n }\n\n _missingVotesRatioTier1 = _ratioTier1;\n _missingVotesRatioTier2 = _ratioTier2;\n _jailDurationForMissingVotesRatioTier2 = _jailDurationTier2;\n _skipBridgeOperatorSlashingThreshold = _skipSlashingThreshold;\n emit BridgeOperatorSlashingConfigsUpdated(_ratioTier1, _ratioTier2, _jailDurationTier2, _skipSlashingThreshold);\n }\n}\n" + }, + "contracts/ronin/slash-indicator/SlashBridgeVoting.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../libraries/Math.sol\";\nimport { HasValidatorDeprecated, HasTrustedOrgDeprecated, HasGovernanceAdminDeprecated } from \"../../utils/DeprecatedSlots.sol\";\nimport { IBridgeAdminProposal } from \"../../interfaces/IBridgeAdminProposal.sol\";\nimport \"../../interfaces/slash-indicator/ISlashBridgeVoting.sol\";\nimport \"../../interfaces/IRoninTrustedOrganization.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\n\n// TODO: remove this from slashing logic of consensus contract\nabstract contract SlashBridgeVoting is\n ISlashBridgeVoting,\n HasContracts,\n HasValidatorDeprecated,\n HasTrustedOrgDeprecated,\n HasGovernanceAdminDeprecated\n{\n /// @dev Mapping from validator address => period index => bridge voting slashed\n mapping(address => mapping(uint256 => bool)) internal _bridgeVotingSlashed;\n /// @dev The threshold to slash when a trusted organization does not vote for bridge operators.\n uint256 internal _bridgeVotingThreshold;\n /// @dev The amount of RON to slash bridge voting.\n uint256 internal _bridgeVotingSlashAmount;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @inheritdoc ISlashBridgeVoting\n */\n function slashBridgeVoting(address _consensusAddr) external onlyAdmin {\n IRoninTrustedOrganization.TrustedOrganization memory _org = IRoninTrustedOrganization(\n getContract(ContractType.RONIN_TRUSTED_ORGANIZATION)\n ).getTrustedOrganization(_consensusAddr);\n uint256 _lastVotedBlock = Math.max(\n IBridgeAdminProposal(getContract(ContractType.BRIDGE_MANAGER)).lastVotedBlock(_org.bridgeVoter),\n _org.addedBlock\n );\n IRoninValidatorSet _validatorContract = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n uint256 _period = _validatorContract.currentPeriod();\n\n if (block.number - _lastVotedBlock <= _bridgeVotingThreshold || _bridgeVotingSlashed[_consensusAddr][_period])\n revert ErrInvalidSlash();\n\n _bridgeVotingSlashed[_consensusAddr][_period] = true;\n emit Slashed(_consensusAddr, SlashType.BRIDGE_VOTING, _period);\n _validatorContract.execSlash(_consensusAddr, 0, _bridgeVotingSlashAmount, false);\n }\n\n /**\n * @inheritdoc ISlashBridgeVoting\n */\n function getBridgeVotingSlashingConfigs()\n external\n view\n override\n returns (uint256 bridgeVotingThreshold_, uint256 bridgeVotingSlashAmount_)\n {\n return (_bridgeVotingThreshold, _bridgeVotingSlashAmount);\n }\n\n /**\n * @inheritdoc ISlashBridgeVoting\n */\n function setBridgeVotingSlashingConfigs(uint256 _threshold, uint256 _slashAmount) external override onlyAdmin {\n _setBridgeVotingSlashingConfigs(_threshold, _slashAmount);\n }\n\n /**\n * @dev See `ISlashBridgeVoting-setBridgeVotingSlashingConfigs`.\n */\n function _setBridgeVotingSlashingConfigs(uint256 _threshold, uint256 _slashAmount) internal {\n _bridgeVotingThreshold = _threshold;\n _bridgeVotingSlashAmount = _slashAmount;\n emit BridgeVotingSlashingConfigsUpdated(_threshold, _slashAmount);\n }\n}\n" + }, + "contracts/ronin/slash-indicator/SlashDoubleSign.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../interfaces/slash-indicator/ISlashDoubleSign.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../precompile-usages/PCUValidateDoubleSign.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport { HasValidatorDeprecated } from \"../../utils/DeprecatedSlots.sol\";\n\nabstract contract SlashDoubleSign is ISlashDoubleSign, HasContracts, HasValidatorDeprecated, PCUValidateDoubleSign {\n /// @dev The amount of RON to slash double sign.\n uint256 internal _slashDoubleSignAmount;\n /// @dev The block number that the punished validator will be jailed until, due to double signing.\n uint256 internal _doubleSigningJailUntilBlock;\n /** @dev The offset from the submitted block to the current block, from which double signing will be invalidated.\n * This parameter is exposed for system transaction.\n **/\n uint256 internal _doubleSigningOffsetLimitBlock;\n /// @dev Recording of submitted proof to prevent relay attack.\n mapping(bytes32 => bool) _submittedEvidence;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[24] private ______gap;\n\n /**\n * @inheritdoc ISlashDoubleSign\n */\n function slashDoubleSign(\n address _consensusAddr,\n bytes calldata _header1,\n bytes calldata _header2\n ) external override onlyAdmin {\n bytes32 _header1Checksum = keccak256(_header1);\n bytes32 _header2Checksum = keccak256(_header2);\n\n if (_submittedEvidence[_header1Checksum] || _submittedEvidence[_header2Checksum]) {\n revert ErrEvidenceAlreadySubmitted();\n }\n\n if (_pcValidateEvidence(_consensusAddr, _header1, _header2)) {\n IRoninValidatorSet _validatorContract = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n uint256 _period = _validatorContract.currentPeriod();\n _submittedEvidence[_header1Checksum] = true;\n _submittedEvidence[_header2Checksum] = true;\n emit Slashed(_consensusAddr, SlashType.DOUBLE_SIGNING, _period);\n _validatorContract.execSlash(_consensusAddr, _doubleSigningJailUntilBlock, _slashDoubleSignAmount, true);\n }\n }\n\n /**\n * @inheritdoc ISlashDoubleSign\n */\n function getDoubleSignSlashingConfigs()\n external\n view\n override\n returns (\n uint256 slashDoubleSignAmount_,\n uint256 doubleSigningJailUntilBlock_,\n uint256 doubleSigningOffsetLimitBlock_\n )\n {\n return (_slashDoubleSignAmount, _doubleSigningJailUntilBlock, _doubleSigningOffsetLimitBlock);\n }\n\n /**\n * @inheritdoc ISlashDoubleSign\n */\n function setDoubleSignSlashingConfigs(\n uint256 _slashAmount,\n uint256 _jailUntilBlock,\n uint256 _offsetLimitBlock\n ) external override onlyAdmin {\n _setDoubleSignSlashingConfigs(_slashAmount, _jailUntilBlock, _offsetLimitBlock);\n }\n\n /**\n * @dev See `ISlashDoubleSign-setDoubleSignSlashingConfigs`.\n */\n function _setDoubleSignSlashingConfigs(\n uint256 _slashAmount,\n uint256 _jailUntilBlock,\n uint256 _offsetLimitBlock\n ) internal {\n _slashDoubleSignAmount = _slashAmount;\n _doubleSigningJailUntilBlock = _jailUntilBlock;\n _doubleSigningOffsetLimitBlock = _offsetLimitBlock;\n emit DoubleSignSlashingConfigsUpdated(_slashAmount, _jailUntilBlock, _doubleSigningOffsetLimitBlock);\n }\n\n /**\n * @dev Returns whether the account `_addr` should be slashed or not.\n */\n function _shouldSlash(address _addr) internal view virtual returns (bool);\n}\n" + }, + "contracts/ronin/slash-indicator/SlashFastFinality.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../interfaces/slash-indicator/ISlashFastFinality.sol\";\nimport { IRoninValidatorSet } from \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport { IProfile } from \"../../interfaces/IProfile.sol\";\nimport { IRoninTrustedOrganization } from \"../../interfaces/IRoninTrustedOrganization.sol\";\nimport \"../../precompile-usages/PCUValidateFastFinality.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../utils/CommonErrors.sol\";\n\nabstract contract SlashFastFinality is ISlashFastFinality, HasContracts, PCUValidateFastFinality {\n /// @dev The amount of RON to slash fast finality.\n uint256 internal _slashFastFinalityAmount;\n /// @dev The block number that the punished validator will be jailed until, due to malicious fast finality.\n uint256 internal _fastFinalityJailUntilBlock;\n /// @dev Recording of submitted proof to prevent relay attack.\n mapping(bytes32 => bool) internal _processedEvidence;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[21] private ______gap;\n\n modifier onlyGoverningValidator() {\n if (_getGovernorWeight(msg.sender) == 0) revert ErrUnauthorized(msg.sig, RoleAccess.GOVERNOR);\n _;\n }\n\n /**\n * @inheritdoc ISlashFastFinality\n */\n function slashFastFinality(\n address consensusAddr,\n bytes calldata voterPublicKey,\n uint256 targetBlockNumber,\n bytes32[2] calldata targetBlockHash,\n bytes[][2] calldata listOfPublicKey,\n bytes[2] calldata aggregatedSignature\n ) external override onlyGoverningValidator {\n IProfile profileContract = IProfile(getContract(ContractType.PROFILE));\n bytes memory expectingPubKey = (profileContract.getId2Profile(consensusAddr)).pubkey;\n if (keccak256(voterPublicKey) != keccak256(expectingPubKey)) revert ErrInvalidArguments(msg.sig);\n\n bytes32 evidenceHash = keccak256(abi.encodePacked(consensusAddr, targetBlockNumber));\n if (_processedEvidence[evidenceHash]) revert ErrEvidenceAlreadySubmitted();\n\n if (\n _pcValidateFastFinalityEvidence(\n voterPublicKey,\n targetBlockNumber,\n targetBlockHash,\n listOfPublicKey,\n aggregatedSignature\n )\n ) {\n _processedEvidence[evidenceHash] = true;\n\n IRoninValidatorSet validatorContract = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n uint256 period = validatorContract.currentPeriod();\n emit Slashed(consensusAddr, SlashType.FAST_FINALITY, period);\n validatorContract.execSlash({\n validatorAddr: consensusAddr,\n newJailedUntil: _fastFinalityJailUntilBlock,\n slashAmount: _slashFastFinalityAmount,\n cannotBailout: true\n });\n }\n }\n\n /**\n * @inheritdoc ISlashFastFinality\n */\n function getFastFinalitySlashingConfigs()\n external\n view\n override\n returns (uint256 slashFastFinalityAmount_, uint256 fastFinalityJailUntilBlock_)\n {\n return (_slashFastFinalityAmount, _fastFinalityJailUntilBlock);\n }\n\n /**\n * @inheritdoc ISlashFastFinality\n */\n function setFastFinalitySlashingConfigs(uint256 slashAmount, uint256 jailUntilBlock) external override onlyAdmin {\n _setFastFinalitySlashingConfigs(slashAmount, jailUntilBlock);\n }\n\n /**\n * @dev See `ISlashFastFinality-setFastFinalitySlashingConfigs`.\n */\n function _setFastFinalitySlashingConfigs(uint256 slashAmount, uint256 jailUntilBlock) internal {\n _slashFastFinalityAmount = slashAmount;\n _fastFinalityJailUntilBlock = jailUntilBlock;\n emit FastFinalitySlashingConfigsUpdated(slashAmount, jailUntilBlock);\n }\n\n /**\n * @dev Get governor, i.e. governing validator's weight, of the `addr`.\n */\n function _getGovernorWeight(address addr) internal view returns (uint256) {\n return IRoninTrustedOrganization(getContract(ContractType.RONIN_TRUSTED_ORGANIZATION)).getGovernorWeight(addr);\n }\n}\n" + }, + "contracts/ronin/slash-indicator/SlashIndicator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../../interfaces/slash-indicator/ISlashIndicator.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../interfaces/IMaintenance.sol\";\nimport \"./SlashDoubleSign.sol\";\nimport \"./SlashFastFinality.sol\";\nimport \"./SlashBridgeVoting.sol\";\nimport \"./SlashBridgeOperator.sol\";\nimport \"./SlashUnavailability.sol\";\nimport \"./CreditScore.sol\";\n\ncontract SlashIndicator is\n ISlashIndicator,\n SlashDoubleSign,\n SlashFastFinality,\n SlashBridgeVoting,\n SlashBridgeOperator,\n SlashUnavailability,\n CreditScore,\n Initializable\n{\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the contract storage.\n */\n function initialize(\n address __validatorContract,\n address __maintenanceContract,\n address __roninTrustedOrganizationContract,\n address __roninGovernanceAdminContract,\n // _bridgeOperatorSlashingConfigs[0]: _missingVotesRatioTier1\n // _bridgeOperatorSlashingConfigs[1]: _missingVotesRatioTier2\n // _bridgeOperatorSlashingConfigs[2]: _jailDurationForMissingVotesRatioTier2\n // _bridgeOperatorSlashingConfigs[3]: _skipBridgeOperatorSlashingThreshold\n uint256[4] calldata _bridgeOperatorSlashingConfigs,\n // _bridgeVotingSlashingConfigs[0]: _bridgeVotingThreshold\n // _bridgeVotingSlashingConfigs[1]: _bridgeVotingSlashAmount\n uint256[2] calldata _bridgeVotingSlashingConfigs,\n // _doubleSignSlashingConfigs[0]: _slashDoubleSignAmount\n // _doubleSignSlashingConfigs[1]: _doubleSigningJailUntilBlock\n // _doubleSignSlashingConfigs[2]: _doubleSigningOffsetLimitBlock\n uint256[3] calldata _doubleSignSlashingConfigs,\n // _unavailabilitySlashingConfigs[0]: _unavailabilityTier1Threshold\n // _unavailabilitySlashingConfigs[1]: _unavailabilityTier2Threshold\n // _unavailabilitySlashingConfigs[2]: _slashAmountForUnavailabilityTier2Threshold\n // _unavailabilitySlashingConfigs[3]: _jailDurationForUnavailabilityTier2Threshold\n uint256[4] calldata _unavailabilitySlashingConfigs,\n // _creditScoreConfigs[0]: _gainCreditScore\n // _creditScoreConfigs[1]: _maxCreditScore\n // _creditScoreConfigs[2]: _bailOutCostMultiplier\n // _creditScoreConfigs[3]: _cutOffPercentageAfterBailout\n uint256[4] calldata _creditScoreConfigs\n ) external initializer {\n _setContract(ContractType.VALIDATOR, __validatorContract);\n _setContract(ContractType.MAINTENANCE, __maintenanceContract);\n _setContract(ContractType.GOVERNANCE_ADMIN, __roninGovernanceAdminContract);\n _setContract(ContractType.RONIN_TRUSTED_ORGANIZATION, __roninTrustedOrganizationContract);\n\n _setBridgeOperatorSlashingConfigs(\n _bridgeOperatorSlashingConfigs[0],\n _bridgeOperatorSlashingConfigs[1],\n _bridgeOperatorSlashingConfigs[2],\n _bridgeOperatorSlashingConfigs[3]\n );\n _setBridgeVotingSlashingConfigs(_bridgeVotingSlashingConfigs[0], _bridgeVotingSlashingConfigs[1]);\n _setDoubleSignSlashingConfigs(\n _doubleSignSlashingConfigs[0],\n _doubleSignSlashingConfigs[1],\n _doubleSignSlashingConfigs[2]\n );\n _setUnavailabilitySlashingConfigs(\n _unavailabilitySlashingConfigs[0],\n _unavailabilitySlashingConfigs[1],\n _unavailabilitySlashingConfigs[2],\n _unavailabilitySlashingConfigs[3]\n );\n _setCreditScoreConfigs(\n _creditScoreConfigs[0],\n _creditScoreConfigs[1],\n _creditScoreConfigs[2],\n _creditScoreConfigs[3]\n );\n }\n\n function initializeV2(address roninGovernanceAdminContract) external reinitializer(2) {\n _setContract(ContractType.VALIDATOR, ______deprecatedValidator);\n _setContract(ContractType.MAINTENANCE, ______deprecatedMaintenance);\n _setContract(ContractType.GOVERNANCE_ADMIN, roninGovernanceAdminContract);\n _setContract(ContractType.RONIN_TRUSTED_ORGANIZATION, ______deprecatedTrustedOrg);\n\n delete ______deprecatedValidator;\n delete ______deprecatedMaintenance;\n delete ______deprecatedTrustedOrg;\n delete ______deprecatedGovernanceAdmin;\n }\n\n function initializeV3(address profileContract) external reinitializer(3) {\n _setContract(ContractType.PROFILE, profileContract);\n _setFastFinalitySlashingConfigs(_slashDoubleSignAmount, _doubleSigningJailUntilBlock);\n }\n\n /**\n * @dev Helper for CreditScore contract to reset the indicator of the validator after bailing out.\n */\n function _setUnavailabilityIndicator(\n address _validator,\n uint256 _period,\n uint256 _indicator\n ) internal override(CreditScore, SlashUnavailability) {\n SlashUnavailability._setUnavailabilityIndicator(_validator, _period, _indicator);\n }\n\n /**\n * @dev Helper for CreditScore contract to query indicator of the validator.\n */\n function getUnavailabilityIndicator(\n address _validator,\n uint256 _period\n ) public view override(CreditScore, ISlashUnavailability, SlashUnavailability) returns (uint256) {\n return SlashUnavailability.getUnavailabilityIndicator(_validator, _period);\n }\n\n /**\n * @inheritdoc ICreditScore\n */\n function checkBailedOutAtPeriod(\n address _validator,\n uint256 _period\n ) public view override(CreditScore, ICreditScore, SlashUnavailability) returns (bool) {\n return CreditScore.checkBailedOutAtPeriod(_validator, _period);\n }\n\n /**\n * @dev Sanity check the address to be slashed\n */\n function _shouldSlash(address _addr) internal view override(SlashDoubleSign, SlashUnavailability) returns (bool) {\n return\n (msg.sender != _addr) &&\n IRoninValidatorSet(getContract(ContractType.VALIDATOR)).isBlockProducer(_addr) &&\n !IMaintenance(getContract(ContractType.MAINTENANCE)).checkMaintained(_addr, block.number);\n }\n}\n" + }, + "contracts/ronin/slash-indicator/SlashUnavailability.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"./CreditScore.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../interfaces/slash-indicator/ISlashUnavailability.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport { HasValidatorDeprecated } from \"../../utils/DeprecatedSlots.sol\";\nimport { ErrInvalidThreshold } from \"../../utils/CommonErrors.sol\";\n\nabstract contract SlashUnavailability is ISlashUnavailability, HasContracts, HasValidatorDeprecated {\n /// @dev The last block that a validator is slashed for unavailability.\n uint256 public lastUnavailabilitySlashedBlock;\n /// @dev Mapping from validator address => period index => unavailability indicator.\n mapping(address => mapping(uint256 => uint256)) internal _unavailabilityIndicator;\n\n /**\n * @dev The mining reward will be deprecated, if (s)he missed more than this threshold.\n * This threshold is applied for tier-1 and tier-3 of unavailability slash.\n */\n uint256 internal _unavailabilityTier1Threshold;\n /**\n * @dev The mining reward will be deprecated, (s)he will be put in jailed, and will be deducted\n * self-staking if (s)he misses more than this threshold. This threshold is applied for tier-2 slash.\n */\n uint256 internal _unavailabilityTier2Threshold;\n /**\n * @dev The amount of RON to deduct from self-staking of a block producer when (s)he is slashed with\n * tier-2 or tier-3.\n **/\n uint256 internal _slashAmountForUnavailabilityTier2Threshold;\n /// @dev The number of blocks to jail a block producer when (s)he is slashed with tier-2 or tier-3.\n uint256 internal _jailDurationForUnavailabilityTier2Threshold;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n modifier oncePerBlock() {\n if (block.number <= lastUnavailabilitySlashedBlock) {\n revert ErrCannotSlashAValidatorTwiceOrSlashMoreThanOneValidatorInOneBlock();\n }\n\n lastUnavailabilitySlashedBlock = block.number;\n _;\n }\n\n /**\n * @inheritdoc ISlashUnavailability\n */\n function slashUnavailability(address _validatorAddr) external override oncePerBlock {\n if (msg.sender != block.coinbase) revert ErrUnauthorized(msg.sig, RoleAccess.COINBASE);\n\n if (!_shouldSlash(_validatorAddr)) {\n // Should return instead of throwing error since this is a part of system transaction.\n return;\n }\n\n IRoninValidatorSet _validatorContract = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n uint256 _period = _validatorContract.currentPeriod();\n uint256 _count;\n unchecked {\n _count = ++_unavailabilityIndicator[_validatorAddr][_period];\n }\n uint256 _newJailedUntilBlock = Math.addIfNonZero(block.number, _jailDurationForUnavailabilityTier2Threshold);\n\n if (_count == _unavailabilityTier2Threshold) {\n emit Slashed(_validatorAddr, SlashType.UNAVAILABILITY_TIER_2, _period);\n _validatorContract.execSlash(\n _validatorAddr,\n _newJailedUntilBlock,\n _slashAmountForUnavailabilityTier2Threshold,\n false\n );\n } else if (_count == _unavailabilityTier1Threshold) {\n bool _tier1SecondTime = checkBailedOutAtPeriod(_validatorAddr, _period);\n if (!_tier1SecondTime) {\n emit Slashed(_validatorAddr, SlashType.UNAVAILABILITY_TIER_1, _period);\n _validatorContract.execSlash(_validatorAddr, 0, 0, false);\n } else {\n /// Handles tier-3\n emit Slashed(_validatorAddr, SlashType.UNAVAILABILITY_TIER_3, _period);\n _validatorContract.execSlash(\n _validatorAddr,\n _newJailedUntilBlock,\n _slashAmountForUnavailabilityTier2Threshold,\n true\n );\n }\n }\n }\n\n /**\n * @inheritdoc ISlashUnavailability\n */\n function setUnavailabilitySlashingConfigs(\n uint256 _tier1Threshold,\n uint256 _tier2Threshold,\n uint256 _slashAmountForTier2Threshold,\n uint256 _jailDurationForTier2Threshold\n ) external override onlyAdmin {\n _setUnavailabilitySlashingConfigs(\n _tier1Threshold,\n _tier2Threshold,\n _slashAmountForTier2Threshold,\n _jailDurationForTier2Threshold\n );\n }\n\n /**\n * @inheritdoc ISlashUnavailability\n */\n function getUnavailabilitySlashingConfigs()\n external\n view\n override\n returns (\n uint256 unavailabilityTier1Threshold_,\n uint256 unavailabilityTier2Threshold_,\n uint256 slashAmountForUnavailabilityTier2Threshold_,\n uint256 jailDurationForUnavailabilityTier2Threshold_\n )\n {\n return (\n _unavailabilityTier1Threshold,\n _unavailabilityTier2Threshold,\n _slashAmountForUnavailabilityTier2Threshold,\n _jailDurationForUnavailabilityTier2Threshold\n );\n }\n\n /**\n * @inheritdoc ISlashUnavailability\n */\n function currentUnavailabilityIndicator(address _validator) external view override returns (uint256) {\n return\n getUnavailabilityIndicator(_validator, IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod());\n }\n\n /**\n * @inheritdoc ISlashUnavailability\n */\n function getUnavailabilityIndicator(\n address _validator,\n uint256 _period\n ) public view virtual override returns (uint256) {\n return _unavailabilityIndicator[_validator][_period];\n }\n\n /**\n * @dev Sets the unavailability indicator of the `_validator` at `_period`.\n */\n function _setUnavailabilityIndicator(address _validator, uint256 _period, uint256 _indicator) internal virtual {\n _unavailabilityIndicator[_validator][_period] = _indicator;\n }\n\n /**\n * @dev See `ISlashUnavailability-setUnavailabilitySlashingConfigs`.\n */\n function _setUnavailabilitySlashingConfigs(\n uint256 _tier1Threshold,\n uint256 _tier2Threshold,\n uint256 _slashAmountForTier2Threshold,\n uint256 _jailDurationForTier2Threshold\n ) internal {\n if (_unavailabilityTier1Threshold > _unavailabilityTier2Threshold) revert ErrInvalidThreshold(msg.sig);\n\n _unavailabilityTier1Threshold = _tier1Threshold;\n _unavailabilityTier2Threshold = _tier2Threshold;\n _slashAmountForUnavailabilityTier2Threshold = _slashAmountForTier2Threshold;\n _jailDurationForUnavailabilityTier2Threshold = _jailDurationForTier2Threshold;\n emit UnavailabilitySlashingConfigsUpdated(\n _tier1Threshold,\n _tier2Threshold,\n _slashAmountForTier2Threshold,\n _jailDurationForTier2Threshold\n );\n }\n\n /**\n * @dev Returns whether the account `_addr` should be slashed or not.\n */\n function _shouldSlash(address _addr) internal view virtual returns (bool);\n\n /**\n * @dev See `ICreditScore-checkBailedOutAtPeriod`\n */\n function checkBailedOutAtPeriod(address _validator, uint256 _period) public view virtual returns (bool);\n}\n" + }, + "contracts/ronin/staking/BaseStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"../../extensions/RONTransferHelper.sol\";\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../interfaces/staking/IBaseStaking.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"../../libraries/Math.sol\";\nimport { HasValidatorDeprecated } from \"../../utils/DeprecatedSlots.sol\";\nimport \"./RewardCalculation.sol\";\n\nabstract contract BaseStaking is\n RONTransferHelper,\n ReentrancyGuard,\n RewardCalculation,\n HasContracts,\n IBaseStaking,\n HasValidatorDeprecated\n{\n /// @dev Mapping from pool address => staking pool detail\n mapping(address => PoolDetail) internal _stakingPool;\n\n /// @dev The cooldown time in seconds to undelegate from the last timestamp (s)he delegated.\n uint256 internal _cooldownSecsToUndelegate;\n /// @dev The number of seconds that a candidate must wait to be revoked and take the self-staking amount back.\n uint256 internal _waitingSecsToRevoke;\n\n /// @dev Mapping from admin address of an active pool => consensus address.\n mapping(address => address) internal _adminOfActivePoolMapping;\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[49] private ______gap;\n\n modifier noEmptyValue() {\n _requireValue();\n _;\n }\n\n modifier anyExceptPoolAdmin(PoolDetail storage _pool, address _delegator) {\n _anyExceptPoolAdmin(_pool, _delegator);\n _;\n }\n\n modifier onlyPoolAdmin(PoolDetail storage _pool, address _requester) {\n _requirePoolAdmin(_pool, _requester);\n _;\n }\n\n modifier poolIsActive(address _poolAddr) {\n _poolIsActive(_poolAddr);\n _;\n }\n\n function _requireValue() private view {\n if (msg.value == 0) revert ErrZeroValue();\n }\n\n function _requirePoolAdmin(PoolDetail storage _pool, address _requester) private view {\n if (_pool.admin != _requester) revert ErrOnlyPoolAdminAllowed();\n }\n\n function _anyExceptPoolAdmin(PoolDetail storage _pool, address _delegator) private view {\n if (_pool.admin == _delegator) revert ErrPoolAdminForbidden();\n }\n\n function _poolIsActive(address _poolAddr) private view {\n if (!IRoninValidatorSet(getContract(ContractType.VALIDATOR)).isValidatorCandidate(_poolAddr))\n revert ErrInactivePool(_poolAddr);\n }\n\n /**\n * @inheritdoc IBaseStaking\n */\n function isAdminOfActivePool(address _poolAdminAddr) public view override returns (bool) {\n return _adminOfActivePoolMapping[_poolAdminAddr] != address(0);\n }\n\n /**\n * @inheritdoc IBaseStaking\n */\n function getPoolAddressOf(address _poolAdminAddr) external view override returns (address) {\n return _adminOfActivePoolMapping[_poolAdminAddr];\n }\n\n /**\n * @inheritdoc IBaseStaking\n */\n function getPoolDetail(\n address _poolAddr\n ) external view returns (address _admin, uint256 _stakingAmount, uint256 _stakingTotal) {\n PoolDetail storage _pool = _stakingPool[_poolAddr];\n return (_pool.admin, _pool.stakingAmount, _pool.stakingTotal);\n }\n\n /**\n * @inheritdoc IBaseStaking\n */\n function getManySelfStakings(address[] calldata _pools) external view returns (uint256[] memory _selfStakings) {\n _selfStakings = new uint256[](_pools.length);\n for (uint _i = 0; _i < _pools.length; ) {\n _selfStakings[_i] = _stakingPool[_pools[_i]].stakingAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRewardPool\n */\n function getStakingTotal(address _poolAddr) public view override returns (uint256) {\n return _stakingPool[_poolAddr].stakingTotal;\n }\n\n /**\n * @inheritdoc IRewardPool\n */\n function getManyStakingTotals(\n address[] calldata _poolList\n ) public view override returns (uint256[] memory _stakingAmounts) {\n _stakingAmounts = new uint256[](_poolList.length);\n for (uint _i = 0; _i < _poolList.length; ) {\n _stakingAmounts[_i] = getStakingTotal(_poolList[_i]);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IRewardPool\n */\n function getStakingAmount(address _poolAddr, address _user) public view override returns (uint256) {\n return _stakingPool[_poolAddr].delegatingAmount[_user];\n }\n\n /**\n * @inheritdoc IRewardPool\n */\n function getManyStakingAmounts(\n address[] calldata _poolAddrs,\n address[] calldata _userList\n ) external view override returns (uint256[] memory _stakingAmounts) {\n if (_poolAddrs.length != _userList.length) revert ErrInvalidArrays();\n _stakingAmounts = new uint256[](_poolAddrs.length);\n for (uint _i = 0; _i < _stakingAmounts.length; ) {\n _stakingAmounts[_i] = _stakingPool[_poolAddrs[_i]].delegatingAmount[_userList[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IBaseStaking\n */\n function cooldownSecsToUndelegate() external view returns (uint256) {\n return _cooldownSecsToUndelegate;\n }\n\n /**\n * @inheritdoc IBaseStaking\n */\n function waitingSecsToRevoke() external view returns (uint256) {\n return _waitingSecsToRevoke;\n }\n\n /**\n * @inheritdoc IBaseStaking\n */\n function setCooldownSecsToUndelegate(uint256 _cooldownSecs) external override onlyAdmin {\n _setCooldownSecsToUndelegate(_cooldownSecs);\n }\n\n /**\n * @inheritdoc IBaseStaking\n */\n function setWaitingSecsToRevoke(uint256 _secs) external override onlyAdmin {\n _setWaitingSecsToRevoke(_secs);\n }\n\n /**\n * @dev Sets the minium number of seconds to undelegate.\n *\n * Emits the event `CooldownSecsToUndelegateUpdated`.\n *\n */\n function _setCooldownSecsToUndelegate(uint256 _cooldownSecs) internal {\n _cooldownSecsToUndelegate = _cooldownSecs;\n emit CooldownSecsToUndelegateUpdated(_cooldownSecs);\n }\n\n /**\n * @dev Sets the number of seconds that a candidate must wait to be revoked.\n *\n * Emits the event `WaitingSecsToRevokeUpdated`.\n *\n */\n function _setWaitingSecsToRevoke(uint256 _secs) internal {\n _waitingSecsToRevoke = _secs;\n emit WaitingSecsToRevokeUpdated(_secs);\n }\n\n /**\n * @dev Changes the delegate amount.\n */\n function _changeDelegatingAmount(\n PoolDetail storage _pool,\n address _delegator,\n uint256 _newDelegatingAmount,\n uint256 _newStakingTotal\n ) internal {\n _syncUserReward(_pool.addr, _delegator, _newDelegatingAmount);\n _pool.stakingTotal = _newStakingTotal;\n _pool.delegatingAmount[_delegator] = _newDelegatingAmount;\n }\n}\n" + }, + "contracts/ronin/staking/CandidateStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../extensions/consumers/GlobalConfigConsumer.sol\";\nimport \"../../extensions/consumers/PercentageConsumer.sol\";\nimport \"../../libraries/AddressArrayUtils.sol\";\nimport \"../../interfaces/staking/ICandidateStaking.sol\";\nimport \"./BaseStaking.sol\";\n\nabstract contract CandidateStaking is BaseStaking, ICandidateStaking, GlobalConfigConsumer, PercentageConsumer {\n /// @dev The minimum threshold for being a validator candidate.\n uint256 internal _minValidatorStakingAmount;\n\n /// @dev The max commission rate that the validator can set (in range of [0;100_00] means [0-100%])\n uint256 internal _maxCommissionRate;\n /// @dev The min commission rate that the validator can set (in range of [0;100_00] means [0-100%])\n uint256 internal _minCommissionRate;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[48] ______gap;\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function minValidatorStakingAmount() public view override returns (uint256) {\n return _minValidatorStakingAmount;\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function getCommissionRateRange() external view override returns (uint256, uint256) {\n return (_minCommissionRate, _maxCommissionRate);\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function setMinValidatorStakingAmount(uint256 _threshold) external override onlyAdmin {\n _setMinValidatorStakingAmount(_threshold);\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function setCommissionRateRange(uint256 _minRate, uint256 _maxRate) external override onlyAdmin {\n _setCommissionRateRange(_minRate, _maxRate);\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function applyValidatorCandidate(\n address _candidateAdmin,\n address _consensusAddr,\n address payable _treasuryAddr,\n uint256 _commissionRate\n ) external payable override nonReentrant {\n if (isAdminOfActivePool(msg.sender)) revert ErrAdminOfAnyActivePoolForbidden(msg.sender);\n if (_commissionRate > _maxCommissionRate || _commissionRate < _minCommissionRate) revert ErrInvalidCommissionRate();\n\n uint256 _amount = msg.value;\n address payable _poolAdmin = payable(msg.sender);\n _applyValidatorCandidate({\n _poolAdmin: _poolAdmin,\n _candidateAdmin: _candidateAdmin,\n _consensusAddr: _consensusAddr,\n _treasuryAddr: _treasuryAddr,\n _commissionRate: _commissionRate,\n _amount: _amount\n });\n\n PoolDetail storage _pool = _stakingPool[_consensusAddr];\n _pool.admin = _poolAdmin;\n _pool.addr = _consensusAddr;\n _adminOfActivePoolMapping[_poolAdmin] = _consensusAddr;\n\n _stake(_stakingPool[_consensusAddr], _poolAdmin, _amount);\n emit PoolApproved(_consensusAddr, _poolAdmin);\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function requestUpdateCommissionRate(\n address _consensusAddr,\n uint256 _effectiveDaysOnwards,\n uint256 _commissionRate\n ) external override poolIsActive(_consensusAddr) onlyPoolAdmin(_stakingPool[_consensusAddr], msg.sender) {\n if (_commissionRate > _maxCommissionRate || _commissionRate < _minCommissionRate) revert ErrInvalidCommissionRate();\n IRoninValidatorSet(getContract(ContractType.VALIDATOR)).execRequestUpdateCommissionRate(\n _consensusAddr,\n _effectiveDaysOnwards,\n _commissionRate\n );\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function execDeprecatePools(\n address[] calldata _pools,\n uint256 _newPeriod\n ) external override onlyContract(ContractType.VALIDATOR) {\n if (_pools.length == 0) {\n return;\n }\n\n for (uint _i = 0; _i < _pools.length; ) {\n PoolDetail storage _pool = _stakingPool[_pools[_i]];\n // Deactivate the pool admin in the active mapping.\n delete _adminOfActivePoolMapping[_pool.admin];\n\n // Deduct and transfer the self staking amount to the pool admin.\n uint256 _deductingAmount = _pool.stakingAmount;\n if (_deductingAmount > 0) {\n _deductStakingAmount(_pool, _deductingAmount);\n if (!_unsafeSendRONLimitGas(payable(_pool.admin), _deductingAmount, DEFAULT_ADDITION_GAS)) {\n emit StakingAmountTransferFailed(_pool.addr, _pool.admin, _deductingAmount, address(this).balance);\n }\n }\n\n // Settle the unclaimed reward and transfer to the pool admin.\n uint256 _lastRewardAmount = _claimReward(_pools[_i], _pool.admin, _newPeriod);\n if (_lastRewardAmount > 0) {\n _unsafeSendRONLimitGas(payable(_pool.admin), _lastRewardAmount, DEFAULT_ADDITION_GAS);\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit PoolsDeprecated(_pools);\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function stake(address _consensusAddr) external payable override noEmptyValue poolIsActive(_consensusAddr) {\n _stake(_stakingPool[_consensusAddr], msg.sender, msg.value);\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function unstake(\n address _consensusAddr,\n uint256 _amount\n ) external override nonReentrant poolIsActive(_consensusAddr) {\n if (_amount == 0) revert ErrUnstakeZeroAmount();\n address _requester = msg.sender;\n PoolDetail storage _pool = _stakingPool[_consensusAddr];\n uint256 _remainAmount = _pool.stakingAmount - _amount;\n if (_remainAmount < _minValidatorStakingAmount) revert ErrStakingAmountLeft();\n\n _unstake(_pool, _requester, _amount);\n if (!_unsafeSendRONLimitGas(payable(_requester), _amount, DEFAULT_ADDITION_GAS)) revert ErrCannotTransferRON();\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function requestRenounce(\n address _consensusAddr\n ) external override poolIsActive(_consensusAddr) onlyPoolAdmin(_stakingPool[_consensusAddr], msg.sender) {\n IRoninValidatorSet(getContract(ContractType.VALIDATOR)).execRequestRenounceCandidate(\n _consensusAddr,\n _waitingSecsToRevoke\n );\n }\n\n /**\n * @inheritdoc ICandidateStaking\n */\n function requestEmergencyExit(\n address _consensusAddr\n ) external override poolIsActive(_consensusAddr) onlyPoolAdmin(_stakingPool[_consensusAddr], msg.sender) {\n IRoninValidatorSet(getContract(ContractType.VALIDATOR)).execEmergencyExit(_consensusAddr, _waitingSecsToRevoke);\n }\n\n /**\n * @dev See `ICandidateStaking-applyValidatorCandidate`\n */\n function _applyValidatorCandidate(\n address payable _poolAdmin,\n address _candidateAdmin,\n address _consensusAddr,\n address payable _treasuryAddr,\n uint256 _commissionRate,\n uint256 _amount\n ) internal {\n if (!_unsafeSendRONLimitGas(_poolAdmin, 0, DEFAULT_ADDITION_GAS))\n revert ErrCannotInitTransferRON(_poolAdmin, \"pool admin\");\n if (!_unsafeSendRONLimitGas(_treasuryAddr, 0, DEFAULT_ADDITION_GAS))\n revert ErrCannotInitTransferRON(_treasuryAddr, \"treasury\");\n if (_amount < _minValidatorStakingAmount) revert ErrInsufficientStakingAmount();\n if (_poolAdmin != _candidateAdmin || _candidateAdmin != _treasuryAddr) revert ErrThreeInteractionAddrsNotEqual();\n\n {\n address[] memory _diffAddrs = new address[](2);\n _diffAddrs[0] = _poolAdmin;\n _diffAddrs[1] = _consensusAddr;\n if (AddressArrayUtils.hasDuplicate(_diffAddrs)) revert AddressArrayUtils.ErrDuplicated(msg.sig);\n }\n\n IRoninValidatorSet(getContract(ContractType.VALIDATOR)).execApplyValidatorCandidate(\n _candidateAdmin,\n _consensusAddr,\n _treasuryAddr,\n _commissionRate\n );\n }\n\n /**\n * @dev See `ICandidateStaking-stake`\n */\n function _stake(\n PoolDetail storage _pool,\n address _requester,\n uint256 _amount\n ) internal onlyPoolAdmin(_pool, _requester) {\n _pool.stakingAmount += _amount;\n _changeDelegatingAmount(_pool, _requester, _pool.stakingAmount, _pool.stakingTotal + _amount);\n _pool.lastDelegatingTimestamp[_requester] = block.timestamp;\n emit Staked(_pool.addr, _amount);\n }\n\n /**\n * @dev See `ICandidateStaking-unstake`\n */\n function _unstake(\n PoolDetail storage _pool,\n address _requester,\n uint256 _amount\n ) internal onlyPoolAdmin(_pool, _requester) {\n if (_amount > _pool.stakingAmount) revert ErrInsufficientStakingAmount();\n if (_pool.lastDelegatingTimestamp[_requester] + _cooldownSecsToUndelegate > block.timestamp) {\n revert ErrUnstakeTooEarly();\n }\n\n _pool.stakingAmount -= _amount;\n _changeDelegatingAmount(_pool, _requester, _pool.stakingAmount, _pool.stakingTotal - _amount);\n emit Unstaked(_pool.addr, _amount);\n }\n\n /**\n * @dev Deducts from staking amount of the validator `_consensusAddr` for `_amount`.\n *\n * Emits the event `Unstaked`.\n *\n * @return The actual deducted amount\n */\n function _deductStakingAmount(PoolDetail storage _pool, uint256 _amount) internal virtual returns (uint256);\n\n /**\n * @dev Sets the minimum threshold for being a validator candidate.\n *\n * Emits the `MinValidatorStakingAmountUpdated` event.\n *\n */\n function _setMinValidatorStakingAmount(uint256 _threshold) internal {\n _minValidatorStakingAmount = _threshold;\n emit MinValidatorStakingAmountUpdated(_threshold);\n }\n\n /**\n * @dev Sets the max commission rate that a candidate can set.\n *\n * Emits the `MaxCommissionRateUpdated` event.\n *\n */\n function _setCommissionRateRange(uint256 _minRate, uint256 _maxRate) internal {\n if (_maxRate > _MAX_PERCENTAGE || _minRate > _maxRate) revert ErrInvalidCommissionRate();\n _maxCommissionRate = _maxRate;\n _minCommissionRate = _minRate;\n emit CommissionRateRangeUpdated(_minRate, _maxRate);\n }\n}\n" + }, + "contracts/ronin/staking/DelegatorStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../interfaces/staking/IDelegatorStaking.sol\";\nimport \"./BaseStaking.sol\";\n\nabstract contract DelegatorStaking is BaseStaking, IDelegatorStaking {\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @inheritdoc IDelegatorStaking\n */\n function delegate(address _consensusAddr) external payable noEmptyValue poolIsActive(_consensusAddr) {\n if (isAdminOfActivePool(msg.sender)) revert ErrAdminOfAnyActivePoolForbidden(msg.sender);\n _delegate(_stakingPool[_consensusAddr], msg.sender, msg.value);\n }\n\n /**\n * @inheritdoc IDelegatorStaking\n */\n function undelegate(address _consensusAddr, uint256 _amount) external nonReentrant {\n address payable _delegator = payable(msg.sender);\n _undelegate(_stakingPool[_consensusAddr], _delegator, _amount);\n if (!_sendRON(_delegator, _amount)) revert ErrCannotTransferRON();\n }\n\n /**\n * @inheritdoc IDelegatorStaking\n */\n function bulkUndelegate(address[] calldata _consensusAddrs, uint256[] calldata _amounts) external nonReentrant {\n if (_consensusAddrs.length == 0 || _consensusAddrs.length != _amounts.length) revert ErrInvalidArrays();\n\n address payable _delegator = payable(msg.sender);\n uint256 _total;\n\n for (uint _i = 0; _i < _consensusAddrs.length; ) {\n _total += _amounts[_i];\n _undelegate(_stakingPool[_consensusAddrs[_i]], _delegator, _amounts[_i]);\n\n unchecked {\n ++_i;\n }\n }\n\n if (!_sendRON(_delegator, _total)) revert ErrCannotTransferRON();\n }\n\n /**\n * @inheritdoc IDelegatorStaking\n */\n function redelegate(\n address _consensusAddrSrc,\n address _consensusAddrDst,\n uint256 _amount\n ) external nonReentrant poolIsActive(_consensusAddrDst) {\n address _delegator = msg.sender;\n _undelegate(_stakingPool[_consensusAddrSrc], _delegator, _amount);\n _delegate(_stakingPool[_consensusAddrDst], _delegator, _amount);\n }\n\n /**\n * @inheritdoc IDelegatorStaking\n */\n function claimRewards(\n address[] calldata _consensusAddrList\n ) external override nonReentrant returns (uint256 _amount) {\n _amount = _claimRewards(msg.sender, _consensusAddrList);\n _transferRON(payable(msg.sender), _amount);\n }\n\n /**\n * @inheritdoc IDelegatorStaking\n */\n function delegateRewards(\n address[] calldata _consensusAddrList,\n address _consensusAddrDst\n ) external override nonReentrant poolIsActive(_consensusAddrDst) returns (uint256 _amount) {\n if (isAdminOfActivePool(msg.sender)) revert ErrAdminOfAnyActivePoolForbidden(msg.sender);\n return _delegateRewards(msg.sender, _consensusAddrList, _consensusAddrDst);\n }\n\n /**\n * @inheritdoc IDelegatorStaking\n */\n function getRewards(\n address _user,\n address[] calldata _poolAddrList\n ) external view returns (uint256[] memory _rewards) {\n address _consensusAddr;\n uint256 _period = IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod();\n _rewards = new uint256[](_poolAddrList.length);\n\n for (uint256 _i = 0; _i < _poolAddrList.length; ) {\n _consensusAddr = _poolAddrList[_i];\n _rewards[_i] = _getReward(_consensusAddr, _user, _period, getStakingAmount(_consensusAddr, _user));\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @dev Delegates from a validator address.\n *\n * Requirements:\n * - The delegator is not the pool admin.\n *\n * Emits the `Delegated` event.\n *\n * Note: This function does not verify the `msg.value` with the amount.\n *\n */\n function _delegate(\n PoolDetail storage _pool,\n address _delegator,\n uint256 _amount\n ) internal anyExceptPoolAdmin(_pool, _delegator) {\n _changeDelegatingAmount(\n _pool,\n _delegator,\n _pool.delegatingAmount[_delegator] + _amount,\n _pool.stakingTotal + _amount\n );\n _pool.lastDelegatingTimestamp[_delegator] = block.timestamp;\n emit Delegated(_delegator, _pool.addr, _amount);\n }\n\n /**\n * @dev Undelegates from a validator address.\n *\n * Requirements:\n * - The delegator is not the pool admin.\n * - The amount is larger than 0.\n * - The delegating amount is larger than or equal to the undelegating amount.\n *\n * Emits the `Undelegated` event.\n *\n * Note: Consider transferring back the amount of RON after calling this function.\n *\n */\n function _undelegate(\n PoolDetail storage _pool,\n address _delegator,\n uint256 _amount\n ) private anyExceptPoolAdmin(_pool, _delegator) {\n if (_amount == 0) revert ErrUndelegateZeroAmount();\n if (_pool.delegatingAmount[_delegator] < _amount) revert ErrInsufficientDelegatingAmount();\n\n IRoninValidatorSet _validatorContract = IRoninValidatorSet(getContract(ContractType.VALIDATOR));\n if (\n _validatorContract.isValidatorCandidate(_pool.addr) &&\n _validatorContract.getCandidateInfo(_pool.addr).revokingTimestamp == 0 && // if candidate is not on renunciation\n _pool.lastDelegatingTimestamp[_delegator] + _cooldownSecsToUndelegate >= block.timestamp // delegator is still in cooldown\n ) revert ErrUndelegateTooEarly();\n\n _changeDelegatingAmount(\n _pool,\n _delegator,\n _pool.delegatingAmount[_delegator] - _amount,\n _pool.stakingTotal - _amount\n );\n emit Undelegated(_delegator, _pool.addr, _amount);\n }\n\n /**\n * @dev Claims rewards from the pools `_poolAddrList`.\n * Note: This function does not transfer reward to user.\n */\n function _claimRewards(address _user, address[] memory _poolAddrList) internal returns (uint256 _amount) {\n uint256 _period = _currentPeriod();\n for (uint256 _i = 0; _i < _poolAddrList.length; ) {\n _amount += _claimReward(_poolAddrList[_i], _user, _period);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @dev Claims the rewards and delegates them to the consensus address.\n */\n function _delegateRewards(\n address _user,\n address[] calldata _poolAddrList,\n address _poolAddrDst\n ) internal returns (uint256 _amount) {\n _amount = _claimRewards(_user, _poolAddrList);\n _delegate(_stakingPool[_poolAddrDst], _user, _amount);\n }\n}\n" + }, + "contracts/ronin/staking/RewardCalculation.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../interfaces/staking/IRewardPool.sol\";\nimport \"../../libraries/Math.sol\";\n\n/**\n * @title RewardCalculation contract\n * @dev This contract mainly contains the methods to calculate reward for staking contract.\n */\nabstract contract RewardCalculation is IRewardPool {\n /// @dev Mapping from pool address => period number => accumulated rewards per share (one unit staking)\n mapping(address => mapping(uint256 => PeriodWrapper)) private _accumulatedRps;\n /// @dev Mapping from the pool address => user address => the reward info of the user\n mapping(address => mapping(address => UserRewardFields)) private _userReward;\n /// @dev Mapping from the pool address => reward pool fields\n mapping(address => PoolFields) private _stakingPool;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @inheritdoc IRewardPool\n */\n function getReward(address _poolAddr, address _user) external view returns (uint256) {\n return _getReward(_poolAddr, _user, _currentPeriod(), getStakingAmount(_poolAddr, _user));\n }\n\n /**\n * @inheritdoc IRewardPool\n */\n function getStakingAmount(address _poolAddr, address _user) public view virtual returns (uint256);\n\n /**\n * @inheritdoc IRewardPool\n */\n function getStakingTotal(address _poolAddr) public view virtual returns (uint256);\n\n /**\n * @dev Returns the reward amount that user claimable.\n */\n function _getReward(\n address _poolAddr,\n address _user,\n uint256 _latestPeriod,\n uint256 _latestStakingAmount\n ) internal view returns (uint256) {\n UserRewardFields storage _reward = _userReward[_poolAddr][_user];\n\n if (_reward.lastPeriod == _latestPeriod) {\n return _reward.debited;\n }\n\n uint256 _aRps;\n uint256 _lastPeriodReward;\n PoolFields storage _pool = _stakingPool[_poolAddr];\n PeriodWrapper storage _wrappedArps = _accumulatedRps[_poolAddr][_reward.lastPeriod];\n\n if (_wrappedArps.lastPeriod > 0) {\n // Calculates the last period reward if the aRps at the period is set\n _aRps = _wrappedArps.inner;\n _lastPeriodReward = _reward.lowestAmount * (_aRps - _reward.aRps);\n } else {\n // Fallbacks to the previous aRps in case the aRps is not set\n _aRps = _reward.aRps;\n }\n\n uint256 _newPeriodsReward = _latestStakingAmount * (_pool.aRps - _aRps);\n return _reward.debited + (_lastPeriodReward + _newPeriodsReward) / 1e18;\n }\n\n /**\n * @dev Syncs the user reward.\n *\n * Emits the event `UserRewardUpdated` once the debit amount is updated.\n * Emits the event `PoolSharesUpdated` once the pool share is updated.\n *\n * Note: The method should be called whenever the user's staking amount changes.\n *\n */\n function _syncUserReward(address _poolAddr, address _user, uint256 _newStakingAmount) internal {\n uint256 _period = _currentPeriod();\n PoolFields storage _pool = _stakingPool[_poolAddr];\n uint256 _lastShares = _pool.shares.inner;\n\n // Updates the pool shares if it is outdated\n if (_pool.shares.lastPeriod < _period) {\n _pool.shares = PeriodWrapper(getStakingTotal(_poolAddr), _period);\n }\n\n UserRewardFields storage _reward = _userReward[_poolAddr][_user];\n uint256 _currentStakingAmount = getStakingAmount(_poolAddr, _user);\n uint256 _debited = _getReward(_poolAddr, _user, _period, _currentStakingAmount);\n\n if (_reward.debited != _debited) {\n _reward.debited = _debited;\n emit UserRewardUpdated(_poolAddr, _user, _debited);\n }\n\n _syncMinStakingAmount(_pool, _reward, _period, _newStakingAmount, _currentStakingAmount);\n _reward.aRps = _pool.aRps;\n _reward.lastPeriod = _period;\n\n if (_pool.shares.inner != _lastShares) {\n emit PoolSharesUpdated(_period, _poolAddr, _pool.shares.inner);\n }\n }\n\n /**\n * @dev Syncs the minimum staking amount of an user in the current period.\n */\n function _syncMinStakingAmount(\n PoolFields storage _pool,\n UserRewardFields storage _reward,\n uint256 _latestPeriod,\n uint256 _newStakingAmount,\n uint256 _currentStakingAmount\n ) internal {\n if (_reward.lastPeriod < _latestPeriod) {\n _reward.lowestAmount = _currentStakingAmount;\n }\n\n uint256 _lowestAmount = Math.min(_reward.lowestAmount, _newStakingAmount);\n uint256 _diffAmount = _reward.lowestAmount - _lowestAmount;\n if (_diffAmount > 0) {\n _reward.lowestAmount = _lowestAmount;\n if (_pool.shares.inner < _diffAmount) revert ErrInvalidPoolShare();\n _pool.shares.inner -= _diffAmount;\n }\n }\n\n /**\n * @dev Claims the settled reward for a specific user.\n *\n * @param _lastPeriod Must be in two possible value: `_currentPeriod` in normal calculation, or\n * `_currentPeriod + 1` in case of calculating the reward for revoked validators.\n *\n * Emits the `RewardClaimed` event and the `UserRewardUpdated` event.\n *\n * Note: This method should be called before transferring rewards for the user.\n *\n */\n function _claimReward(address _poolAddr, address _user, uint256 _lastPeriod) internal returns (uint256 _amount) {\n uint256 _currentStakingAmount = getStakingAmount(_poolAddr, _user);\n _amount = _getReward(_poolAddr, _user, _lastPeriod, _currentStakingAmount);\n emit RewardClaimed(_poolAddr, _user, _amount);\n\n UserRewardFields storage _reward = _userReward[_poolAddr][_user];\n _reward.debited = 0;\n _syncMinStakingAmount(_stakingPool[_poolAddr], _reward, _lastPeriod, _currentStakingAmount, _currentStakingAmount);\n _reward.lastPeriod = _lastPeriod;\n _reward.aRps = _stakingPool[_poolAddr].aRps;\n emit UserRewardUpdated(_poolAddr, _user, 0);\n }\n\n /**\n * @dev Records the amount of rewards `_rewards` for the pools `_poolAddrs`.\n *\n * Emits the event `PoolsUpdated` once the contract recorded the rewards successfully.\n * Emits the event `PoolsUpdateFailed` once the input array lengths are not equal.\n * Emits the event `PoolUpdateConflicted` when the pool is already updated in the period.\n *\n * Note: This method should be called once at the period ending.\n *\n */\n function _recordRewards(address[] memory _poolAddrs, uint256[] calldata _rewards, uint256 _period) internal {\n if (_poolAddrs.length != _rewards.length) {\n emit PoolsUpdateFailed(_period, _poolAddrs, _rewards);\n return;\n }\n\n uint256 _rps;\n uint256 _count;\n address _poolAddr;\n uint256 _stakingTotal;\n uint256[] memory _aRps = new uint256[](_poolAddrs.length);\n uint256[] memory _shares = new uint256[](_poolAddrs.length);\n address[] memory _conflicted = new address[](_poolAddrs.length);\n\n for (uint _i = 0; _i < _poolAddrs.length; _i++) {\n _poolAddr = _poolAddrs[_i];\n PoolFields storage _pool = _stakingPool[_poolAddr];\n _stakingTotal = getStakingTotal(_poolAddr);\n\n if (_accumulatedRps[_poolAddr][_period].lastPeriod == _period) {\n unchecked {\n _conflicted[_count++] = _poolAddr;\n }\n continue;\n }\n\n // Updates the pool shares if it is outdated\n if (_pool.shares.lastPeriod < _period) {\n _pool.shares = PeriodWrapper(_stakingTotal, _period);\n }\n\n // The rps is 0 if no one stakes for the pool\n _rps = _pool.shares.inner == 0 ? 0 : (_rewards[_i] * 1e18) / _pool.shares.inner;\n _aRps[_i - _count] = _pool.aRps += _rps;\n _accumulatedRps[_poolAddr][_period] = PeriodWrapper(_pool.aRps, _period);\n _pool.shares.inner = _stakingTotal;\n _shares[_i - _count] = _pool.shares.inner;\n _poolAddrs[_i - _count] = _poolAddr;\n }\n\n if (_count > 0) {\n assembly {\n mstore(_conflicted, _count)\n mstore(_poolAddrs, sub(mload(_poolAddrs), _count))\n }\n emit PoolsUpdateConflicted(_period, _conflicted);\n }\n\n if (_poolAddrs.length > 0) {\n emit PoolsUpdated(_period, _poolAddrs, _aRps, _shares);\n }\n }\n\n /**\n * @dev Returns the current period.\n */\n function _currentPeriod() internal view virtual returns (uint256);\n}\n" + }, + "contracts/ronin/staking/Staking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../../libraries/Math.sol\";\nimport \"../../interfaces/staking/IStaking.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"./CandidateStaking.sol\";\nimport \"./DelegatorStaking.sol\";\n\ncontract Staking is IStaking, CandidateStaking, DelegatorStaking, Initializable {\n constructor() {\n _disableInitializers();\n }\n\n receive() external payable onlyContract(ContractType.VALIDATOR) {}\n\n fallback() external payable onlyContract(ContractType.VALIDATOR) {}\n\n /**\n * @dev Initializes the contract storage.\n */\n function initialize(\n address __validatorContract,\n uint256 __minValidatorStakingAmount,\n uint256 __maxCommissionRate,\n uint256 __cooldownSecsToUndelegate,\n uint256 __waitingSecsToRevoke\n ) external initializer {\n _setContract(ContractType.VALIDATOR, __validatorContract);\n _setMinValidatorStakingAmount(__minValidatorStakingAmount);\n _setCommissionRateRange(0, __maxCommissionRate);\n _setCooldownSecsToUndelegate(__cooldownSecsToUndelegate);\n _setWaitingSecsToRevoke(__waitingSecsToRevoke);\n }\n\n function initializeV2() external reinitializer(2) {\n _setContract(ContractType.VALIDATOR, ______deprecatedValidator);\n delete ______deprecatedValidator;\n }\n\n /**\n * @dev This method only work on testnet, to hotfix the applied validator candidate that is failed.\n * TODO: Should remove this method before deploying it on mainnet.\n */\n function tmp_re_applyValidatorCandidate(\n address _candidateAdmin,\n address _consensusAddr,\n address payable _treasuryAddr,\n uint256 _commissionRate\n ) external {\n require(block.chainid == 2021, \"E1\");\n require(msg.sender == 0x57832A94810E18c84a5A5E2c4dD67D012ade574F, \"E2\");\n\n IRoninValidatorSet(getContract(ContractType.VALIDATOR)).execApplyValidatorCandidate(\n _candidateAdmin,\n _consensusAddr,\n _treasuryAddr,\n _commissionRate\n );\n }\n\n /**\n * @inheritdoc IStaking\n */\n function execRecordRewards(\n address[] calldata _consensusAddrs,\n uint256[] calldata _rewards,\n uint256 _period\n ) external payable override onlyContract(ContractType.VALIDATOR) {\n _recordRewards(_consensusAddrs, _rewards, _period);\n }\n\n /**\n * @inheritdoc IStaking\n */\n function execDeductStakingAmount(\n address _consensusAddr,\n uint256 _amount\n ) external override onlyContract(ContractType.VALIDATOR) returns (uint256 _actualDeductingAmount) {\n _actualDeductingAmount = _deductStakingAmount(_stakingPool[_consensusAddr], _amount);\n address payable _validatorContractAddr = payable(msg.sender);\n if (!_unsafeSendRON(_validatorContractAddr, _actualDeductingAmount)) {\n emit StakingAmountDeductFailed(\n _consensusAddr,\n _validatorContractAddr,\n _actualDeductingAmount,\n address(this).balance\n );\n }\n }\n\n /**\n * @inheritdoc RewardCalculation\n */\n function _currentPeriod() internal view virtual override returns (uint256) {\n return IRoninValidatorSet(getContract(ContractType.VALIDATOR)).currentPeriod();\n }\n\n /**\n * @inheritdoc CandidateStaking\n */\n function _deductStakingAmount(\n PoolDetail storage _pool,\n uint256 _amount\n ) internal override returns (uint256 _actualDeductingAmount) {\n _actualDeductingAmount = Math.min(_pool.stakingAmount, _amount);\n\n _pool.stakingAmount -= _actualDeductingAmount;\n _changeDelegatingAmount(\n _pool,\n _pool.admin,\n _pool.stakingAmount,\n Math.subNonNegative(_pool.stakingTotal, _actualDeductingAmount)\n );\n emit Unstaked(_pool.addr, _actualDeductingAmount);\n }\n}\n" + }, + "contracts/ronin/StakingVesting.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../interfaces/IStakingVesting.sol\";\nimport \"../extensions/collections/HasContracts.sol\";\nimport \"../extensions/consumers/PercentageConsumer.sol\";\nimport { RONTransferHelper } from \"../extensions/RONTransferHelper.sol\";\nimport { HasValidatorDeprecated } from \"../utils/DeprecatedSlots.sol\";\nimport \"../utils/CommonErrors.sol\";\n\ncontract StakingVesting is\n IStakingVesting,\n PercentageConsumer,\n HasValidatorDeprecated,\n HasContracts,\n Initializable,\n RONTransferHelper\n{\n /// @dev The block bonus for the block producer whenever a new block is mined.\n uint256 internal _blockProducerBonusPerBlock;\n /// @dev The block bonus for the bridge operator whenever a new block is mined.\n uint256 internal _bridgeOperatorBonusPerBlock;\n /// @dev The last block number that the staking vesting sent.\n uint256 public lastBlockSendingBonus;\n /// @dev The percentage that extracted from reward of block producer for fast finality.\n uint256 internal _fastFinalityRewardPercentage;\n\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the contract storage.\n */\n function initialize(\n address __validatorContract,\n uint256 __blockProducerBonusPerBlock,\n uint256 __bridgeOperatorBonusPerBlock\n ) external payable initializer {\n _setContract(ContractType.VALIDATOR, __validatorContract);\n _setBlockProducerBonusPerBlock(__blockProducerBonusPerBlock);\n _setBridgeOperatorBonusPerBlock(__bridgeOperatorBonusPerBlock);\n }\n\n function initializeV2() external reinitializer(2) {\n _setContract(ContractType.VALIDATOR, ______deprecatedValidator);\n delete ______deprecatedValidator;\n }\n\n function initializeV3(uint256 fastFinalityRewardPercent) external reinitializer(3) {\n _setFastFinalityRewardPercentage(fastFinalityRewardPercent);\n }\n\n /**\n * @inheritdoc IStakingVesting\n */\n function receiveRON() external payable {}\n\n /**\n * @inheritdoc IStakingVesting\n */\n function blockProducerBlockBonus(uint256 /* _block */) public view override returns (uint256) {\n return _blockProducerBonusPerBlock;\n }\n\n /**\n * @inheritdoc IStakingVesting\n */\n function bridgeOperatorBlockBonus(uint256 /* _block */) public view override returns (uint256) {\n return _bridgeOperatorBonusPerBlock;\n }\n\n /**\n * @inheritdoc IStakingVesting\n */\n function fastFinalityRewardPercentage() external view override returns (uint256) {\n return _fastFinalityRewardPercentage;\n }\n\n /**\n * @inheritdoc IStakingVesting\n */\n function requestBonus(\n bool forBlockProducer,\n bool forBridgeOperator\n )\n external\n override\n onlyContract(ContractType.VALIDATOR)\n returns (bool success, uint256 blockProducerBonus, uint256 bridgeOperatorBonus, uint256 fastFinalityRewardPercent)\n {\n if (block.number <= lastBlockSendingBonus) revert ErrBonusAlreadySent();\n\n lastBlockSendingBonus = block.number;\n\n blockProducerBonus = forBlockProducer ? blockProducerBlockBonus(block.number) : 0;\n bridgeOperatorBonus = forBridgeOperator ? bridgeOperatorBlockBonus(block.number) : 0;\n fastFinalityRewardPercent = _fastFinalityRewardPercentage;\n\n uint256 totalAmount = blockProducerBonus + bridgeOperatorBonus;\n\n if (totalAmount > 0) {\n address payable validatorContractAddr = payable(msg.sender);\n\n success = _unsafeSendRON(validatorContractAddr, totalAmount);\n\n if (!success) {\n emit BonusTransferFailed(\n block.number,\n validatorContractAddr,\n blockProducerBonus,\n bridgeOperatorBonus,\n address(this).balance\n );\n return (success, 0, 0, 0);\n }\n\n emit BonusTransferred(block.number, validatorContractAddr, blockProducerBonus, bridgeOperatorBonus);\n }\n }\n\n /**\n * @inheritdoc IStakingVesting\n */\n function setBlockProducerBonusPerBlock(uint256 _amount) external override onlyAdmin {\n _setBlockProducerBonusPerBlock(_amount);\n }\n\n /**\n * @inheritdoc IStakingVesting\n */\n function setBridgeOperatorBonusPerBlock(uint256 _amount) external override onlyAdmin {\n _setBridgeOperatorBonusPerBlock(_amount);\n }\n\n /**\n * @inheritdoc IStakingVesting\n */\n function setFastFinalityRewardPercentage(uint256 percent) external override onlyAdmin {\n if (percent > _MAX_PERCENTAGE) revert ErrInvalidArguments(msg.sig);\n _setFastFinalityRewardPercentage(percent);\n }\n\n /**\n * @dev Sets the bonus amount per block for block producer.\n *\n * Emits the event `BlockProducerBonusPerBlockUpdated`.\n *\n */\n function _setBlockProducerBonusPerBlock(uint256 _amount) internal {\n _blockProducerBonusPerBlock = _amount;\n emit BlockProducerBonusPerBlockUpdated(_amount);\n }\n\n /**\n * @dev Sets the bonus amount per block for bridge operator.\n *\n * Emits the event `BridgeOperatorBonusPerBlockUpdated`.\n *\n */\n function _setBridgeOperatorBonusPerBlock(uint256 _amount) internal {\n _bridgeOperatorBonusPerBlock = _amount;\n emit BridgeOperatorBonusPerBlockUpdated(_amount);\n }\n\n /**\n * @dev Sets the percent of fast finality reward.\n *\n * Emits the event `FastFinalityRewardPercentageUpdated`.\n *\n */\n function _setFastFinalityRewardPercentage(uint256 percent) internal {\n _fastFinalityRewardPercentage = percent;\n emit FastFinalityRewardPercentageUpdated(percent);\n }\n}\n" + }, + "contracts/ronin/validator/CandidateManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../extensions/consumers/GlobalConfigConsumer.sol\";\nimport \"../../extensions/consumers/PercentageConsumer.sol\";\nimport \"../../interfaces/validator/ICandidateManager.sol\";\nimport \"../../interfaces/staking/IStaking.sol\";\nimport { HasStakingDeprecated } from \"../../utils/DeprecatedSlots.sol\";\n\nabstract contract CandidateManager is\n ICandidateManager,\n PercentageConsumer,\n GlobalConfigConsumer,\n HasContracts,\n HasStakingDeprecated\n{\n /// @dev Maximum number of validator candidate\n uint256 private _maxValidatorCandidate;\n\n /// @dev The validator candidate array\n address[] internal _candidates;\n /// @dev Mapping from candidate consensus address => bitwise negation of validator index in `_candidates`\n mapping(address => uint256) internal _candidateIndex;\n /// @dev Mapping from candidate consensus address => their info\n mapping(address => ValidatorCandidate) internal _candidateInfo;\n\n /**\n * @dev The minimum offset in day from current date to the effective date of a new commission schedule.\n * Value of 1 means the change gets affected at the beginning of the following day.\n **/\n uint256 internal _minEffectiveDaysOnwards;\n /// @dev Mapping from candidate consensus address => schedule commission change.\n mapping(address => CommissionSchedule) internal _candidateCommissionChangeSchedule;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[48] private ______gap;\n\n /**\n * @inheritdoc ICandidateManager\n */\n function maxValidatorCandidate() public view override returns (uint256) {\n return _maxValidatorCandidate;\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function minEffectiveDaysOnward() external view override returns (uint256) {\n return _minEffectiveDaysOnwards;\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function setMaxValidatorCandidate(uint256 _number) external override onlyAdmin {\n _setMaxValidatorCandidate(_number);\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function setMinEffectiveDaysOnwards(uint256 _numOfDays) external override onlyAdmin {\n _setMinEffectiveDaysOnwards(_numOfDays);\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function execApplyValidatorCandidate(\n address _candidateAdmin,\n address _consensusAddr,\n address payable _treasuryAddr,\n uint256 _commissionRate\n ) external override onlyContract(ContractType.STAKING) {\n uint256 _length = _candidates.length;\n if (_length >= maxValidatorCandidate()) revert ErrExceedsMaxNumberOfCandidate();\n if (isValidatorCandidate(_consensusAddr)) revert ErrExistentCandidate();\n if (_commissionRate > _MAX_PERCENTAGE) revert ErrInvalidCommissionRate();\n\n for (uint _i; _i < _candidates.length; ) {\n ValidatorCandidate storage existentInfo = _candidateInfo[_candidates[_i]];\n if (_candidateAdmin == existentInfo.admin) revert ErrExistentCandidateAdmin(_candidateAdmin);\n if (_treasuryAddr == existentInfo.treasuryAddr) revert ErrExistentTreasury(_treasuryAddr);\n\n unchecked {\n ++_i;\n }\n }\n\n _candidateIndex[_consensusAddr] = ~_length;\n _candidates.push(_consensusAddr);\n\n ValidatorCandidate storage _info = _candidateInfo[_consensusAddr];\n _info.admin = _candidateAdmin;\n _info.consensusAddr = _consensusAddr;\n _info.treasuryAddr = _treasuryAddr;\n _info.commissionRate = _commissionRate;\n emit CandidateGranted(_consensusAddr, _treasuryAddr, _candidateAdmin);\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function execRequestRenounceCandidate(\n address _consensusAddr,\n uint256 _secsLeft\n ) external override onlyContract(ContractType.STAKING) {\n if (_isTrustedOrg(_consensusAddr)) revert ErrTrustedOrgCannotRenounce();\n\n ValidatorCandidate storage _info = _candidateInfo[_consensusAddr];\n if (_info.revokingTimestamp != 0) revert ErrAlreadyRequestedRevokingCandidate();\n _setRevokingTimestamp(_info, block.timestamp + _secsLeft);\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function execRequestUpdateCommissionRate(\n address _consensusAddr,\n uint256 _effectiveDaysOnwards,\n uint256 _commissionRate\n ) external override onlyContract(ContractType.STAKING) {\n if (_candidateCommissionChangeSchedule[_consensusAddr].effectiveTimestamp != 0) {\n revert ErrAlreadyRequestedUpdatingCommissionRate();\n }\n if (_commissionRate > _MAX_PERCENTAGE) revert ErrInvalidCommissionRate();\n if (_effectiveDaysOnwards < _minEffectiveDaysOnwards) revert ErrInvalidEffectiveDaysOnwards();\n\n CommissionSchedule storage _schedule = _candidateCommissionChangeSchedule[_consensusAddr];\n uint256 _effectiveTimestamp = ((block.timestamp / PERIOD_DURATION) + _effectiveDaysOnwards) * PERIOD_DURATION;\n _schedule.effectiveTimestamp = _effectiveTimestamp;\n _schedule.commissionRate = _commissionRate;\n\n emit CommissionRateUpdateScheduled(_consensusAddr, _effectiveTimestamp, _commissionRate);\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function isValidatorCandidate(address _addr) public view override returns (bool) {\n return _candidateIndex[_addr] != 0;\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function getCandidateInfos() external view override returns (ValidatorCandidate[] memory _list) {\n _list = new ValidatorCandidate[](_candidates.length);\n for (uint _i; _i < _list.length; ) {\n _list[_i] = _candidateInfo[_candidates[_i]];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function getCandidateInfo(address _candidate) external view override returns (ValidatorCandidate memory) {\n if (!isValidatorCandidate(_candidate)) revert ErrNonExistentCandidate();\n return _candidateInfo[_candidate];\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function getValidatorCandidates() public view override returns (address[] memory) {\n return _candidates;\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function getCommissionChangeSchedule(address _candidate) external view override returns (CommissionSchedule memory) {\n return _candidateCommissionChangeSchedule[_candidate];\n }\n\n /**\n * @dev Removes unsastisfied candidates, the ones who have insufficient minimum candidate staking amount,\n * or the ones who requested to renounce their candidate role.\n *\n * Emits the event `CandidatesRevoked` when a candidate is revoked.\n *\n */\n function _syncCandidateSet(uint256 _nextPeriod) internal returns (address[] memory _unsatisfiedCandidates) {\n IStaking _staking = IStaking(getContract(ContractType.STAKING));\n uint256 _waitingSecsToRevoke = _staking.waitingSecsToRevoke();\n uint256 _minStakingAmount = _staking.minValidatorStakingAmount();\n uint256[] memory _selfStakings = _staking.getManySelfStakings(_candidates);\n\n uint256 _length = _candidates.length;\n uint256 _unsatisfiedCount;\n _unsatisfiedCandidates = new address[](_length);\n\n {\n uint256 _i;\n address _addr;\n ValidatorCandidate storage _info;\n while (_i < _length) {\n _addr = _candidates[_i];\n _info = _candidateInfo[_addr];\n\n // Checks for under-balance status of candidates\n bool _hasTopupDeadline = _info.topupDeadline != 0;\n if (_selfStakings[_i] < _minStakingAmount) {\n // Updates deadline on the first time unsatisfied the staking amount condition\n if (!_hasTopupDeadline) {\n uint256 _topupDeadline = block.timestamp + _waitingSecsToRevoke;\n _info.topupDeadline = _topupDeadline;\n emit CandidateTopupDeadlineUpdated(_addr, _topupDeadline);\n }\n } else if (_hasTopupDeadline) {\n // Removes the deadline if the staking amount condition is satisfied\n delete _info.topupDeadline;\n emit CandidateTopupDeadlineUpdated(_addr, 0);\n }\n\n // Removes unsastisfied candidates\n bool _revokingActivated = (_info.revokingTimestamp != 0 && _info.revokingTimestamp <= block.timestamp) ||\n _emergencyExitLockedFundReleased(_addr);\n bool _topupDeadlineMissed = _info.topupDeadline != 0 && _info.topupDeadline <= block.timestamp;\n if (_revokingActivated || _topupDeadlineMissed) {\n _selfStakings[_i] = _selfStakings[--_length];\n unchecked {\n _unsatisfiedCandidates[_unsatisfiedCount++] = _addr;\n }\n _removeCandidate(_addr);\n continue;\n }\n\n // Checks for schedule of commission change and updates commission rate\n uint256 _scheduleTimestamp = _candidateCommissionChangeSchedule[_addr].effectiveTimestamp;\n if (_scheduleTimestamp != 0 && _scheduleTimestamp <= block.timestamp) {\n uint256 _commisionRate = _candidateCommissionChangeSchedule[_addr].commissionRate;\n delete _candidateCommissionChangeSchedule[_addr];\n _info.commissionRate = _commisionRate;\n emit CommissionRateUpdated(_addr, _commisionRate);\n }\n\n unchecked {\n _i++;\n }\n }\n }\n\n assembly {\n mstore(_unsatisfiedCandidates, _unsatisfiedCount)\n }\n\n if (_unsatisfiedCount > 0) {\n emit CandidatesRevoked(_unsatisfiedCandidates);\n _staking.execDeprecatePools(_unsatisfiedCandidates, _nextPeriod);\n }\n }\n\n /**\n * @inheritdoc ICandidateManager\n */\n function isCandidateAdmin(address _candidate, address _admin) external view override returns (bool) {\n return _candidateInfo[_candidate].admin == _admin;\n }\n\n /**\n * @dev Sets the maximum number of validator candidate.\n *\n * Emits the `MaxValidatorCandidateUpdated` event.\n *\n */\n function _setMaxValidatorCandidate(uint256 _threshold) internal {\n _maxValidatorCandidate = _threshold;\n emit MaxValidatorCandidateUpdated(_threshold);\n }\n\n /**\n * @dev Sets the minimum number of days onwards to the effective date of commission rate change.\n *\n * Emits the `MinEffectiveDaysOnwardsUpdated` event.\n *\n */\n function _setMinEffectiveDaysOnwards(uint256 _numOfDays) internal {\n if (_numOfDays < 1) revert ErrInvalidMinEffectiveDaysOnwards();\n _minEffectiveDaysOnwards = _numOfDays;\n emit MinEffectiveDaysOnwardsUpdated(_numOfDays);\n }\n\n /**\n * @dev Removes the candidate.\n */\n function _removeCandidate(address _addr) internal virtual {\n uint256 _idx = _candidateIndex[_addr];\n if (_idx == 0) {\n return;\n }\n\n delete _candidateInfo[_addr];\n delete _candidateIndex[_addr];\n delete _candidateCommissionChangeSchedule[_addr];\n\n address _lastCandidate = _candidates[_candidates.length - 1];\n if (_lastCandidate != _addr) {\n _candidateIndex[_lastCandidate] = _idx;\n _candidates[~_idx] = _lastCandidate;\n }\n\n _candidates.pop();\n }\n\n /**\n * @dev Sets timestamp to revoke a candidate.\n */\n function _setRevokingTimestamp(ValidatorCandidate storage _candidate, uint256 _timestamp) internal {\n if (!isValidatorCandidate(_candidate.consensusAddr)) revert ErrNonExistentCandidate();\n _candidate.revokingTimestamp = _timestamp;\n emit CandidateRevokingTimestampUpdated(_candidate.consensusAddr, _timestamp);\n }\n\n /**\n * @dev Returns a flag indicating whether the fund is unlocked.\n */\n function _emergencyExitLockedFundReleased(address _consensusAddr) internal virtual returns (bool);\n\n /**\n * @dev Returns whether the consensus address is a trusted org or not.\n */\n function _isTrustedOrg(address _consensusAddr) internal virtual returns (bool);\n}\n" + }, + "contracts/ronin/validator/CoinbaseExecution.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../extensions/RONTransferHelper.sol\";\nimport \"../../interfaces/IStakingVesting.sol\";\nimport \"../../interfaces/IMaintenance.sol\";\nimport \"../../interfaces/IRoninTrustedOrganization.sol\";\nimport \"../../interfaces/IFastFinalityTracking.sol\";\nimport \"../../interfaces/slash-indicator/ISlashIndicator.sol\";\nimport \"../../interfaces/validator/ICoinbaseExecution.sol\";\nimport \"../../libraries/EnumFlags.sol\";\nimport \"../../libraries/Math.sol\";\nimport { HasStakingVestingDeprecated, HasBridgeTrackingDeprecated, HasMaintenanceDeprecated, HasSlashIndicatorDeprecated } from \"../../utils/DeprecatedSlots.sol\";\nimport \"../../precompile-usages/PCUSortValidators.sol\";\nimport \"../../precompile-usages/PCUPickValidatorSet.sol\";\nimport \"./storage-fragments/CommonStorage.sol\";\nimport \"./CandidateManager.sol\";\nimport { EmergencyExit } from \"./EmergencyExit.sol\";\nimport { ErrCallerMustBeCoinbase } from \"../../utils/CommonErrors.sol\";\n\nabstract contract CoinbaseExecution is\n ICoinbaseExecution,\n RONTransferHelper,\n PCUSortValidators,\n PCUPickValidatorSet,\n HasContracts,\n HasStakingVestingDeprecated,\n HasBridgeTrackingDeprecated,\n HasMaintenanceDeprecated,\n HasSlashIndicatorDeprecated,\n EmergencyExit\n{\n using EnumFlags for EnumFlags.ValidatorFlag;\n\n modifier onlyCoinbase() {\n _requireCoinbase();\n _;\n }\n\n modifier whenEpochEnding() {\n if (!epochEndingAt(block.number)) revert ErrAtEndOfEpochOnly();\n _;\n }\n\n modifier oncePerEpoch() {\n if (epochOf(_lastUpdatedBlock) >= epochOf(block.number)) revert ErrAlreadyWrappedEpoch();\n _lastUpdatedBlock = block.number;\n _;\n }\n\n function _requireCoinbase() private view {\n if (msg.sender != block.coinbase) revert ErrCallerMustBeCoinbase();\n }\n\n /**\n * @inheritdoc ICoinbaseExecution\n */\n function submitBlockReward() external payable override onlyCoinbase {\n bool requestForBlockProducer = isBlockProducer(msg.sender) &&\n !_jailed(msg.sender) &&\n !_miningRewardDeprecated(msg.sender, currentPeriod());\n\n (, uint256 blockProducerBonus, , uint256 fastFinalityRewardPercentage) = IStakingVesting(\n getContract(ContractType.STAKING_VESTING)\n ).requestBonus({ forBlockProducer: requestForBlockProducer, forBridgeOperator: false });\n\n // Deprecates reward for non-validator or slashed validator\n if (!requestForBlockProducer) {\n _totalDeprecatedReward += msg.value;\n emit BlockRewardDeprecated(msg.sender, msg.value, BlockRewardDeprecatedType.UNAVAILABILITY);\n return;\n }\n\n emit BlockRewardSubmitted(msg.sender, msg.value, blockProducerBonus);\n\n uint256 period = currentPeriod();\n uint256 reward = msg.value + blockProducerBonus;\n uint256 rewardFastFinality = (reward * fastFinalityRewardPercentage) / _MAX_PERCENTAGE; // reward for fast finality\n uint256 rewardProducingBlock = reward - rewardFastFinality; // reward for producing blocks\n uint256 cutOffReward;\n\n // Add fast finality reward to total reward for current epoch, then split it later in the {wrapupEpoch} method.\n _totalFastFinalityReward += rewardFastFinality;\n\n if (_miningRewardBailoutCutOffAtPeriod[msg.sender][period]) {\n (, , , uint256 cutOffPercentage) = ISlashIndicator(getContract(ContractType.SLASH_INDICATOR))\n .getCreditScoreConfigs();\n cutOffReward = (rewardProducingBlock * cutOffPercentage) / _MAX_PERCENTAGE;\n _totalDeprecatedReward += cutOffReward;\n emit BlockRewardDeprecated(msg.sender, cutOffReward, BlockRewardDeprecatedType.AFTER_BAILOUT);\n }\n\n rewardProducingBlock -= cutOffReward;\n (uint256 minRate, uint256 maxRate) = IStaking(getContract(ContractType.STAKING)).getCommissionRateRange();\n uint256 rate = Math.max(Math.min(_candidateInfo[msg.sender].commissionRate, maxRate), minRate);\n uint256 miningAmount = (rate * rewardProducingBlock) / _MAX_PERCENTAGE;\n _miningReward[msg.sender] += miningAmount;\n\n uint256 delegatingAmount = rewardProducingBlock - miningAmount;\n _delegatingReward[msg.sender] += delegatingAmount;\n }\n\n /**\n * @inheritdoc ICoinbaseExecution\n */\n function wrapUpEpoch() external payable virtual override onlyCoinbase whenEpochEnding oncePerEpoch {\n uint256 _newPeriod = _computePeriod(block.timestamp);\n bool _periodEnding = _isPeriodEnding(_newPeriod);\n\n address[] memory _currentValidators = getValidators();\n address[] memory _revokedCandidates;\n uint256 _epoch = epochOf(block.number);\n uint256 _nextEpoch = _epoch + 1;\n uint256 _lastPeriod = currentPeriod();\n\n _syncFastFinalityReward(_epoch, _currentValidators);\n\n if (_periodEnding) {\n (\n uint256 _totalDelegatingReward,\n uint256[] memory _delegatingRewards\n ) = _distributeRewardToTreasuriesAndCalculateTotalDelegatingReward(_lastPeriod, _currentValidators);\n _settleAndTransferDelegatingRewards(_lastPeriod, _currentValidators, _totalDelegatingReward, _delegatingRewards);\n _tryRecycleLockedFundsFromEmergencyExits();\n _recycleDeprecatedRewards();\n ISlashIndicator _slashIndicatorContract = ISlashIndicator(getContract(ContractType.SLASH_INDICATOR));\n _slashIndicatorContract.updateCreditScores(_currentValidators, _lastPeriod);\n (_currentValidators, _revokedCandidates) = _syncValidatorSet(_newPeriod);\n if (_revokedCandidates.length > 0) {\n _slashIndicatorContract.execResetCreditScores(_revokedCandidates);\n }\n _currentPeriodStartAtBlock = block.number + 1;\n }\n _revampRoles(_newPeriod, _nextEpoch, _currentValidators);\n emit WrappedUpEpoch(_lastPeriod, _epoch, _periodEnding);\n _periodOf[_nextEpoch] = _newPeriod;\n _lastUpdatedPeriod = _newPeriod;\n }\n\n /**\n * @dev This method calculate and update reward of each `validators` accordingly thier fast finality voting performance\n * in the `epoch`. The leftover reward is added to the {_totalDeprecatedReward} and is recycled later to the\n * {StakingVesting} contract.\n *\n * Requirements:\n * - This method is only called once each epoch.\n */\n function _syncFastFinalityReward(uint256 epoch, address[] memory validators) private {\n uint256[] memory voteCounts = IFastFinalityTracking(getContract(ContractType.FAST_FINALITY_TRACKING))\n .getManyFinalityVoteCounts(epoch, validators);\n uint256 divisor = _numberOfBlocksInEpoch * validators.length;\n uint256 iReward;\n uint256 totalReward = _totalFastFinalityReward;\n uint256 totalDispensedReward = 0;\n\n for (uint i; i < validators.length; ) {\n iReward = (totalReward * voteCounts[i]) / divisor;\n _fastFinalityReward[validators[i]] += iReward;\n totalDispensedReward += iReward;\n unchecked {\n ++i;\n }\n }\n\n _totalDeprecatedReward += (totalReward - totalDispensedReward);\n delete _totalFastFinalityReward;\n }\n\n /**\n * @dev This loops over all current validators to:\n * - Update delegating reward for and calculate total delegating rewards to be sent to the staking contract,\n * - Distribute the reward of block producers and bridge operators to their treasury addresses,\n * - Update the total deprecated reward if the two previous conditions do not sastify.\n *\n * Note: This method should be called once in the end of each period.\n *\n */\n function _distributeRewardToTreasuriesAndCalculateTotalDelegatingReward(\n uint256 _lastPeriod,\n address[] memory _currentValidators\n ) private returns (uint256 _totalDelegatingReward, uint256[] memory _delegatingRewards) {\n address _consensusAddr;\n address payable _treasury;\n _delegatingRewards = new uint256[](_currentValidators.length);\n\n for (uint _i; _i < _currentValidators.length; ) {\n _consensusAddr = _currentValidators[_i];\n _treasury = _candidateInfo[_consensusAddr].treasuryAddr;\n\n if (!_jailed(_consensusAddr) && !_miningRewardDeprecated(_consensusAddr, _lastPeriod)) {\n _totalDelegatingReward += _delegatingReward[_consensusAddr];\n _delegatingRewards[_i] = _delegatingReward[_consensusAddr];\n _distributeMiningReward(_consensusAddr, _treasury);\n _distributeFastFinalityReward(_consensusAddr, _treasury);\n } else {\n _totalDeprecatedReward +=\n _miningReward[_consensusAddr] +\n _delegatingReward[_consensusAddr] +\n _fastFinalityReward[_consensusAddr];\n }\n\n delete _delegatingReward[_consensusAddr];\n delete _miningReward[_consensusAddr];\n delete _fastFinalityReward[_consensusAddr];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @dev Distributes bonus of staking vesting and mining fee for the block producer.\n *\n * Emits the `MiningRewardDistributed` once the reward is distributed successfully.\n * Emits the `MiningRewardDistributionFailed` once the contract fails to distribute reward.\n *\n * Note: This method should be called once in the end of each period.\n *\n */\n function _distributeMiningReward(address _consensusAddr, address payable _treasury) private {\n uint256 _amount = _miningReward[_consensusAddr];\n if (_amount > 0) {\n if (_unsafeSendRONLimitGas(_treasury, _amount, DEFAULT_ADDITION_GAS)) {\n emit MiningRewardDistributed(_consensusAddr, _treasury, _amount);\n return;\n }\n\n emit MiningRewardDistributionFailed(_consensusAddr, _treasury, _amount, address(this).balance);\n }\n }\n\n function _distributeFastFinalityReward(address _consensusAddr, address payable _treasury) private {\n uint256 _amount = _fastFinalityReward[_consensusAddr];\n if (_amount > 0) {\n if (_unsafeSendRONLimitGas(_treasury, _amount, DEFAULT_ADDITION_GAS)) {\n emit FastFinalityRewardDistributed(_consensusAddr, _treasury, _amount);\n return;\n }\n\n emit FastFinalityRewardDistributionFailed(_consensusAddr, _treasury, _amount, address(this).balance);\n }\n }\n\n /**\n * @dev Helper function to settle rewards for delegators of `_currentValidators` at the end of each period,\n * then transfer the rewards from this contract to the staking contract, in order to finalize a period.\n *\n * Emits the `StakingRewardDistributed` once the reward is distributed successfully.\n * Emits the `StakingRewardDistributionFailed` once the contract fails to distribute reward.\n *\n * Note: This method should be called once in the end of each period.\n *\n */\n function _settleAndTransferDelegatingRewards(\n uint256 _period,\n address[] memory _currentValidators,\n uint256 _totalDelegatingReward,\n uint256[] memory _delegatingRewards\n ) private {\n IStaking _staking = IStaking(getContract(ContractType.STAKING));\n if (_totalDelegatingReward > 0) {\n if (_unsafeSendRON(payable(address(_staking)), _totalDelegatingReward)) {\n _staking.execRecordRewards(_currentValidators, _delegatingRewards, _period);\n emit StakingRewardDistributed(_totalDelegatingReward, _currentValidators, _delegatingRewards);\n return;\n }\n\n emit StakingRewardDistributionFailed(\n _totalDelegatingReward,\n _currentValidators,\n _delegatingRewards,\n address(this).balance\n );\n }\n }\n\n /**\n * @dev Transfer the deprecated rewards e.g. the rewards that get deprecated when validator is slashed/maintained,\n * to the staking vesting contract\n *\n * Note: This method should be called once in the end of each period.\n */\n function _recycleDeprecatedRewards() private {\n uint256 _withdrawAmount = _totalDeprecatedReward;\n\n if (_withdrawAmount != 0) {\n address _withdrawTarget = getContract(ContractType.STAKING_VESTING);\n\n delete _totalDeprecatedReward;\n\n (bool _success, ) = _withdrawTarget.call{ value: _withdrawAmount }(\n abi.encodeWithSelector(IStakingVesting.receiveRON.selector)\n );\n\n if (_success) {\n emit DeprecatedRewardRecycled(_withdrawTarget, _withdrawAmount);\n } else {\n emit DeprecatedRewardRecycleFailed(_withdrawTarget, _withdrawAmount, address(this).balance);\n }\n }\n }\n\n /**\n * @dev Updates the validator set based on the validator candidates from the Staking contract.\n *\n * Emits the `ValidatorSetUpdated` event.\n *\n * Note: This method should be called once in the end of each period.\n *\n */\n function _syncValidatorSet(\n uint256 _newPeriod\n ) private returns (address[] memory _newValidators, address[] memory _unsastifiedCandidates) {\n _unsastifiedCandidates = _syncCandidateSet(_newPeriod);\n uint256[] memory _weights = IStaking(getContract(ContractType.STAKING)).getManyStakingTotals(_candidates);\n uint256[] memory _trustedWeights = IRoninTrustedOrganization(getContract(ContractType.RONIN_TRUSTED_ORGANIZATION))\n .getConsensusWeights(_candidates);\n uint256 _newValidatorCount;\n (_newValidators, _newValidatorCount) = _pcPickValidatorSet(\n _candidates,\n _weights,\n _trustedWeights,\n _maxValidatorNumber,\n _maxPrioritizedValidatorNumber\n );\n _setNewValidatorSet(_newValidators, _newValidatorCount, _newPeriod);\n }\n\n /**\n * @dev Private helper function helps writing the new validator set into the contract storage.\n *\n * Emits the `ValidatorSetUpdated` event.\n *\n * Note: This method should be called once in the end of each period.\n *\n */\n function _setNewValidatorSet(\n address[] memory _newValidators,\n uint256 _newValidatorCount,\n uint256 _newPeriod\n ) private {\n // Remove exceeding validators in the current set\n for (uint256 _i = _newValidatorCount; _i < validatorCount; ) {\n delete _validatorMap[_validators[_i]];\n delete _validators[_i];\n\n unchecked {\n ++_i;\n }\n }\n\n // Remove flag for all validator in the current set\n for (uint _i; _i < _newValidatorCount; ) {\n delete _validatorMap[_validators[_i]];\n\n unchecked {\n ++_i;\n }\n }\n\n // Update new validator set and set flag correspondingly.\n for (uint256 _i; _i < _newValidatorCount; ) {\n address _newValidator = _newValidators[_i];\n _validatorMap[_newValidator] = EnumFlags.ValidatorFlag.Both;\n _validators[_i] = _newValidator;\n\n unchecked {\n ++_i;\n }\n }\n\n validatorCount = _newValidatorCount;\n emit ValidatorSetUpdated(_newPeriod, _newValidators);\n }\n\n /**\n * @dev Activate/Deactivate the validators from producing blocks, based on their in jail status and maintenance status.\n *\n * Requirements:\n * - This method is called at the end of each epoch\n *\n * Emits the `BlockProducerSetUpdated` event.\n * Emits the `BridgeOperatorSetUpdated` event.\n *\n */\n function _revampRoles(uint256 _newPeriod, uint256 _nextEpoch, address[] memory _currentValidators) private {\n bool[] memory _maintainedList = IMaintenance(getContract(ContractType.MAINTENANCE)).checkManyMaintained(\n _currentValidators,\n block.number + 1\n );\n\n for (uint _i; _i < _currentValidators.length; ) {\n address _validator = _currentValidators[_i];\n bool _emergencyExitRequested = block.timestamp <= _emergencyExitJailedTimestamp[_validator];\n bool _isProducerBefore = isBlockProducer(_validator);\n bool _isProducerAfter = !(_jailedAtBlock(_validator, block.number + 1) ||\n _maintainedList[_i] ||\n _emergencyExitRequested);\n\n if (!_isProducerBefore && _isProducerAfter) {\n _validatorMap[_validator] = _validatorMap[_validator].addFlag(EnumFlags.ValidatorFlag.BlockProducer);\n } else if (_isProducerBefore && !_isProducerAfter) {\n _validatorMap[_validator] = _validatorMap[_validator].removeFlag(EnumFlags.ValidatorFlag.BlockProducer);\n }\n\n unchecked {\n ++_i;\n }\n }\n emit BlockProducerSetUpdated(_newPeriod, _nextEpoch, getBlockProducers());\n }\n\n /**\n * @dev Override `CandidateManager-_isTrustedOrg`.\n */\n function _isTrustedOrg(address _consensusAddr) internal view override returns (bool) {\n return\n IRoninTrustedOrganization(getContract(ContractType.RONIN_TRUSTED_ORGANIZATION)).getConsensusWeight(\n _consensusAddr\n ) > 0;\n }\n}\n" + }, + "contracts/ronin/validator/EmergencyExit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../extensions/RONTransferHelper.sol\";\nimport \"../../interfaces/IRoninGovernanceAdmin.sol\";\nimport \"../../interfaces/validator/IEmergencyExit.sol\";\nimport \"./storage-fragments/CommonStorage.sol\";\nimport \"./CandidateManager.sol\";\n\nabstract contract EmergencyExit is IEmergencyExit, RONTransferHelper, CandidateManager, CommonStorage {\n /**\n * @inheritdoc IEmergencyExit\n */\n function emergencyExitLockedAmount() external view returns (uint256) {\n return _emergencyExitLockedAmount;\n }\n\n /**\n * @inheritdoc IEmergencyExit\n */\n function emergencyExpiryDuration() external view returns (uint256) {\n return _emergencyExpiryDuration;\n }\n\n /**\n * @inheritdoc IEmergencyExit\n */\n function execEmergencyExit(\n address _consensusAddr,\n uint256 _secLeftToRevoke\n ) external onlyContract(ContractType.STAKING) {\n EmergencyExitInfo storage _info = _exitInfo[_consensusAddr];\n if (_info.recyclingAt != 0) revert ErrAlreadyRequestedEmergencyExit();\n\n uint256 _revokingTimestamp = block.timestamp + _secLeftToRevoke;\n _setRevokingTimestamp(_candidateInfo[_consensusAddr], _revokingTimestamp);\n _emergencyExitJailedTimestamp[_consensusAddr] = _revokingTimestamp;\n\n uint256 _deductedAmount = IStaking(msg.sender).execDeductStakingAmount(_consensusAddr, _emergencyExitLockedAmount);\n if (_deductedAmount > 0) {\n uint256 _recyclingAt = block.timestamp + _emergencyExpiryDuration;\n _lockedConsensusList.push(_consensusAddr);\n _info.lockedAmount = _deductedAmount;\n _info.recyclingAt = _recyclingAt;\n IRoninGovernanceAdmin(_getAdmin()).createEmergencyExitPoll(\n _consensusAddr,\n _candidateInfo[_consensusAddr].treasuryAddr,\n block.timestamp,\n _recyclingAt\n );\n }\n emit EmergencyExitRequested(_consensusAddr, _deductedAmount);\n }\n\n /**\n * @inheritdoc IEmergencyExit\n */\n function setEmergencyExitLockedAmount(uint256 _emergencyExitLockedAmount) external onlyAdmin {\n _setEmergencyExitLockedAmount(_emergencyExitLockedAmount);\n }\n\n /**\n * @inheritdoc IEmergencyExit\n */\n function setEmergencyExpiryDuration(uint256 _emergencyExpiryDuration) external onlyAdmin {\n _setEmergencyExpiryDuration(_emergencyExpiryDuration);\n }\n\n /**\n * @inheritdoc IEmergencyExit\n */\n function execReleaseLockedFundForEmergencyExitRequest(\n address _consensusAddr,\n address payable _recipient\n ) external onlyAdmin {\n if (_exitInfo[_consensusAddr].recyclingAt == 0) {\n return;\n }\n\n uint256 _length = _lockedConsensusList.length;\n uint256 _index = _length;\n\n for (uint _i; _i < _length; ) {\n if (_lockedConsensusList[_i] == _consensusAddr) {\n _index = _i;\n break;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n // The locked amount might be recycled\n if (_index == _length) {\n return;\n }\n\n uint256 _amount = _exitInfo[_consensusAddr].lockedAmount;\n if (_amount > 0) {\n delete _exitInfo[_consensusAddr];\n if (_length > 1) {\n _lockedConsensusList[_index] = _lockedConsensusList[_length - 1];\n }\n _lockedConsensusList.pop();\n\n _lockedFundReleased[_consensusAddr] = true;\n if (_unsafeSendRONLimitGas(_recipient, _amount, DEFAULT_ADDITION_GAS)) {\n emit EmergencyExitLockedFundReleased(_consensusAddr, _recipient, _amount);\n return;\n }\n\n emit EmergencyExitLockedFundReleasingFailed(_consensusAddr, _recipient, _amount, address(this).balance);\n }\n }\n\n /**\n * @dev Tries to recycle the locked funds from emergency exit requests.\n */\n function _tryRecycleLockedFundsFromEmergencyExits() internal {\n uint256 _length = _lockedConsensusList.length;\n\n uint256 _i;\n address _addr;\n EmergencyExitInfo storage _info;\n\n while (_i < _length) {\n _addr = _lockedConsensusList[_i];\n _info = _exitInfo[_addr];\n\n if (_info.recyclingAt <= block.timestamp) {\n _totalDeprecatedReward += _info.lockedAmount;\n\n delete _exitInfo[_addr];\n if (--_length > 0) {\n _lockedConsensusList[_i] = _lockedConsensusList[_length];\n }\n _lockedConsensusList.pop();\n continue;\n }\n\n unchecked {\n _i++;\n }\n }\n }\n\n /**\n * @dev Override `CandidateManager-_emergencyExitLockedFundReleased`.\n */\n function _emergencyExitLockedFundReleased(address _consensusAddr) internal virtual override returns (bool) {\n return _lockedFundReleased[_consensusAddr];\n }\n\n /**\n * @dev Override `CandidateManager-_removeCandidate`.\n */\n function _removeCandidate(address _consensusAddr) internal override {\n delete _lockedFundReleased[_consensusAddr];\n super._removeCandidate(_consensusAddr);\n }\n\n /**\n * @dev See `setEmergencyExitLockedAmount.\n */\n function _setEmergencyExitLockedAmount(uint256 _amount) internal {\n _emergencyExitLockedAmount = _amount;\n emit EmergencyExitLockedAmountUpdated(_amount);\n }\n\n /**\n * @dev See `setEmergencyExpiryDuration`.\n */\n function _setEmergencyExpiryDuration(uint256 _duration) internal {\n _emergencyExpiryDuration = _duration;\n emit EmergencyExpiryDurationUpdated(_duration);\n }\n}\n" + }, + "contracts/ronin/validator/migrations/NotifiedMigrator.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ConditionalImplementControl } from \"../../../extensions/version-control/ConditionalImplementControl.sol\";\nimport { ErrUnauthorizedCall } from \"../../../utils/CommonErrors.sol\";\n\ncontract NotifiedMigrator is ConditionalImplementControl {\n address public immutable NOTIFIER;\n\n constructor(\n address proxyStorage,\n address prevImpl,\n address newImpl,\n address notifier\n ) payable ConditionalImplementControl(proxyStorage, prevImpl, newImpl) {\n NOTIFIER = notifier;\n }\n\n /**\n * @dev See {IConditionalImplementControl-selfUpgrade}.\n */\n function selfUpgrade() external override onlyDelegateFromProxyStorage {\n if (msg.sender != NOTIFIER) revert ErrUnauthorizedCall(msg.sig);\n _upgradeTo(NEW_IMPL);\n }\n}\n" + }, + "contracts/ronin/validator/migrations/RoninValidatorSetTimedMigrator.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IdentityGuard, IConditionalImplementControl, ConditionalImplementControl } from \"../../../extensions/version-control/ConditionalImplementControl.sol\";\nimport { ITimingInfo } from \"../../../interfaces/validator/info-fragments/ITimingInfo.sol\";\nimport { ICoinbaseExecution } from \"../../../interfaces/validator/ICoinbaseExecution.sol\";\nimport { HasProxyAdmin, HasContracts } from \"../../../extensions/collections/HasContracts.sol\";\nimport { TransparentUpgradeableProxyV2 } from \"../../../extensions/TransparentUpgradeableProxyV2.sol\";\nimport { ContractType } from \"../../../utils/ContractType.sol\";\n\n/**\n * @title RoninValidatorSetTimedMigrator\n * @dev A contract that facilitates timed migration of the Ronin validator set using conditional version control.\n */\ncontract RoninValidatorSetTimedMigrator is ConditionalImplementControl, HasContracts {\n /**\n * @dev Modifier that executes the function when conditions are met.\n * If the function is {wrapUpEpoch} from {ICoinbaseExecution},\n * it checks the current period before and after execution.\n * If they differ, it triggers the {selfUpgrade} function.\n */\n modifier whenConditionsAreMet() override {\n if (msg.sig == ICoinbaseExecution.wrapUpEpoch.selector) {\n uint256 currentPeriod = _getCurrentPeriod();\n _;\n if (currentPeriod != _getCurrentPeriod()) {\n this.selfUpgrade();\n }\n } else {\n _;\n }\n }\n\n /**\n * @dev Constructs the {RoninValidatorSetTimedMigrator} contract.\n * @param proxyStorage The address of the proxy storage contract.\n * @param prevImpl The address of the current contract implementation.\n * @param newImpl The address of the new contract implementation.\n */\n constructor(\n address proxyStorage,\n address prevImpl,\n address newImpl\n ) ConditionalImplementControl(proxyStorage, prevImpl, newImpl) {}\n\n function selfUpgrade() external override onlyDelegateFromProxyStorage onlySelfCall {\n _upgradeTo(NEW_IMPL);\n\n IConditionalImplementControl(getContract(ContractType.STAKING)).selfUpgrade();\n IConditionalImplementControl(getContract(ContractType.SLASH_INDICATOR)).selfUpgrade();\n IConditionalImplementControl(getContract(ContractType.RONIN_TRUSTED_ORGANIZATION)).selfUpgrade();\n }\n\n /**\n * @dev Internal function to choose the current version of the contract implementation.\n * @return The address of the current version implementation.\n */\n function _getConditionedImplementation() internal view override returns (address) {\n return PREV_IMPL;\n }\n\n /**\n * @dev Internal function to get the current period from ITimingInfo.\n * @return The current period.\n */\n function _getCurrentPeriod() private view returns (uint256) {\n return ITimingInfo(address(this)).currentPeriod();\n }\n\n function _requireSelfCall() internal view override(ConditionalImplementControl, IdentityGuard) {\n ConditionalImplementControl._requireSelfCall();\n }\n}\n" + }, + "contracts/ronin/validator/RoninValidatorSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"../../interfaces/validator/IRoninValidatorSet.sol\";\nimport \"./CoinbaseExecution.sol\";\nimport \"./SlashingExecution.sol\";\n\ncontract RoninValidatorSet is Initializable, CoinbaseExecution, SlashingExecution {\n constructor() {\n _disableInitializers();\n }\n\n fallback() external payable {\n _fallback();\n }\n\n receive() external payable {\n _fallback();\n }\n\n /**\n * @dev Initializes the contract storage.\n */\n function initialize(\n address __slashIndicatorContract,\n address __stakingContract,\n address __stakingVestingContract,\n address __maintenanceContract,\n address __roninTrustedOrganizationContract,\n address /* __bridgeTrackingContract */,\n uint256 __maxValidatorNumber,\n uint256 __maxValidatorCandidate,\n uint256 __maxPrioritizedValidatorNumber,\n uint256 __minEffectiveDaysOnwards,\n uint256 __numberOfBlocksInEpoch,\n // __emergencyExitConfigs[0]: emergencyExitLockedAmount\n // __emergencyExitConfigs[1]: emergencyExpiryDuration\n uint256[2] calldata __emergencyExitConfigs\n ) external initializer {\n _setContract(ContractType.SLASH_INDICATOR, __slashIndicatorContract);\n _setContract(ContractType.STAKING, __stakingContract);\n _setContract(ContractType.STAKING_VESTING, __stakingVestingContract);\n _setContract(ContractType.MAINTENANCE, __maintenanceContract);\n _setContract(ContractType.RONIN_TRUSTED_ORGANIZATION, __roninTrustedOrganizationContract);\n\n _setMaxValidatorNumber(__maxValidatorNumber);\n _setMaxValidatorCandidate(__maxValidatorCandidate);\n _setMaxPrioritizedValidatorNumber(__maxPrioritizedValidatorNumber);\n _setMinEffectiveDaysOnwards(__minEffectiveDaysOnwards);\n _setEmergencyExitLockedAmount(__emergencyExitConfigs[0]);\n _setEmergencyExpiryDuration(__emergencyExitConfigs[1]);\n _numberOfBlocksInEpoch = __numberOfBlocksInEpoch;\n }\n\n function initializeV2() external reinitializer(2) {\n _setContract(ContractType.STAKING, ______deprecatedStakingContract);\n _setContract(ContractType.MAINTENANCE, ______deprecatedMaintenance);\n _setContract(ContractType.SLASH_INDICATOR, ______deprecatedSlashIndicator);\n _setContract(ContractType.STAKING_VESTING, ______deprecatedStakingVesting);\n _setContract(ContractType.RONIN_TRUSTED_ORGANIZATION, ______deprecatedTrustedOrg);\n\n delete ______deprecatedStakingContract;\n delete ______deprecatedMaintenance;\n delete ______deprecatedSlashIndicator;\n delete ______deprecatedStakingVesting;\n delete ______deprecatedBridgeTracking;\n delete ______deprecatedTrustedOrg;\n }\n\n function initializeV3(address fastFinalityTrackingContract) external reinitializer(3) {\n _setContract(ContractType.FAST_FINALITY_TRACKING, fastFinalityTrackingContract);\n }\n\n /**\n * @dev Only receives RON from staking vesting contract (for topping up bonus), and from staking contract (for transferring\n * deducting amount on slashing).\n */\n function _fallback() internal view {\n if (msg.sender != getContract(ContractType.STAKING_VESTING) && msg.sender != getContract(ContractType.STAKING)) {\n revert ErrUnauthorizedReceiveRON();\n }\n }\n}\n" + }, + "contracts/ronin/validator/SlashingExecution.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../extensions/collections/HasContracts.sol\";\nimport \"../../interfaces/validator/ISlashingExecution.sol\";\nimport \"../../interfaces/staking/IStaking.sol\";\nimport \"../../libraries/Math.sol\";\nimport { HasSlashIndicatorDeprecated, HasStakingDeprecated } from \"../../utils/DeprecatedSlots.sol\";\nimport \"./storage-fragments/CommonStorage.sol\";\n\nabstract contract SlashingExecution is\n ISlashingExecution,\n HasContracts,\n HasSlashIndicatorDeprecated,\n HasStakingDeprecated,\n CommonStorage\n{\n /**\n * @inheritdoc ISlashingExecution\n */\n function execSlash(\n address validatorAddr,\n uint256 newJailedUntil,\n uint256 slashAmount,\n bool cannotBailout\n ) external override onlyContract(ContractType.SLASH_INDICATOR) {\n uint256 period = currentPeriod();\n _miningRewardDeprecatedAtPeriod[validatorAddr][period] = true;\n\n _totalDeprecatedReward += _miningReward[validatorAddr] + _delegatingReward[validatorAddr];\n\n delete _miningReward[validatorAddr];\n delete _delegatingReward[validatorAddr];\n\n _blockProducerJailedBlock[validatorAddr] = Math.max(newJailedUntil, _blockProducerJailedBlock[validatorAddr]);\n\n if (slashAmount > 0) {\n uint256 _actualAmount = IStaking(getContract(ContractType.STAKING)).execDeductStakingAmount(\n validatorAddr,\n slashAmount\n );\n _totalDeprecatedReward += _actualAmount;\n }\n\n if (cannotBailout) {\n _cannotBailoutUntilBlock[validatorAddr] = Math.max(newJailedUntil, _cannotBailoutUntilBlock[validatorAddr]);\n }\n\n emit ValidatorPunished(validatorAddr, period, _blockProducerJailedBlock[validatorAddr], slashAmount, true, false);\n }\n\n /**\n * @inheritdoc ISlashingExecution\n */\n function execBailOut(\n address validatorAddr,\n uint256 period\n ) external override onlyContract(ContractType.SLASH_INDICATOR) {\n if (block.number <= _cannotBailoutUntilBlock[validatorAddr]) revert ErrCannotBailout(validatorAddr);\n\n // Note: Removing rewards of validator in `bailOut` function is not needed, since the rewards have been\n // removed previously in the `slash` function.\n _miningRewardBailoutCutOffAtPeriod[validatorAddr][period] = true;\n _miningRewardDeprecatedAtPeriod[validatorAddr][period] = false;\n _blockProducerJailedBlock[validatorAddr] = block.number - 1;\n\n emit ValidatorUnjailed(validatorAddr, period);\n }\n}\n" + }, + "contracts/ronin/validator/storage-fragments/CommonStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../../interfaces/validator/info-fragments/ICommonInfo.sol\";\nimport \"./JailingStorage.sol\";\nimport \"./TimingStorage.sol\";\nimport \"./ValidatorInfoStorageV2.sol\";\n\nabstract contract CommonStorage is ICommonInfo, TimingStorage, JailingStorage, ValidatorInfoStorageV2 {\n /// @dev Mapping from consensus address => pending reward from producing block\n mapping(address => uint256) internal _miningReward;\n /// @dev Mapping from consensus address => pending reward from delegating\n mapping(address => uint256) internal _delegatingReward;\n\n /// @dev The total reward for fast finality\n uint256 internal _totalFastFinalityReward;\n /// @dev Mapping from consensus address => pending reward for fast finality\n mapping(address => uint256) internal _fastFinalityReward;\n\n /// @dev The deprecated reward that has not been withdrawn by admin\n uint256 internal _totalDeprecatedReward;\n\n /// @dev The amount of RON to lock from a consensus address.\n uint256 internal _emergencyExitLockedAmount;\n /// @dev The duration that an emergency request is expired and the fund will be recycled.\n uint256 internal _emergencyExpiryDuration;\n /// @dev The address list of consensus addresses that being locked fund.\n address[] internal _lockedConsensusList;\n /// @dev Mapping from consensus => request exist info\n mapping(address => EmergencyExitInfo) internal _exitInfo;\n /// @dev Mapping from consensus => flag indicating whether the locked fund is released\n mapping(address => bool) internal _lockedFundReleased;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[44] private ______gap;\n\n /**\n * @inheritdoc ICommonInfo\n */\n function getEmergencyExitInfo(\n address _consensusAddr\n ) external view override returns (EmergencyExitInfo memory _info) {\n _info = _exitInfo[_consensusAddr];\n if (_info.recyclingAt == 0) revert NonExistentRecyclingInfo();\n }\n\n /**\n * @inheritdoc ICommonInfo\n */\n function totalDeprecatedReward() external view override returns (uint256) {\n return _totalDeprecatedReward;\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function epochOf(\n uint256 _block\n ) public view virtual override(ITimingInfo, JailingStorage, TimingStorage) returns (uint256) {\n return TimingStorage.epochOf(_block);\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function currentPeriod() public view virtual override(ITimingInfo, JailingStorage, TimingStorage) returns (uint256) {\n return TimingStorage.currentPeriod();\n }\n}\n" + }, + "contracts/ronin/validator/storage-fragments/JailingStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../../interfaces/validator/info-fragments/IJailingInfo.sol\";\nimport \"./TimingStorage.sol\";\n\nabstract contract JailingStorage is IJailingInfo {\n /// @dev Mapping from consensus address => period number => block producer has no pending reward.\n mapping(address => mapping(uint256 => bool)) internal _miningRewardDeprecatedAtPeriod;\n /// @dev Mapping from consensus address => period number => whether the block producer get cut off reward, due to bailout.\n mapping(address => mapping(uint256 => bool)) internal _miningRewardBailoutCutOffAtPeriod;\n /// @dev Mapping from consensus address => period number => block operator has no pending reward.\n mapping(address => mapping(uint256 => bool)) internal ______deprecatedBridgeRewardDeprecatedAtPeriod;\n\n /// @dev Mapping from consensus address => the last block that the block producer is jailed.\n mapping(address => uint256) internal _blockProducerJailedBlock;\n /// @dev Mapping from consensus address => the last timestamp that the bridge operator is jailed.\n mapping(address => uint256) internal _emergencyExitJailedTimestamp;\n /// @dev Mapping from consensus address => the last block that the block producer cannot bailout.\n mapping(address => uint256) internal _cannotBailoutUntilBlock;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[48] private ______gap;\n\n /**\n * @inheritdoc IJailingInfo\n */\n function checkJailed(address _addr) external view override returns (bool) {\n return checkJailedAtBlock(_addr, block.number);\n }\n\n /**\n * @inheritdoc IJailingInfo\n */\n function getJailedTimeLeft(\n address _addr\n ) external view override returns (bool isJailed_, uint256 blockLeft_, uint256 epochLeft_) {\n return getJailedTimeLeftAtBlock(_addr, block.number);\n }\n\n /**\n * @inheritdoc IJailingInfo\n */\n function checkJailedAtBlock(address _addr, uint256 _blockNum) public view override returns (bool) {\n return _jailedAtBlock(_addr, _blockNum);\n }\n\n /**\n * @inheritdoc IJailingInfo\n */\n function getJailedTimeLeftAtBlock(\n address _addr,\n uint256 _blockNum\n ) public view override returns (bool isJailed_, uint256 blockLeft_, uint256 epochLeft_) {\n uint256 _jailedBlock = _blockProducerJailedBlock[_addr];\n if (_jailedBlock < _blockNum) {\n return (false, 0, 0);\n }\n\n isJailed_ = true;\n blockLeft_ = _jailedBlock - _blockNum + 1;\n epochLeft_ = epochOf(_jailedBlock) - epochOf(_blockNum) + 1;\n }\n\n /**\n * @inheritdoc IJailingInfo\n */\n function checkManyJailed(address[] calldata _addrList) external view override returns (bool[] memory _result) {\n _result = new bool[](_addrList.length);\n for (uint256 _i; _i < _addrList.length; ) {\n _result[_i] = _jailed(_addrList[_i]);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IJailingInfo\n */\n function checkMiningRewardDeprecated(address _blockProducer) external view override returns (bool _result) {\n uint256 _period = currentPeriod();\n return _miningRewardDeprecated(_blockProducer, _period);\n }\n\n /**\n * @inheritdoc IJailingInfo\n */\n function checkMiningRewardDeprecatedAtPeriod(\n address _blockProducer,\n uint256 _period\n ) external view override returns (bool _result) {\n return _miningRewardDeprecated(_blockProducer, _period);\n }\n\n /**\n * @dev See `ITimingInfo-epochOf`\n */\n function epochOf(uint256 _block) public view virtual returns (uint256);\n\n /**\n * @dev See `ITimingInfo-currentPeriod`\n */\n function currentPeriod() public view virtual returns (uint256);\n\n /**\n * @dev Returns whether the reward of the validator is put in jail (cannot join the set of validators) during the current period.\n */\n function _jailed(address _validatorAddr) internal view returns (bool) {\n return _jailedAtBlock(_validatorAddr, block.number);\n }\n\n /**\n * @dev Returns whether the reward of the validator is put in jail (cannot join the set of validators) at a specific block.\n */\n function _jailedAtBlock(address _validatorAddr, uint256 _blockNum) internal view returns (bool) {\n return _blockNum <= _blockProducerJailedBlock[_validatorAddr];\n }\n\n /**\n * @dev Returns whether the block producer has no pending reward in that period.\n */\n function _miningRewardDeprecated(address _validatorAddr, uint256 _period) internal view returns (bool) {\n return _miningRewardDeprecatedAtPeriod[_validatorAddr][_period];\n }\n}\n" + }, + "contracts/ronin/validator/storage-fragments/TimingStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../../extensions/consumers/GlobalConfigConsumer.sol\";\nimport \"../../../interfaces/validator/info-fragments/ITimingInfo.sol\";\n\nabstract contract TimingStorage is ITimingInfo, GlobalConfigConsumer {\n /// @dev The number of blocks in a epoch\n uint256 internal _numberOfBlocksInEpoch;\n /// @dev The last updated block\n uint256 internal _lastUpdatedBlock;\n /// @dev The last updated period\n uint256 internal _lastUpdatedPeriod;\n /// @dev The starting block of the last updated period\n uint256 internal _currentPeriodStartAtBlock;\n\n /// @dev Mapping from epoch index => period index\n mapping(uint256 => uint256) internal _periodOf;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[49] private ______gap;\n\n /**\n * @inheritdoc ITimingInfo\n */\n function getLastUpdatedBlock() external view override returns (uint256) {\n return _lastUpdatedBlock;\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function epochOf(uint256 _block) public view virtual override returns (uint256) {\n return _block / _numberOfBlocksInEpoch + 1;\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function tryGetPeriodOfEpoch(uint256 _epoch) external view returns (bool _filled, uint256 _periodNumber) {\n return (_epoch <= epochOf(block.number) || _periodOf[_epoch] > 0, _periodOf[_epoch]);\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function isPeriodEnding() external view override returns (bool) {\n return _isPeriodEnding(_computePeriod(block.timestamp));\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function epochEndingAt(uint256 _block) public view virtual override returns (bool) {\n return _block % _numberOfBlocksInEpoch == _numberOfBlocksInEpoch - 1;\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function currentPeriod() public view virtual override returns (uint256) {\n return _lastUpdatedPeriod;\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function currentPeriodStartAtBlock() public view override returns (uint256) {\n return _currentPeriodStartAtBlock;\n }\n\n /**\n * @inheritdoc ITimingInfo\n */\n function numberOfBlocksInEpoch() public view virtual override returns (uint256 _numberOfBlocks) {\n return _numberOfBlocksInEpoch;\n }\n\n /**\n * @dev See `ITimingInfo-isPeriodEnding`\n */\n function _isPeriodEnding(uint256 _newPeriod) internal view virtual returns (bool) {\n return _newPeriod > _lastUpdatedPeriod;\n }\n\n /**\n * @dev Returns the calculated period.\n */\n function _computePeriod(uint256 _timestamp) internal pure returns (uint256) {\n return _timestamp / PERIOD_DURATION;\n }\n}\n" + }, + "contracts/ronin/validator/storage-fragments/ValidatorInfoStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../../libraries/EnumFlags.sol\";\nimport { HasTrustedOrgDeprecated } from \"../../../utils/DeprecatedSlots.sol\";\nimport \"../../../extensions/collections/HasContracts.sol\";\nimport \"../../../interfaces/validator/info-fragments/IValidatorInfo.sol\";\n\nabstract contract ValidatorInfoStorage is IValidatorInfo, HasContracts, HasTrustedOrgDeprecated {\n using EnumFlags for EnumFlags.ValidatorFlag;\n\n /// @dev The maximum number of validator.\n uint256 internal _maxValidatorNumber;\n\n /// @dev The total of validators\n uint256 public validatorCount;\n /// @dev Mapping from validator index => validator address\n mapping(uint256 => address) internal _validators;\n /// @dev Mapping from address => flag indicating the validator ability: producing block, operating bridge\n mapping(address => EnumFlags.ValidatorFlag) internal _validatorMap;\n /// @dev The number of slot that is reserved for prioritized validators\n uint256 internal _maxPrioritizedValidatorNumber;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function getValidators()\n public\n view\n override\n returns (\n address[] memory _validatorList,\n address[] memory _bridgeOperators,\n EnumFlags.ValidatorFlag[] memory _flags\n )\n {\n _validatorList = new address[](validatorCount);\n _bridgeOperators = new address[](validatorCount);\n _flags = new EnumFlags.ValidatorFlag[](validatorCount);\n for (uint _i; _i < _validatorList.length; ) {\n address _validator = _validators[_i];\n _validatorList[_i] = _validator;\n _bridgeOperators[_i] = _bridgeOperatorOf(_validator);\n _flags[_i] = _validatorMap[_validator];\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function isValidator(address _addr) public view override returns (bool) {\n return !_validatorMap[_addr].isNone();\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function getBlockProducers() public view override returns (address[] memory _result) {\n _result = new address[](validatorCount);\n uint256 _count = 0;\n for (uint _i; _i < _result.length; ) {\n if (isBlockProducer(_validators[_i])) {\n _result[_count++] = _validators[_i];\n }\n\n unchecked {\n ++_i;\n }\n }\n\n assembly {\n mstore(_result, _count)\n }\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function isBlockProducer(address _addr) public view override returns (bool) {\n return _validatorMap[_addr].hasFlag(EnumFlags.ValidatorFlag.BlockProducer);\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function totalBlockProducer() external view returns (uint256 _total) {\n unchecked {\n for (uint _i; _i < validatorCount; _i++) {\n if (isBlockProducer(_validators[_i])) {\n _total++;\n }\n }\n }\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function getBridgeOperators()\n public\n view\n override\n returns (address[] memory _bridgeOperatorList, address[] memory _validatorList)\n {\n uint256 _length = validatorCount;\n _bridgeOperatorList = new address[](_length);\n _validatorList = new address[](_length);\n uint256 _count = 0;\n unchecked {\n for (uint _i; _i < _length; ++_i) {\n if (isOperatingBridge(_validators[_i])) {\n address __validator = _validators[_i];\n _bridgeOperatorList[_count] = _bridgeOperatorOf(__validator);\n _validatorList[_count++] = __validator;\n }\n }\n }\n\n assembly {\n mstore(_bridgeOperatorList, _count)\n mstore(_validatorList, _count)\n }\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function getBridgeOperatorsOf(\n address[] memory _validatorAddrs\n ) public view override returns (address[] memory _bridgeOperatorList) {\n _bridgeOperatorList = new address[](_validatorAddrs.length);\n for (uint _i; _i < _bridgeOperatorList.length; ) {\n _bridgeOperatorList[_i] = _bridgeOperatorOf(_validatorAddrs[_i]);\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function isBridgeOperator(address _bridgeOperatorAddr) external view override returns (bool _isOperator) {\n for (uint _i; _i < validatorCount; ) {\n if (_bridgeOperatorOf(_validators[_i]) == _bridgeOperatorAddr && isOperatingBridge(_validators[_i])) {\n _isOperator = true;\n break;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function isOperatingBridge(address _consensusAddr) public view override returns (bool) {\n return _validatorMap[_consensusAddr].hasFlag(EnumFlags.ValidatorFlag.DeprecatedBridgeOperator);\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function maxValidatorNumber() external view override returns (uint256 _maximumValidatorNumber) {\n return _maxValidatorNumber;\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function maxPrioritizedValidatorNumber() external view override returns (uint256 _maximumPrioritizedValidatorNumber) {\n return _maxPrioritizedValidatorNumber;\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function totalBridgeOperator() public view returns (uint256 _total) {\n unchecked {\n for (uint _i; _i < validatorCount; _i++) {\n if (isOperatingBridge(_validators[_i])) {\n _total++;\n }\n }\n }\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function setMaxValidatorNumber(uint256 _max) external override onlyAdmin {\n _setMaxValidatorNumber(_max);\n }\n\n /**\n * @inheritdoc IValidatorInfo\n */\n function setMaxPrioritizedValidatorNumber(uint256 _number) external override onlyAdmin {\n _setMaxPrioritizedValidatorNumber(_number);\n }\n\n /**\n * @dev Returns the bridge operator of a consensus address.\n */\n function _bridgeOperatorOf(address _consensusAddr) internal view virtual returns (address);\n\n /**\n * @dev See `IValidatorInfo-setMaxValidatorNumber`\n */\n function _setMaxValidatorNumber(uint256 _number) internal {\n _maxValidatorNumber = _number;\n emit MaxValidatorNumberUpdated(_number);\n }\n\n /**\n * @dev See `IValidatorInfo-setMaxPrioritizedValidatorNumber`\n */\n function _setMaxPrioritizedValidatorNumber(uint256 _number) internal {\n if (_number > _maxValidatorNumber) revert ErrInvalidMaxPrioritizedValidatorNumber();\n _maxPrioritizedValidatorNumber = _number;\n emit MaxPrioritizedValidatorNumberUpdated(_number);\n }\n}\n" + }, + "contracts/ronin/validator/storage-fragments/ValidatorInfoStorageV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../../../libraries/EnumFlags.sol\";\nimport { HasTrustedOrgDeprecated } from \"../../../utils/DeprecatedSlots.sol\";\nimport \"../../../extensions/collections/HasContracts.sol\";\nimport \"../../../interfaces/validator/info-fragments/IValidatorInfoV2.sol\";\n\nabstract contract ValidatorInfoStorageV2 is IValidatorInfoV2, HasContracts, HasTrustedOrgDeprecated {\n using EnumFlags for EnumFlags.ValidatorFlag;\n\n /// @dev The maximum number of validator.\n uint256 internal _maxValidatorNumber;\n\n /// @dev The total of validators\n uint256 public validatorCount;\n /// @dev Mapping from validator index => validator address\n mapping(uint256 => address) internal _validators;\n /// @dev Mapping from address => flag indicating the validator ability: producing block, operating bridge\n mapping(address => EnumFlags.ValidatorFlag) internal _validatorMap;\n /// @dev The number of slot that is reserved for prioritized validators\n uint256 internal _maxPrioritizedValidatorNumber;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n */\n uint256[50] private ______gap;\n\n /**\n * @inheritdoc IValidatorInfoV2\n */\n function getValidators() public view override returns (address[] memory _validatorList) {\n _validatorList = new address[](validatorCount);\n for (uint _i; _i < _validatorList.length; ) {\n address _validator = _validators[_i];\n _validatorList[_i] = _validator;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n * @inheritdoc IValidatorInfoV2\n */\n function getBlockProducers() public view override returns (address[] memory _result) {\n _result = new address[](validatorCount);\n uint256 _count = 0;\n for (uint _i; _i < _result.length; ) {\n if (isBlockProducer(_validators[_i])) {\n _result[_count++] = _validators[_i];\n }\n\n unchecked {\n ++_i;\n }\n }\n\n assembly {\n mstore(_result, _count)\n }\n }\n\n /**\n * @inheritdoc IValidatorInfoV2\n */\n function isBlockProducer(address _addr) public view override returns (bool) {\n return _validatorMap[_addr].hasFlag(EnumFlags.ValidatorFlag.BlockProducer);\n }\n\n /**\n * @inheritdoc IValidatorInfoV2\n */\n function totalBlockProducer() external view returns (uint256 _total) {\n unchecked {\n for (uint _i; _i < validatorCount; _i++) {\n if (isBlockProducer(_validators[_i])) {\n _total++;\n }\n }\n }\n }\n\n /**\n * @inheritdoc IValidatorInfoV2\n */\n function maxValidatorNumber() external view override returns (uint256 _maximumValidatorNumber) {\n return _maxValidatorNumber;\n }\n\n /**\n * @inheritdoc IValidatorInfoV2\n */\n function maxPrioritizedValidatorNumber() external view override returns (uint256 _maximumPrioritizedValidatorNumber) {\n return _maxPrioritizedValidatorNumber;\n }\n\n /**\n * @inheritdoc IValidatorInfoV2\n */\n function setMaxValidatorNumber(uint256 _max) external override onlyAdmin {\n _setMaxValidatorNumber(_max);\n }\n\n /**\n * @inheritdoc IValidatorInfoV2\n */\n function setMaxPrioritizedValidatorNumber(uint256 _number) external override onlyAdmin {\n _setMaxPrioritizedValidatorNumber(_number);\n }\n\n /**\n * @dev See `IValidatorInfoV2-setMaxValidatorNumber`\n */\n function _setMaxValidatorNumber(uint256 _number) internal {\n _maxValidatorNumber = _number;\n emit MaxValidatorNumberUpdated(_number);\n }\n\n /**\n * @dev See `IValidatorInfoV2-setMaxPrioritizedValidatorNumber`\n */\n function _setMaxPrioritizedValidatorNumber(uint256 _number) internal {\n if (_number > _maxValidatorNumber) revert ErrInvalidMaxPrioritizedValidatorNumber();\n _maxPrioritizedValidatorNumber = _number;\n emit MaxPrioritizedValidatorNumberUpdated(_number);\n }\n}\n" + }, + "contracts/ronin/VaultForwarder.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.9;\n\nimport \"../extensions/forwarder/Forwarder.sol\";\nimport \"../extensions/RONTransferHelper.sol\";\n\n/**\n * @title A vault contract that keeps RON, and behaves as an EOA account to interact with a target contract.\n * @dev There are three roles of interaction:\n * - Admin: top-up and withdraw RON to the vault, cannot forward call to the target.\n * - Moderator: forward all calls to the target, can top-up RON, cannot withdraw RON.\n * - Others: can top-up RON, cannot execute any other actions.\n */\ncontract VaultForwarder is Forwarder, RONTransferHelper {\n /// @dev Emitted when the admin withdraws all RON from the forwarder contract.\n event ForwarderRONWithdrawn(address indexed _recipient, uint256 _value);\n\n constructor(address[] memory _targets, address _admin, address _mod) Forwarder(_targets, _admin, _mod) {}\n\n /**\n * @dev Withdraws all balance from the transfer to the admin.\n *\n * Requirements:\n * - Only the admin can call this method.\n */\n function withdrawAll() external onlyRole(DEFAULT_ADMIN_ROLE) {\n uint256 _value = address(this).balance;\n emit ForwarderRONWithdrawn(msg.sender, _value);\n _transferRON(payable(msg.sender), _value);\n }\n}\n" + }, + "contracts/types/operations/LibTUint256Slot.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { TUint256Slot } from \"../Types.sol\";\n\n/**\n * @title LibTUint256Slot\n * @dev Library for handling unsigned 256-bit integers.\n */\nlibrary LibTUint256Slot {\n /// @dev value is equal to bytes4(keccak256(\"Panic(uint256)\"))\n /// @dev see: https://github.com/foundry-rs/forge-std/blob/master/src/StdError.sol\n uint256 private constant PANIC_ERROR_SIGNATURE = 0x4e487b71;\n /// @dev error code for {Arithmetic over/underflow} error\n uint256 private constant ARITHMETIC_ERROR_CODE = 0x11;\n /// @dev error code for {Division or modulo by 0} error\n uint256 private constant DIVISION_ERROR_CODE = 0x12;\n\n /**\n * @dev Loads the value of the TUint256Slot variable.\n * @param self The TUint256Slot variable.\n * @return val The loaded value.\n */\n function load(TUint256Slot self) internal view returns (uint256 val) {\n assembly {\n val := sload(self)\n }\n }\n\n /**\n * @dev Stores a value into the TUint256Slot variable.\n * @param self The TUint256Slot variable.\n * @param other The value to be stored.\n */\n function store(TUint256Slot self, uint256 other) internal {\n assembly {\n sstore(self, other)\n }\n }\n\n /**\n * @dev Multiplies the TUint256Slot variable by a given value.\n * @param self The TUint256Slot variable.\n * @param other The value to multiply by.\n * @return res The resulting value after multiplication.\n */\n function mul(TUint256Slot self, uint256 other) internal view returns (uint256 res) {\n assembly {\n let storedVal := sload(self)\n if iszero(iszero(storedVal)) {\n res := mul(storedVal, other)\n\n // Overflow check\n if iszero(eq(other, div(res, storedVal))) {\n // Store 4 bytes the function selector of Panic(uint256)\n // Equivalent to revert Panic(uint256)\n mstore(0x00, PANIC_ERROR_SIGNATURE)\n // Store 4 bytes of division error code in the next slot\n mstore(0x20, ARITHMETIC_ERROR_CODE)\n // Revert 36 bytes of error starting from 0x1c\n revert(0x1c, 0x24)\n }\n }\n }\n }\n\n /**\n * @dev Divides the TUint256Slot variable by a given value.\n * @param self The TUint256Slot variable.\n * @param other The value to divide by.\n * @return res The resulting value after division.\n */\n function div(TUint256Slot self, uint256 other) internal view returns (uint256 res) {\n assembly {\n let storedVal := sload(self)\n // revert if divide by zero\n if iszero(other) {\n // Store 4 bytes the function selector of Panic(uint256)\n // Equivalent to revert Panic(uint256)\n mstore(0x00, PANIC_ERROR_SIGNATURE)\n // Store 4 bytes of division error code in the next slot\n mstore(0x20, DIVISION_ERROR_CODE)\n // Revert 36 bytes of error starting from 0x1c\n revert(0x1c, 0x24)\n }\n res := div(storedVal, other)\n }\n }\n\n /**\n * @dev Subtracts a given value from the TUint256Slot variable.\n * @param self The TUint256Slot variable.\n * @param other The value to subtract.\n * @return res The resulting value after subtraction.\n */\n function sub(TUint256Slot self, uint256 other) internal view returns (uint256 res) {\n assembly {\n let storedVal := sload(self)\n\n // Underflow check\n if lt(storedVal, other) {\n // Store 4 bytes the function selector of Panic(uint256)\n // Equivalent to revert Panic(uint256)\n mstore(0x00, PANIC_ERROR_SIGNATURE)\n // Store 4 bytes of division error code in the next slot\n mstore(0x20, ARITHMETIC_ERROR_CODE)\n // Revert 36 bytes of error starting from 0x1c\n revert(0x1c, 0x24)\n }\n\n res := sub(storedVal, other)\n }\n }\n\n /**\n * @dev Adds a given value to the TUint256Slot variable.\n * @param self The TUint256Slot variable.\n * @param other The value to add.\n * @return res The resulting value after addition.\n */\n function add(TUint256Slot self, uint256 other) internal view returns (uint256 res) {\n assembly {\n let storedVal := sload(self)\n res := add(storedVal, other)\n\n // Overflow check\n if lt(res, other) {\n // Store 4 bytes the function selector of Panic(uint256)\n // Equivalent to revert Panic(uint256)\n mstore(0x00, PANIC_ERROR_SIGNATURE)\n // Store 4 bytes of division error code in the next slot\n mstore(0x20, ARITHMETIC_ERROR_CODE)\n // Revert 36 bytes of error starting from 0x1c\n revert(0x1c, 0x24)\n }\n }\n }\n\n /**\n * @dev Increments the TUint256Slot variable by 1 and returns the new value.\n * @param self The TUint256Slot variable.\n * @return res The resulting value after incrementing.\n */\n function preIncrement(TUint256Slot self) internal returns (uint256 res) {\n res = addAssign(self, 1);\n }\n\n /**\n * @dev Increments the TUint256Slot variable by 1 and returns the original value.\n * @param self The TUint256Slot variable.\n * @return res The original value before incrementing.\n */\n function postIncrement(TUint256Slot self) internal returns (uint256 res) {\n res = load(self);\n store(self, res + 1);\n }\n\n /**\n * @dev Decrements the TUint256Slot variable by 1 and returns the new value.\n * @param self The TUint256Slot variable.\n * @return res The resulting value after decrementing.\n */\n function preDecrement(TUint256Slot self) internal returns (uint256 res) {\n res = subAssign(self, 1);\n }\n\n /**\n * @dev Decrements the TUint256Slot variable by 1 and returns the new value.\n * @param self The TUint256Slot variable.\n * @return res The resulting value before decrementing.\n */\n function postDecrement(TUint256Slot self) internal returns (uint256 res) {\n res = load(self);\n store(self, res - 1);\n }\n\n /**\n * @dev Adds a given value to the TUint256Slot variable and stores the result.\n * @param self The TUint256Slot variable.\n * @param other The value to add.\n * @return res The resulting value after addition and storage.\n */\n function addAssign(TUint256Slot self, uint256 other) internal returns (uint256 res) {\n store(self, res = add(self, other));\n }\n\n /**\n * @dev Subtracts a given value from the TUint256Slot variable and stores the result.\n * @param self The TUint256Slot variable.\n * @param other The value to subtract.\n * @return res The resulting value after subtraction and storage.\n */\n function subAssign(TUint256Slot self, uint256 other) internal returns (uint256 res) {\n store(self, res = sub(self, other));\n }\n}\n" + }, + "contracts/types/Types.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { LibTUint256Slot } from \"./operations/LibTUint256Slot.sol\";\n\ntype TUint256Slot is bytes32;\n\nusing {\n LibTUint256Slot.add,\n LibTUint256Slot.sub,\n LibTUint256Slot.mul,\n LibTUint256Slot.div,\n LibTUint256Slot.load,\n LibTUint256Slot.store,\n LibTUint256Slot.addAssign,\n LibTUint256Slot.subAssign,\n LibTUint256Slot.preDecrement,\n LibTUint256Slot.postDecrement,\n LibTUint256Slot.preIncrement,\n LibTUint256Slot.postIncrement\n} for TUint256Slot global;\n" + }, + "contracts/utils/CommonErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ContractType } from \"./ContractType.sol\";\nimport { RoleAccess } from \"./RoleAccess.sol\";\n\nerror ErrSyncTooFarPeriod(uint256 period, uint256 latestRewardedPeriod);\n/**\n * @dev Error thrown when an address is expected to be an already created externally owned account (EOA).\n * This error indicates that the provided address is invalid for certain contract operations that require already created EOA.\n */\nerror ErrAddressIsNotCreatedEOA(address addr, bytes32 codehash);\n/**\n * @dev Error raised when a bridge operator update operation fails.\n * @param bridgeOperator The address of the bridge operator that failed to update.\n */\nerror ErrBridgeOperatorUpdateFailed(address bridgeOperator);\n/**\n * @dev Error thrown when attempting to add a bridge operator that already exists in the contract.\n * This error indicates that the provided bridge operator address is already registered as a bridge operator in the contract.\n */\nerror ErrBridgeOperatorAlreadyExisted(address bridgeOperator);\n/**\n * @dev The error indicating an unsupported interface.\n * @param interfaceId The bytes4 interface identifier that is not supported.\n * @param addr The address where the unsupported interface was encountered.\n */\nerror ErrUnsupportedInterface(bytes4 interfaceId, address addr);\n/**\n * @dev Error thrown when the return data from a callback function is invalid.\n * @param callbackFnSig The signature of the callback function that returned invalid data.\n * @param register The address of the register where the callback function was invoked.\n * @param returnData The invalid return data received from the callback function.\n */\nerror ErrInvalidReturnData(bytes4 callbackFnSig, address register, bytes returnData);\n/**\n * @dev Error of set to non-contract.\n */\nerror ErrZeroCodeContract(address addr);\n/**\n * @dev Error indicating that arguments are invalid.\n */\nerror ErrInvalidArguments(bytes4 msgSig);\n/**\n * @dev Error indicating that given address is null when it should not.\n */\nerror ErrZeroAddress(bytes4 msgSig);\n/**\n * @dev Error indicating that the provided threshold is invalid for a specific function signature.\n * @param msgSig The function signature (bytes4) that the invalid threshold applies to.\n */\nerror ErrInvalidThreshold(bytes4 msgSig);\n\n/**\n * @dev Error indicating that a function can only be called by the contract itself.\n * @param msgSig The function signature (bytes4) that can only be called by the contract itself.\n */\nerror ErrOnlySelfCall(bytes4 msgSig);\n\n/**\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\n * @param msgSig The function signature (bytes4) that the caller is unauthorized to perform.\n * @param expectedRole The role required to perform the function.\n */\nerror ErrUnauthorized(bytes4 msgSig, RoleAccess expectedRole);\n\n/**\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\n * @param msgSig The function signature (bytes4) that the caller is unauthorized to perform.\n */\nerror ErrUnauthorizedCall(bytes4 msgSig);\n\n/**\n * @dev Error indicating that the caller is unauthorized to perform a specific function.\n * @param msgSig The function signature (bytes4).\n * @param expectedContractType The contract type required to perform the function.\n * @param actual The actual address that called to the function.\n */\nerror ErrUnexpectedInternalCall(bytes4 msgSig, ContractType expectedContractType, address actual);\n\n/**\n * @dev Error indicating that an array is empty when it should contain elements.\n */\nerror ErrEmptyArray();\n\n/**\n * @dev Error indicating a mismatch in the length of input parameters or arrays for a specific function.\n * @param msgSig The function signature (bytes4) that has a length mismatch.\n */\nerror ErrLengthMismatch(bytes4 msgSig);\n\n/**\n * @dev Error indicating that a proxy call to an external contract has failed.\n * @param msgSig The function signature (bytes4) of the proxy call that failed.\n * @param extCallSig The function signature (bytes4) of the external contract call that failed.\n */\nerror ErrProxyCallFailed(bytes4 msgSig, bytes4 extCallSig);\n\n/**\n * @dev Error indicating that a function tried to call a precompiled contract that is not allowed.\n * @param msgSig The function signature (bytes4) that attempted to call a precompiled contract.\n */\nerror ErrCallPrecompiled(bytes4 msgSig);\n\n/**\n * @dev Error indicating that a native token transfer has failed.\n * @param msgSig The function signature (bytes4) of the token transfer that failed.\n */\nerror ErrNativeTransferFailed(bytes4 msgSig);\n\n/**\n * @dev Error indicating that an order is invalid.\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid order.\n */\nerror ErrInvalidOrder(bytes4 msgSig);\n\n/**\n * @dev Error indicating that the chain ID is invalid.\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid chain ID.\n * @param actual Current chain ID that executing function.\n * @param expected Expected chain ID required for the tx to success.\n */\nerror ErrInvalidChainId(bytes4 msgSig, uint256 actual, uint256 expected);\n\n/**\n * @dev Error indicating that a vote type is not supported.\n * @param msgSig The function signature (bytes4) of the operation that encountered an unsupported vote type.\n */\nerror ErrUnsupportedVoteType(bytes4 msgSig);\n\n/**\n * @dev Error indicating that the proposal nonce is invalid.\n * @param msgSig The function signature (bytes4) of the operation that encountered an invalid proposal nonce.\n */\nerror ErrInvalidProposalNonce(bytes4 msgSig);\n\n/**\n * @dev Error indicating that a voter has already voted.\n * @param voter The address of the voter who has already voted.\n */\nerror ErrAlreadyVoted(address voter);\n\n/**\n * @dev Error indicating that a signature is invalid for a specific function signature.\n * @param msgSig The function signature (bytes4) that encountered an invalid signature.\n */\nerror ErrInvalidSignatures(bytes4 msgSig);\n\n/**\n * @dev Error indicating that a relay call has failed.\n * @param msgSig The function signature (bytes4) of the relay call that failed.\n */\nerror ErrRelayFailed(bytes4 msgSig);\n/**\n * @dev Error indicating that a vote weight is invalid for a specific function signature.\n * @param msgSig The function signature (bytes4) that encountered an invalid vote weight.\n */\nerror ErrInvalidVoteWeight(bytes4 msgSig);\n\n/**\n * @dev Error indicating that a query was made for an outdated bridge operator set.\n */\nerror ErrQueryForOutdatedBridgeOperatorSet();\n\n/**\n * @dev Error indicating that a request is invalid.\n */\nerror ErrInvalidRequest();\n\n/**\n * @dev Error indicating that a token standard is invalid.\n */\nerror ErrInvalidTokenStandard();\n\n/**\n * @dev Error indicating that a token is not supported.\n */\nerror ErrUnsupportedToken();\n\n/**\n * @dev Error indicating that a receipt kind is invalid.\n */\nerror ErrInvalidReceiptKind();\n\n/**\n * @dev Error indicating that a receipt is invalid.\n */\nerror ErrInvalidReceipt();\n\n/**\n * @dev Error indicating that an address is not payable.\n */\nerror ErrNonpayableAddress(address);\n\n/**\n * @dev Error indicating that the period is already processed, i.e. scattered reward.\n */\nerror ErrPeriodAlreadyProcessed(uint256 requestingPeriod, uint256 latestPeriod);\n\n/**\n * @dev Error thrown when an invalid vote hash is provided.\n */\nerror ErrInvalidVoteHash();\n\n/**\n * @dev Error thrown when querying for an empty vote.\n */\nerror ErrQueryForEmptyVote();\n\n/**\n * @dev Error thrown when querying for an expired vote.\n */\nerror ErrQueryForExpiredVote();\n\n/**\n * @dev Error thrown when querying for a non-existent vote.\n */\nerror ErrQueryForNonExistentVote();\n\n/**\n * @dev Error indicating that the method is only called once per block.\n */\nerror ErrOncePerBlock();\n\n/**\n * @dev Error of method caller must be coinbase\n */\nerror ErrCallerMustBeCoinbase();\n" + }, + "contracts/utils/ContractType.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nenum ContractType {\n /* 0 */ UNKNOWN,\n /* 1 */ PAUSE_ENFORCER,\n /* 2 */ BRIDGE,\n /* 3 */ BRIDGE_TRACKING,\n /* 4 */ GOVERNANCE_ADMIN,\n /* 5 */ MAINTENANCE,\n /* 6 */ SLASH_INDICATOR,\n /* 7 */ STAKING_VESTING,\n /* 8 */ VALIDATOR,\n /* 9 */ STAKING,\n /* 10 */ RONIN_TRUSTED_ORGANIZATION,\n /* 11 */ BRIDGE_MANAGER,\n /* 12 */ BRIDGE_SLASH,\n /* 13 */ BRIDGE_REWARD,\n /* 14 */ FAST_FINALITY_TRACKING,\n /* 15 */ PROFILE\n}\n" + }, + "contracts/utils/DeprecatedSlots.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Deprecated Contracts\n * @dev These abstract contracts are deprecated and should not be used in new implementations.\n * They provide functionality related to various aspects of a smart contract but have been marked\n * as deprecated to indicate that they are no longer actively maintained or recommended for use.\n * The purpose of these contracts is to preserve the slots for already deployed contracts.\n */\ncontract HasSlashIndicatorDeprecated {\n /// @custom:deprecated Previously `_slashIndicatorContract` (non-zero value)\n address internal ______deprecatedSlashIndicator;\n}\n\ncontract HasStakingVestingDeprecated {\n /// @custom:deprecated Previously `_stakingVestingContract` (non-zero value)\n address internal ______deprecatedStakingVesting;\n}\n\ncontract HasBridgeDeprecated {\n /// @custom:deprecated Previously `_bridgeContract` (non-zero value)\n address internal ______deprecatedBridge;\n}\n\ncontract HasValidatorDeprecated {\n /// @custom:deprecated Previously `_validatorContract` (non-zero value)\n address internal ______deprecatedValidator;\n}\n\ncontract HasStakingDeprecated {\n /// @custom:deprecated Previously `_stakingContract` (non-zero value)\n address internal ______deprecatedStakingContract;\n}\n\ncontract HasMaintenanceDeprecated {\n /// @custom:deprecated Previously `_maintenanceContract` (non-zero value)\n address internal ______deprecatedMaintenance;\n}\n\ncontract HasTrustedOrgDeprecated {\n /// @custom:deprecated Previously `_trustedOrgContract` (non-zero value)\n address internal ______deprecatedTrustedOrg;\n}\n\ncontract HasGovernanceAdminDeprecated {\n /// @custom:deprecated Previously `_governanceAdminContract` (non-zero value)\n address internal ______deprecatedGovernanceAdmin;\n}\n\ncontract HasBridgeTrackingDeprecated {\n /// @custom:deprecated Previously `_bridgeTrackingContract` (non-zero value)\n address internal ______deprecatedBridgeTracking;\n}\n" + }, + "contracts/utils/IdentityGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { AddressArrayUtils } from \"../libraries/AddressArrayUtils.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { TransparentUpgradeableProxyV2 } from \"../extensions/TransparentUpgradeableProxyV2.sol\";\nimport { ErrAddressIsNotCreatedEOA, ErrZeroAddress, ErrOnlySelfCall, ErrZeroCodeContract, ErrUnsupportedInterface } from \"./CommonErrors.sol\";\n\nabstract contract IdentityGuard {\n using AddressArrayUtils for address[];\n\n /// @dev value is equal to keccak256(abi.encode())\n /// @dev see: https://eips.ethereum.org/EIPS/eip-1052\n bytes32 internal constant CREATED_ACCOUNT_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n\n /**\n * @dev Modifier to restrict functions to only be called by this contract.\n * @dev Reverts if the caller is not this contract.\n */\n modifier onlySelfCall() virtual {\n _requireSelfCall();\n _;\n }\n\n /**\n * @dev Modifier to ensure that the elements in the `arr` array are non-duplicates.\n * It calls the internal `_checkDuplicate` function to perform the duplicate check.\n *\n * Requirements:\n * - The elements in the `arr` array must not contain any duplicates.\n */\n modifier nonDuplicate(address[] memory arr) virtual {\n _requireNonDuplicate(arr);\n _;\n }\n\n /**\n * @dev Internal method to check the method caller.\n * @dev Reverts if the method caller is not this contract.\n */\n function _requireSelfCall() internal view virtual {\n if (msg.sender != address(this)) revert ErrOnlySelfCall(msg.sig);\n }\n\n /**\n * @dev Internal function to check if a contract address has code.\n * @param addr The address of the contract to check.\n * @dev Throws an error if the contract address has no code.\n */\n function _requireHasCode(address addr) internal view {\n if (addr.code.length == 0) revert ErrZeroCodeContract(addr);\n }\n\n /**\n * @dev Checks if an address is zero and reverts if it is.\n * @param addr The address to check.\n */\n function _requireNonZeroAddress(address addr) internal pure {\n if (addr == address(0)) revert ErrZeroAddress(msg.sig);\n }\n\n /**\n * @dev Check if arr is empty and revert if it is.\n * Checks if an array contains any duplicate addresses and reverts if duplicates are found.\n * @param arr The array of addresses to check.\n */\n function _requireNonDuplicate(address[] memory arr) internal pure {\n if (arr.hasDuplicate()) revert AddressArrayUtils.ErrDuplicated(msg.sig);\n }\n\n /**\n * @dev Internal function to require that the provided address is a created externally owned account (EOA).\n * This internal function is used to ensure that the provided address is a valid externally owned account (EOA).\n * It checks the codehash of the address against a predefined constant to confirm that the address is a created EOA.\n * @notice This method only works with non-state EOA accounts\n */\n function _requireCreatedEOA(address addr) internal view {\n _requireNonZeroAddress(addr);\n bytes32 codehash = addr.codehash;\n if (codehash != CREATED_ACCOUNT_HASH) revert ErrAddressIsNotCreatedEOA(addr, codehash);\n }\n\n /**\n * @dev Internal function to require that the specified contract supports the given interface. This method handle in\n * both case that the callee is either or not the proxy admin of the caller. If the contract does not support the\n * interface `interfaceId` or EIP165, a revert with the corresponding error message is triggered.\n *\n * @param contractAddr The address of the contract to check for interface support.\n * @param interfaceId The interface ID to check for support.\n */\n function _requireSupportsInterface(address contractAddr, bytes4 interfaceId) internal view {\n bytes memory supportsInterfaceParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\n (bool success, bytes memory returnOrRevertData) = contractAddr.staticcall(supportsInterfaceParams);\n if (!success) {\n (success, returnOrRevertData) = contractAddr.staticcall(\n abi.encodeCall(TransparentUpgradeableProxyV2.functionDelegateCall, (supportsInterfaceParams))\n );\n if (!success) revert ErrUnsupportedInterface(interfaceId, contractAddr);\n }\n if (!abi.decode(returnOrRevertData, (bool))) revert ErrUnsupportedInterface(interfaceId, contractAddr);\n }\n}\n" + }, + "contracts/utils/RoleAccess.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nenum RoleAccess {\n /* 0 */ UNKNOWN,\n /* 1 */ ADMIN,\n /* 2 */ COINBASE,\n /* 3 */ GOVERNOR,\n /* 4 */ CANDIDATE_ADMIN,\n /* 5 */ WITHDRAWAL_MIGRATOR,\n /* 6 */ __DEPRECATED_BRIDGE_OPERATOR,\n /* 7 */ BLOCK_PRODUCER,\n /* 8 */ VALIDATOR_CANDIDATE\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "storageLayout" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 28f0124ce..44dbe3bb4 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -102,13 +102,6 @@ const compilerConfig: SolcUserConfig = { enabled: true, runs: 200, }, - /// @dev see: https://github.com/Uniswap/v3-core/blob/main/hardhat.config.ts - metadata: { - // do not include the metadata hash, since this is machine dependent - // and we want all generated code to be deterministic - // https://docs.soliditylang.org/en/v0.8.17/metadata.html - bytecodeHash: 'none', - }, }, }; @@ -123,6 +116,13 @@ const config: HardhatUserConfig = { enabled: true, runs: 10, }, + /// @dev see: https://github.com/Uniswap/v3-core/blob/main/hardhat.config.ts + metadata: { + // do not include the metadata hash, since this is machine dependent + // and we want all generated code to be deterministic + // https://docs.soliditylang.org/en/v0.8.17/metadata.html + bytecodeHash: 'none', + }, }, }, }, diff --git a/logs/contract_code_sizes.log b/logs/contract_code_sizes.log index 6fad63f74..11b37b431 100644 --- a/logs/contract_code_sizes.log +++ b/logs/contract_code_sizes.log @@ -3,173 +3,173 @@ ············································|···························|················· | Contract Name · Size (KiB) · Change (KiB) │ ············································|···························|················· - | Address · 0.044 · │ + | Address · 0.084 · │ ············································|···························|················· - | AddressArrayUtils · 0.044 · │ + | AddressArrayUtils · 0.084 · │ ············································|···························|················· - | Ballot · 0.044 · │ + | Ballot · 0.084 · │ ············································|···························|················· - | BridgeOperatorsBallot · 0.122 · │ + | BridgeOperatorsBallot · 0.162 · │ ············································|···························|················· - | BridgeReward · 5.646 · │ + | BridgeReward · 5.687 · │ ············································|···························|················· - | BridgeSlash · 5.212 · │ + | BridgeSlash · 5.252 · │ ············································|···························|················· - | BridgeTracking · 6.530 · │ + | BridgeTracking · 6.570 · │ ············································|···························|················· - | ECDSA · 0.044 · │ + | ECDSA · 0.084 · │ ············································|···························|················· - | EmergencyExitBallot · 0.044 · │ + | EmergencyExitBallot · 0.084 · │ ············································|···························|················· - | EnumerableSet · 0.044 · │ + | EnumerableSet · 0.084 · │ ············································|···························|················· - | EnumFlags · 0.044 · │ + | EnumFlags · 0.084 · │ ············································|···························|················· - | ERC1967Proxy · 0.133 · │ + | ERC1967Proxy · 0.173 · │ ············································|···························|················· - | ERC20 · 2.081 · │ + | ERC20 · 2.121 · │ ············································|···························|················· - | ERC20PresetMinterPauser · 6.179 · │ + | ERC20PresetMinterPauser · 6.219 · │ ············································|···························|················· - | ErrorHandler · 0.044 · │ + | ErrorHandler · 0.084 · │ ············································|···························|················· - | FastFinalityTracking · 2.063 · │ + | FastFinalityTracking · 2.104 · │ ············································|···························|················· - | Forwarder · 3.398 · │ + | Forwarder · 3.438 · │ ············································|···························|················· - | GlobalProposal · 0.122 · │ + | GlobalProposal · 0.162 · │ ············································|···························|················· - | HasBridgeDeprecated · 0.021 · │ + | HasBridgeDeprecated · 0.062 · │ ············································|···························|················· - | HasBridgeTrackingDeprecated · 0.021 · │ + | HasBridgeTrackingDeprecated · 0.062 · │ ············································|···························|················· - | HasGovernanceAdminDeprecated · 0.021 · │ + | HasGovernanceAdminDeprecated · 0.062 · │ ············································|···························|················· - | HasMaintenanceDeprecated · 0.021 · │ + | HasMaintenanceDeprecated · 0.062 · │ ············································|···························|················· - | HasSlashIndicatorDeprecated · 0.021 · │ + | HasSlashIndicatorDeprecated · 0.062 · │ ············································|···························|················· - | HasStakingDeprecated · 0.021 · │ + | HasStakingDeprecated · 0.062 · │ ············································|···························|················· - | HasStakingVestingDeprecated · 0.021 · │ + | HasStakingVestingDeprecated · 0.062 · │ ············································|···························|················· - | HasTrustedOrgDeprecated · 0.021 · │ + | HasTrustedOrgDeprecated · 0.062 · │ ············································|···························|················· - | HasValidatorDeprecated · 0.021 · │ + | HasValidatorDeprecated · 0.062 · │ ············································|···························|················· - | IsolatedGovernance · 0.044 · │ + | IsolatedGovernance · 0.084 · │ ············································|···························|················· - | LibTUint256Slot · 0.044 · │ + | LibTUint256Slot · 0.084 · │ ············································|···························|················· - | MainchainBridgeManager · 18.841 · │ + | MainchainBridgeManager · 18.881 · │ ············································|···························|················· - | MainchainGatewayV2 · 17.721 · │ + | MainchainGatewayV2 · 17.761 · │ ············································|···························|················· - | Maintenance · 6.359 · │ + | Maintenance · 6.399 · │ ············································|···························|················· - | Math · 0.044 · │ + | Math · 0.084 · │ ············································|···························|················· - | MockActor · 0.229 · │ + | MockActor · 0.269 · │ ············································|···························|················· - | MockBridge · 1.232 · │ + | MockBridge · 1.272 · │ ············································|···························|················· - | MockBridgeManager · 10.503 · │ + | MockBridgeManager · 10.543 · │ ············································|···························|················· - | MockBridgeReward · 6.368 · │ + | MockBridgeReward · 6.408 · │ ············································|···························|················· - | MockBridgeSlash · 5.365 · │ + | MockBridgeSlash · 5.405 · │ ············································|···························|················· - | MockConditionalImplementControl · 1.160 · │ + | MockConditionalImplementControl · 1.200 · │ ············································|···························|················· - | MockForwarderTarget · 1.271 · │ + | MockForwarderTarget · 1.312 · │ ············································|···························|················· - | MockGatewayForTracking · 1.583 · │ + | MockGatewayForTracking · 1.623 · │ ············································|···························|················· - | MockLogicV1 · 0.402 · │ + | MockLogicV1 · 0.442 · │ ············································|···························|················· - | MockLogicV2 · 0.402 · │ + | MockLogicV2 · 0.442 · │ ············································|···························|················· - | MockLogicValidatorSetV1 · 0.444 · │ + | MockLogicValidatorSetV1 · 0.484 · │ ············································|···························|················· - | MockLogicValidatorSetV2 · 0.444 · │ + | MockLogicValidatorSetV2 · 0.484 · │ ············································|···························|················· - | MockPaymentFallback · 0.079 · │ + | MockPaymentFallback · 0.119 · │ ············································|···························|················· - | MockPaymentFallbackExpensive · 0.255 · │ + | MockPaymentFallbackExpensive · 0.295 · │ ············································|···························|················· - | MockPCUPickValidatorSet · 1.206 · │ + | MockPCUPickValidatorSet · 1.246 · │ ············································|···························|················· - | MockPCUSortValidators · 0.976 · │ + | MockPCUSortValidators · 1.016 · │ ············································|···························|················· - | MockPCUValidateDoubleSign · 0.799 · │ + | MockPCUValidateDoubleSign · 0.839 · │ ············································|···························|················· - | MockPCUValidateFastFinality · 1.612 · │ + | MockPCUValidateFastFinality · 1.652 · │ ············································|···························|················· - | MockPrecompile · 4.014 · │ + | MockPrecompile · 4.054 · │ ············································|···························|················· - | MockRoninBridgeManager · 23.962 · │ + | MockRoninBridgeManager · 24.002 · │ ············································|···························|················· - | MockRoninGatewayV2Extended · 20.438 · │ + | MockRoninGatewayV2Extended · 20.478 · │ ············································|···························|················· - | MockRoninValidatorSetExtended · 24.964 · │ + | MockRoninValidatorSetExtended · 25.004 · │ ············································|···························|················· - | MockRoninValidatorSetOverridePrecompile · 24.242 · │ + | MockRoninValidatorSetOverridePrecompile · 24.282 · │ ············································|···························|················· - | MockSlashIndicatorExtended · 17.009 · │ + | MockSlashIndicatorExtended · 17.049 · │ ············································|···························|················· - | MockSorting · 2.990 · │ + | MockSorting · 3.030 · │ ············································|···························|················· - | MockStaking · 4.527 · │ + | MockStaking · 4.567 · │ ············································|···························|················· - | MockTransfer · 0.354 · │ + | MockTransfer · 0.394 · │ ············································|···························|················· - | MockTUint256Slot · 2.625 · │ + | MockTUint256Slot · 2.665 · │ ············································|···························|················· - | MockValidatorContract · 0.128 · │ + | MockValidatorContract · 0.168 · │ ············································|···························|················· - | MockValidatorSet · 8.125 · │ + | MockValidatorSet · 8.165 · │ ············································|···························|················· - | NotifiedMigrator · 0.945 · │ + | NotifiedMigrator · 0.985 · │ ············································|···························|················· - | PauseEnforcer · 4.401 · │ + | PauseEnforcer · 4.441 · │ ············································|···························|················· - | Profile · 4.037 · │ + | Profile · 4.649 · │ ············································|···························|················· - | Proposal · 0.122 · │ + | Proposal · 0.162 · │ ············································|···························|················· - | ProxyAdmin · 1.604 · │ + | ProxyAdmin · 1.644 · │ ············································|···························|················· - | RoninBridgeManager · 23.962 · │ + | RoninBridgeManager · 24.002 · │ ············································|···························|················· - | RoninGatewayV2 · 20.130 · │ + | RoninGatewayV2 · 20.170 · │ ············································|···························|················· - | RoninGovernanceAdmin · 14.431 · │ + | RoninGovernanceAdmin · 14.471 · │ ············································|···························|················· - | RoninTrustedOrganization · 7.631 · │ + | RoninTrustedOrganization · 7.671 · │ ············································|···························|················· - | RoninValidatorSet · 20.350 · │ + | RoninValidatorSet · 20.310 · │ ············································|···························|················· - | RoninValidatorSetTimedMigrator · 2.286 · │ + | RoninValidatorSetTimedMigrator · 2.326 · │ ············································|···························|················· - | SlashIndicator · 13.655 · │ + | SlashIndicator · 13.695 · │ ············································|···························|················· - | Sorting · 0.044 · │ + | Sorting · 0.084 · │ ············································|···························|················· - | Staking · 16.271 · │ + | Staking · 16.311 · │ ············································|···························|················· - | StakingVesting · 3.016 · │ + | StakingVesting · 3.056 · │ ············································|···························|················· - | StorageSlot · 0.044 · │ + | StorageSlot · 0.084 · │ ············································|···························|················· - | Strings · 0.044 · │ + | Strings · 0.084 · │ ············································|···························|················· - | Token · 0.169 · │ + | Token · 0.209 · │ ············································|···························|················· - | Transfer · 0.122 · │ + | Transfer · 0.162 · │ ············································|···························|················· - | TransparentUpgradeableProxy · 1.979 · │ + | TransparentUpgradeableProxy · 2.020 · │ ············································|···························|················· - | TransparentUpgradeableProxyV2 · 2.266 · │ + | TransparentUpgradeableProxyV2 · 2.306 · │ ············································|···························|················· - | VaultForwarder · 3.729 · │ + | VaultForwarder · 3.769 · │ ·-------------------------------------------|---------------------------|----------------· diff --git a/logs/storage_layout.log b/logs/storage_layout.log index 194e27e3c..3a56d3cfa 100644 --- a/logs/storage_layout.log +++ b/logs/storage_layout.log @@ -533,15 +533,15 @@ PauseEnforcer:_initializing (storage_slot: 2) (offset: 1) (type: t_bool) (number PauseEnforcer:target (storage_slot: 2) (offset: 2) (type: t_contract(IPauseTarget)) (numberOfBytes: 20) PauseEnforcer:emergency (storage_slot: 2) (offset: 22) (type: t_bool) (numberOfBytes: 1) Profile:_id2Profile (storage_slot: 0) (offset: 0) (type: t_mapping(t_addresst_struct(CandidateProfile)_storage)) (numberOfBytes: 32) -Profile:_consensus2Id (storage_slot: 1) (offset: 0) (type: t_mapping(t_userDefinedValueType(TConsensus)42965t_address)) (numberOfBytes: 32) +Profile:_consensus2Id (storage_slot: 1) (offset: 0) (type: t_mapping(t_userDefinedValueType(TConsensus)43049t_address)) (numberOfBytes: 32) Profile:__gap (storage_slot: 2) (offset: 0) (type: t_array(t_bytes32)_storage) (numberOfBytes: 1600) Profile:_initialized (storage_slot: 52) (offset: 0) (type: t_uint8) (numberOfBytes: 1) Profile:_initializing (storage_slot: 52) (offset: 1) (type: t_bool) (numberOfBytes: 1) ProfileStorage:_id2Profile (storage_slot: 0) (offset: 0) (type: t_mapping(t_addresst_struct(CandidateProfile)_storage)) (numberOfBytes: 32) -ProfileStorage:_consensus2Id (storage_slot: 1) (offset: 0) (type: t_mapping(t_userDefinedValueType(TConsensus)42965t_address)) (numberOfBytes: 32) +ProfileStorage:_consensus2Id (storage_slot: 1) (offset: 0) (type: t_mapping(t_userDefinedValueType(TConsensus)43049t_address)) (numberOfBytes: 32) ProfileStorage:__gap (storage_slot: 2) (offset: 0) (type: t_array(t_bytes32)_storage) (numberOfBytes: 1600) ProfileXComponents:_id2Profile (storage_slot: 0) (offset: 0) (type: t_mapping(t_addresst_struct(CandidateProfile)_storage)) (numberOfBytes: 32) -ProfileXComponents:_consensus2Id (storage_slot: 1) (offset: 0) (type: t_mapping(t_userDefinedValueType(TConsensus)42965t_address)) (numberOfBytes: 32) +ProfileXComponents:_consensus2Id (storage_slot: 1) (offset: 0) (type: t_mapping(t_userDefinedValueType(TConsensus)43049t_address)) (numberOfBytes: 32) ProfileXComponents:__gap (storage_slot: 2) (offset: 0) (type: t_array(t_bytes32)_storage) (numberOfBytes: 1600) ProxyAdmin:_owner (storage_slot: 0) (offset: 0) (type: t_address) (numberOfBytes: 20) ReentrancyGuard:_status (storage_slot: 0) (offset: 0) (type: t_uint256) (numberOfBytes: 32) diff --git a/src/deploy/proxy/profile-proxy.ts b/src/deploy/proxy/profile-proxy.ts index e94cc5979..4dcaa8180 100644 --- a/src/deploy/proxy/profile-proxy.ts +++ b/src/deploy/proxy/profile-proxy.ts @@ -3,8 +3,9 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { generalRoninConf, roninchainNetworks } from '../../configs/config'; import { verifyAddress } from '../../script/verify-address'; -import { Profile__factory } from '../../types'; import { Address } from 'hardhat-deploy/dist/types'; +import { Network } from '../../utils'; +import { Profile__factory } from '../../types'; const deploy = async ({ getNamedAccounts, deployments }: HardhatRuntimeEnvironment) => { if (!roninchainNetworks.includes(network.name!)) { @@ -25,17 +26,21 @@ const deploy = async ({ getNamedAccounts, deployments }: HardhatRuntimeEnvironme governanceAdmin = GADepl.address; } - const data = new Profile__factory().interface.encodeFunctionData('initialize', [ - generalRoninConf[network.name]!.stakingContract?.address, - generalRoninConf[network.name]!.validatorContract?.address, - ]); + let validatorContractAddress: Address; + if (network.name == Network.Hardhat) { + validatorContractAddress = generalRoninConf[network.name]!.validatorContract?.address!; + } else { + const validatorContractDeployment = await deployments.get('RoninValidatorSetProxy'); + validatorContractAddress = validatorContractDeployment.address; + } + + const data = new Profile__factory().interface.encodeFunctionData('initialize', [validatorContractAddress]); const deployment = await deploy('ProfileProxy', { contract: 'TransparentUpgradeableProxyV2', from: deployer, log: true, - args: [logicContract.address, generalRoninConf[network.name]!.governanceAdmin?.address, data], - nonce, + args: [logicContract.address, governanceAdmin, data], }); verifyAddress(deployment.address, generalRoninConf[network.name].profileContract?.address); }; diff --git a/src/upgrades/REP-003/230925-upgrade-and-init-profile-contract.ts b/src/upgrades/REP-003/230925-upgrade-and-init-profile-contract.ts new file mode 100644 index 000000000..a592adbee --- /dev/null +++ b/src/upgrades/REP-003/230925-upgrade-and-init-profile-contract.ts @@ -0,0 +1,53 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { explorerUrl, proxyInterface } from '../upgradeUtils'; +import { VoteType } from '../../script/proposal'; +import { roninchainNetworks } from '../../configs/config'; +import { network } from 'hardhat'; +import { Profile__factory } from '../../types'; + +const deploy = async ({ getNamedAccounts, deployments, ethers }: HardhatRuntimeEnvironment) => { + if (!roninchainNetworks.includes(network.name!)) { + return; + } + + const { execute } = deployments; + let { governor } = await getNamedAccounts(); // NOTE: Should double check the `governor` account in the `hardhat.config.ts` file + console.log('Governor:', governor); + + const validatorContractAddress = (await deployments.get('RoninValidatorSetProxy')).address; + + // Upgrade Profile Contract + const ProfileProxy = await deployments.get('ProfileProxy'); + const ProfileLogic = await deployments.get('ProfileLogic'); + const ProfileInstr = [ + proxyInterface.encodeFunctionData('upgradeToAndCall', [ + ProfileLogic.address, + new Profile__factory().interface.encodeFunctionData('initialize', [validatorContractAddress]), + ]), + ]; + console.info('ProfileInstr', ProfileInstr); + + // Propose the proposal + const blockNumBefore = await ethers.provider.getBlockNumber(); + const blockBefore = await ethers.provider.getBlock(blockNumBefore); + const timestampBefore = blockBefore.timestamp; + const proposalExpiryTimestamp = timestampBefore + 3600 * 24 * 10; // expired in 10 days + + const tx = await execute( + 'RoninGovernanceAdmin', + { from: governor, log: true }, + 'proposeProposalForCurrentNetwork', + proposalExpiryTimestamp, // expiryTimestamp + [...ProfileInstr.map(() => ProfileProxy.address)], // targets + [...ProfileInstr].map(() => 0), // values + [...ProfileInstr], // datas + [...ProfileInstr].map(() => 1_000_000), // gasAmounts + VoteType.For // ballot type + ); + deployments.log(`${explorerUrl[network.name!]}/tx/${tx.transactionHash}`); +}; + +// yarn hardhat deploy --tags 230925_UpgradeAndInitV1ProfileContractV0_6_3 --network ronin-testnet +deploy.tags = ['230925_UpgradeAndInitV1ProfileContractV0_6_3']; + +export default deploy; diff --git a/test/hardhat_test/helpers/utils.ts b/test/hardhat_test/helpers/utils.ts index 1aac5bf8a..63c4077d9 100644 --- a/test/hardhat_test/helpers/utils.ts +++ b/test/hardhat_test/helpers/utils.ts @@ -72,7 +72,7 @@ export enum ContractType { /* 11 */ BRIDGE_MANAGER, /* 12 */ BRIDGE_SLASH, /* 13 */ BRIDGE_REWARD, - /* 14 */ FAST_FINALTIY_TRACKING, + /* 14 */ FAST_FINALITY_TRACKING, /* 15 */ PROFILE, }