Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Relay Proposal | 20468438 | 192 days ago | IN | 0 ETH | 0.00415999 | ||||
Relay Proposal | 19432315 | 337 days ago | IN | 0 ETH | 0.02726524 | ||||
Relay Proposal | 19259168 | 361 days ago | IN | 0 ETH | 0.01286297 | ||||
Relay Proposal | 19159682 | 375 days ago | IN | 0 ETH | 0.00837817 | ||||
Relay Proposal | 18874394 | 415 days ago | IN | 0 ETH | 0.00662175 | ||||
Relay Global Pro... | 18376136 | 485 days ago | IN | 0 ETH | 0.02674185 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
MainchainBridgeManager
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { CoreGovernance } from "../extensions/sequential-governance/CoreGovernance.sol"; import { GlobalCoreGovernance, GlobalGovernanceRelay } from "../extensions/sequential-governance/governance-relay/GlobalGovernanceRelay.sol"; import { GovernanceRelay } from "../extensions/sequential-governance/governance-relay/GovernanceRelay.sol"; import { ContractType, BridgeManager } from "../extensions/bridge-operator-governance/BridgeManager.sol"; import { Ballot } from "../libraries/Ballot.sol"; import { Proposal } from "../libraries/Proposal.sol"; import { GlobalProposal } from "../libraries/GlobalProposal.sol"; import "../utils/CommonErrors.sol"; contract MainchainBridgeManager is BridgeManager, GovernanceRelay, GlobalGovernanceRelay { uint256 private constant DEFAULT_EXPIRY_DURATION = 1 << 255; constructor( uint256 num, uint256 denom, uint256 roninChainId, address bridgeContract, address[] memory callbackRegisters, address[] memory bridgeOperators, address[] memory governors, uint96[] memory voteWeights, GlobalProposal.TargetOption[] memory targetOptions, address[] memory targets ) payable CoreGovernance(DEFAULT_EXPIRY_DURATION) GlobalCoreGovernance(targetOptions, targets) BridgeManager(num, denom, roninChainId, bridgeContract, callbackRegisters, bridgeOperators, governors, voteWeights) {} /** * @dev See `GovernanceRelay-_relayProposal`. * * Requirements: * - The method caller is governor. */ function relayProposal( Proposal.ProposalDetail calldata proposal, Ballot.VoteType[] calldata supports_, Signature[] calldata signatures ) external onlyGovernor { _relayProposal(proposal, supports_, signatures, DOMAIN_SEPARATOR, msg.sender); } /** * @dev See `GovernanceRelay-_relayGlobalProposal`. * * Requirements: * - The method caller is governor. */ function relayGlobalProposal( GlobalProposal.GlobalProposalDetail calldata globalProposal, Ballot.VoteType[] calldata supports_, Signature[] calldata signatures ) external onlyGovernor { _relayGlobalProposal({ globalProposal: globalProposal, supports_: supports_, signatures: signatures, domainSeparator: DOMAIN_SEPARATOR, creator: msg.sender }); } /** * @dev Internal function to retrieve the minimum vote weight required for governance actions. * @return minimumVoteWeight The minimum vote weight required for governance actions. */ function _getMinimumVoteWeight() internal view override returns (uint256) { return minimumVoteWeight(); } /** * @dev Returns the expiry duration for a new proposal. */ function getProposalExpiryDuration() external view returns (uint256) { return _getProposalExpiryDuration(); } /** * @dev Internal function to retrieve the total weights of all governors. * @return totalWeights The total weights of all governors combined. */ function _getTotalWeight() internal view override returns (uint256) { return getTotalWeight(); } /** * @dev Internal function to calculate the sum of weights for a given array of governors. * @param governors An array containing the addresses of governors to calculate the sum of weights. * @return sumWeights The sum of weights for the provided governors. */ function _sumWeight(address[] memory governors) internal view override returns (uint256) { return _sumGovernorsWeight(governors); } /** * @dev Internal function to retrieve the chain type of the contract. * @return chainType The chain type, indicating the type of the chain the contract operates on (e.g., Mainchain). */ function _getChainType() internal pure override returns (ChainType) { return ChainType.Mainchain; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.0; import "../Proxy.sol"; import "./ERC1967Upgrade.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy, ERC1967Upgrade { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. * * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded * function call, and allows initializing the storage of the proxy like a Solidity constructor. */ constructor(address _logic, bytes memory _data) payable { _upgradeToAndCall(_logic, _data, false); } /** * @dev Returns the current implementation address. */ function _implementation() internal view virtual override returns (address impl) { return ERC1967Upgrade._getImplementation(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967Upgrade { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overridden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol) pragma solidity ^0.8.0; import "../ERC1967/ERC1967Proxy.sol"; /** * @dev This contract implements a proxy that is upgradeable by an admin. * * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector * clashing], which can potentially be used in an attack, this contract uses the * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two * things that go hand in hand: * * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if * that call matches one of the admin functions exposed by the proxy itself. * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the * implementation. If the admin tries to call a function on the implementation it will fail with an error that says * "admin cannot fallback to proxy target". * * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due * to sudden errors when trying to call a function from the proxy implementation. * * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. */ contract TransparentUpgradeableProxy is ERC1967Proxy { /** * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. */ constructor( address _logic, address admin_, bytes memory _data ) payable ERC1967Proxy(_logic, _data) { _changeAdmin(admin_); } /** * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. */ modifier ifAdmin() { if (msg.sender == _getAdmin()) { _; } else { _fallback(); } } /** * @dev Returns the current admin. * * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function admin() external ifAdmin returns (address admin_) { admin_ = _getAdmin(); } /** * @dev Returns the current implementation. * * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function implementation() external ifAdmin returns (address implementation_) { implementation_ = _implementation(); } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. * * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. */ function changeAdmin(address newAdmin) external virtual ifAdmin { _changeAdmin(newAdmin); } /** * @dev Upgrade the implementation of the proxy. * * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. */ function upgradeTo(address newImplementation) external ifAdmin { _upgradeToAndCall(newImplementation, bytes(""), false); } /** * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the * proxied contract. * * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. */ function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { _upgradeToAndCall(newImplementation, data, true); } /** * @dev Returns the current admin. */ function _admin() internal view virtual returns (address) { return _getAdmin(); } /** * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. */ function _beforeFallback() internal virtual override { require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); super._beforeFallback(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * 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. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract TransparentUpgradeableProxyV2 is TransparentUpgradeableProxy { constructor( address _logic, address admin_, bytes memory _data ) payable TransparentUpgradeableProxy(_logic, admin_, _data) {} /** * @dev Calls a function from the current implementation as specified by `_data`, which should be an encoded function call. * * Requirements: * - Only the admin can call this function. * * Note: The proxy admin is not allowed to interact with the proxy logic through the fallback function to avoid * triggering some unexpected logic. This is to allow the administrator to explicitly call the proxy, please consider * reviewing the encoded data `_data` and the method which is called before using this. * */ function functionDelegateCall(bytes memory _data) public payable ifAdmin { address _addr = _implementation(); assembly { let _result := delegatecall(gas(), _addr, add(_data, 32), mload(_data), 0, 0) returndatacopy(0, 0, returndatasize()) switch _result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IBridgeManagerCallback, EnumerableSet, BridgeManagerCallbackRegister } from "./BridgeManagerCallbackRegister.sol"; import { IHasContracts, HasContracts } from "../../extensions/collections/HasContracts.sol"; import { IQuorum } from "../../interfaces/IQuorum.sol"; import { IBridgeManager } from "../../interfaces/bridge/IBridgeManager.sol"; import { AddressArrayUtils } from "../../libraries/AddressArrayUtils.sol"; import { ContractType } from "../../utils/ContractType.sol"; import { RoleAccess } from "../../utils/RoleAccess.sol"; import { TUint256Slot } from "../../types/Types.sol"; import "../../utils/CommonErrors.sol"; abstract contract BridgeManager is IQuorum, IBridgeManager, BridgeManagerCallbackRegister, HasContracts { using AddressArrayUtils for address[]; using EnumerableSet for EnumerableSet.AddressSet; /// @dev value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.governorToBridgeOperatorInfo.slot") - 1 bytes32 private constant GOVERNOR_TO_BRIDGE_OPERATOR_INFO_SLOT = 0x88547008e60f5748911f2e59feb3093b7e4c2e87b2dd69d61f112fcc932de8e3; /// @dev value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.govenorOf.slot") - 1 bytes32 private constant GOVENOR_OF_SLOT = 0x8400683eb2cb350596d73644c0c89fe45f108600003457374f4ab3e87b4f3aa3; /// @dev value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.governors.slot") - 1 bytes32 private constant GOVERNOR_SET_SLOT = 0x546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c; /// @dev value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.bridgeOperators.slot") - 1 bytes32 private constant BRIDGE_OPERATOR_SET_SLOT = 0xd38c234075fde25875da8a6b7e36b58b86681d483271a99eeeee1d78e258a24d; /** * @dev The numerator value used for calculations in the contract. * @notice value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.numerator.slot") - 1 */ TUint256Slot internal constant NUMERATOR_SLOT = TUint256Slot.wrap(0xc55405a488814eaa0e2a685a0131142785b8d033d311c8c8244e34a7c12ca40f); /** * @dev The denominator value used for calculations in the contract. * @notice value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.denominator.slot") - 1 */ TUint256Slot internal constant DENOMINATOR_SLOT = TUint256Slot.wrap(0xac1ff16a4f04f2a37a9ba5252a69baa100b460e517d1f8019c054a5ad698f9ff); /** * @dev The nonce value used for tracking nonces in the contract. * @notice value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.nonce.slot") - 1 */ TUint256Slot internal constant NONCE_SLOT = TUint256Slot.wrap(0x92872d32822c9d44b36a2537d3e0d4c46fc4de1ce154ccfaed560a8a58445f1d); /** * @dev The total weight value used for storing the cumulative weight in the contract. * @notice value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.totalWeights.slot") - 1 */ TUint256Slot internal constant TOTAL_WEIGHTS_SLOT = TUint256Slot.wrap(0x6924fe71b0c8b61aea02ca498b5f53b29bd95726278b1fe4eb791bb24a42644c); /** * @inheritdoc IBridgeManager */ bytes32 public immutable DOMAIN_SEPARATOR; modifier onlyGovernor() virtual { _requireGovernor(msg.sender); _; } constructor( uint256 num, uint256 denom, uint256 roninChainId, address bridgeContract, address[] memory callbackRegisters, address[] memory bridgeOperators, address[] memory governors, uint96[] memory voteWeights ) payable BridgeManagerCallbackRegister(callbackRegisters) { NONCE_SLOT.store(1); _setThreshold(num, denom); _setContract(ContractType.BRIDGE, bridgeContract); DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,bytes32 salt)"), keccak256("BridgeAdmin"), // name hash keccak256("2"), // version hash keccak256(abi.encode("BRIDGE_ADMIN", roninChainId)) // salt ) ); _addBridgeOperators(voteWeights, governors, bridgeOperators); } /** * @inheritdoc IBridgeManager */ function addBridgeOperators( uint96[] calldata voteWeights, address[] calldata governors, address[] calldata bridgeOperators ) external onlySelfCall returns (bool[] memory addeds) { addeds = _addBridgeOperators(voteWeights, governors, bridgeOperators); } /** * @inheritdoc IBridgeManager */ function removeBridgeOperators( address[] calldata bridgeOperators ) external onlySelfCall returns (bool[] memory removeds) { removeds = _removeBridgeOperators(bridgeOperators); } /** * @inheritdoc IBridgeManager * @notice This method checks authorization by querying the corresponding operator of the msg.sender and then * attempts to remove it from the `_bridgeOperatorSet` for gas optimization. In case we allow a governor can leave * their operator address blank null `address(0)`, consider add authorization check. */ function updateBridgeOperator(address newBridgeOperator) external onlyGovernor { _requireNonZeroAddress(newBridgeOperator); // Queries the previous bridge operator mapping(address => BridgeOperatorInfo) storage _gorvernorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo(); address currentBridgeOperator = _gorvernorToBridgeOperatorInfo[msg.sender].addr; if (currentBridgeOperator == newBridgeOperator) { revert ErrBridgeOperatorAlreadyExisted(newBridgeOperator); } // Tries replace the bridge operator EnumerableSet.AddressSet storage _bridgeOperatorSet = _getBridgeOperatorSet(); bool updated = _bridgeOperatorSet.remove(currentBridgeOperator) && _bridgeOperatorSet.add(newBridgeOperator); if (!updated) revert ErrBridgeOperatorUpdateFailed(newBridgeOperator); mapping(address => address) storage _governorOf = _getGovernorOf(); delete _governorOf[currentBridgeOperator]; _governorOf[newBridgeOperator] = msg.sender; _gorvernorToBridgeOperatorInfo[msg.sender].addr = newBridgeOperator; _notifyRegisters( IBridgeManagerCallback.onBridgeOperatorUpdated.selector, abi.encode(currentBridgeOperator, newBridgeOperator) ); emit BridgeOperatorUpdated(msg.sender, currentBridgeOperator, newBridgeOperator); } /** * @inheritdoc IHasContracts */ function setContract(ContractType contractType, address addr) external override onlySelfCall { _requireHasCode(addr); _setContract(contractType, addr); } /** * @inheritdoc IQuorum */ function setThreshold( uint256 numerator, uint256 denominator ) external override onlySelfCall returns (uint256, uint256) { return _setThreshold(numerator, denominator); } /** * @inheritdoc IBridgeManager */ function getTotalWeight() public view returns (uint256) { return TOTAL_WEIGHTS_SLOT.load(); } /** * @inheritdoc IBridgeManager */ function getGovernorWeights(address[] calldata governors) external view returns (uint96[] memory weights) { weights = _getGovernorWeights(governors); } /** * @inheritdoc IBridgeManager */ function getGovernorWeight(address governor) external view returns (uint96 weight) { weight = _getGovernorWeight(governor); } /** * @inheritdoc IBridgeManager */ function sumGovernorsWeight( address[] calldata governors ) external view nonDuplicate(governors) returns (uint256 sum) { sum = _sumGovernorsWeight(governors); } /** * @inheritdoc IBridgeManager */ function totalBridgeOperator() external view returns (uint256) { return _getBridgeOperatorSet().length(); } /** * @inheritdoc IBridgeManager */ function isBridgeOperator(address addr) external view returns (bool) { return _getBridgeOperatorSet().contains(addr); } /** * @inheritdoc IBridgeManager */ function getBridgeOperators() external view returns (address[] memory) { return _getBridgeOperators(); } /** * @inheritdoc IBridgeManager */ function getGovernors() external view returns (address[] memory) { return _getGovernors(); } /** * @inheritdoc IBridgeManager */ function getBridgeOperatorOf(address[] memory governors) public view returns (address[] memory bridgeOperators) { uint256 length = governors.length; bridgeOperators = new address[](length); mapping(address => BridgeOperatorInfo) storage _gorvernorToBridgeOperator = _getGovernorToBridgeOperatorInfo(); for (uint256 i; i < length; ) { bridgeOperators[i] = _gorvernorToBridgeOperator[governors[i]].addr; unchecked { ++i; } } } /** * @inheritdoc IBridgeManager */ function getGovernorsOf(address[] calldata bridgeOperators) external view returns (address[] memory governors) { uint256 length = bridgeOperators.length; governors = new address[](length); mapping(address => address) storage _governorOf = _getGovernorOf(); for (uint256 i; i < length; ) { governors[i] = _governorOf[bridgeOperators[i]]; unchecked { ++i; } } } /** * @inheritdoc IBridgeManager */ function getFullBridgeOperatorInfos() external view returns (address[] memory governors, address[] memory bridgeOperators, uint96[] memory weights) { governors = _getGovernors(); bridgeOperators = getBridgeOperatorOf(governors); weights = _getGovernorWeights(governors); } /** * @inheritdoc IBridgeManager */ function getBridgeOperatorWeight(address bridgeOperator) external view returns (uint96 weight) { mapping(address => address) storage _governorOf = _getGovernorOf(); mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo(); weight = _governorToBridgeOperatorInfo[_governorOf[bridgeOperator]].voteWeight; } /** * @inheritdoc IQuorum */ function minimumVoteWeight() public view virtual returns (uint256) { return (NUMERATOR_SLOT.mul(TOTAL_WEIGHTS_SLOT.load()) + DENOMINATOR_SLOT.load() - 1) / DENOMINATOR_SLOT.load(); } /** * @inheritdoc IQuorum */ function getThreshold() external view virtual returns (uint256 num_, uint256 denom_) { return (NUMERATOR_SLOT.load(), DENOMINATOR_SLOT.load()); } /** * @inheritdoc IQuorum */ function checkThreshold(uint256 _voteWeight) external view virtual returns (bool) { return _voteWeight * DENOMINATOR_SLOT.load() >= NUMERATOR_SLOT.mul(TOTAL_WEIGHTS_SLOT.load()); } /** * @dev Internal function to add bridge operators. * * This function adds the specified `bridgeOperators` to the bridge operator set and establishes the associated mappings. * * Requirements: * - The caller must have the necessary permission to add bridge operators. * - The lengths of `voteWeights`, `governors`, and `bridgeOperators` arrays must be equal. * * @param voteWeights An array of uint256 values representing the vote weights for each bridge operator. * @param governors An array of addresses representing the governors for each bridge operator. * @return addeds An array of boolean values indicating whether each bridge operator was successfully added. */ function _addBridgeOperators( uint96[] memory voteWeights, address[] memory governors, address[] memory bridgeOperators ) internal nonDuplicate(governors.extend(bridgeOperators)) returns (bool[] memory addeds) { uint256 length = bridgeOperators.length; if (!(length == voteWeights.length && length == governors.length)) revert ErrLengthMismatch(msg.sig); addeds = new bool[](length); // simply skip add operations if inputs are empty. if (length == 0) return addeds; EnumerableSet.AddressSet storage _governorSet = _getGovernorsSet(); mapping(address => address) storage _governorOf = _getGovernorOf(); EnumerableSet.AddressSet storage _bridgeOperatorSet = _getBridgeOperatorSet(); mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo(); address governor; address bridgeOperator; uint256 accumulatedWeight; BridgeOperatorInfo memory bridgeOperatorInfo; for (uint256 i; i < length; ) { governor = governors[i]; bridgeOperator = bridgeOperators[i]; _requireNonZeroAddress(governor); _requireNonZeroAddress(bridgeOperator); if (voteWeights[i] == 0) revert ErrInvalidVoteWeight(msg.sig); addeds[i] = !(_governorSet.contains(governor) || _governorSet.contains(bridgeOperator) || _bridgeOperatorSet.contains(governor) || _bridgeOperatorSet.contains(bridgeOperator)); if (addeds[i]) { _governorSet.add(governor); _bridgeOperatorSet.add(bridgeOperator); _governorOf[bridgeOperator] = governor; bridgeOperatorInfo.addr = bridgeOperator; accumulatedWeight += bridgeOperatorInfo.voteWeight = voteWeights[i]; _governorToBridgeOperatorInfo[governor] = bridgeOperatorInfo; } unchecked { ++i; } } TOTAL_WEIGHTS_SLOT.addAssign(accumulatedWeight); _notifyRegisters(IBridgeManagerCallback.onBridgeOperatorsAdded.selector, abi.encode(bridgeOperators, addeds)); emit BridgeOperatorsAdded(addeds, voteWeights, governors, bridgeOperators); } /** * @dev Internal function to remove bridge operators. * * This function removes the specified `bridgeOperators` from the bridge operator set and related mappings. * * Requirements: * - The caller must have the necessary permission to remove bridge operators. * * @param bridgeOperators An array of addresses representing the bridge operators to be removed. * @return removeds An array of boolean values indicating whether each bridge operator was successfully removed. */ function _removeBridgeOperators( address[] memory bridgeOperators ) internal nonDuplicate(bridgeOperators) returns (bool[] memory removeds) { uint256 length = bridgeOperators.length; removeds = new bool[](length); // simply skip remove operations if inputs are empty. if (length == 0) return removeds; mapping(address => address) storage _governorOf = _getGovernorOf(); EnumerableSet.AddressSet storage _governorSet = _getGovernorsSet(); EnumerableSet.AddressSet storage _bridgeOperatorSet = _getBridgeOperatorSet(); mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo(); address governor; address bridgeOperator; uint256 accumulatedWeight; BridgeOperatorInfo memory bridgeOperatorInfo; for (uint256 i; i < length; ) { bridgeOperator = bridgeOperators[i]; governor = _governorOf[bridgeOperator]; _requireNonZeroAddress(governor); _requireNonZeroAddress(bridgeOperator); bridgeOperatorInfo = _governorToBridgeOperatorInfo[governor]; if (bridgeOperatorInfo.addr != bridgeOperator) revert ErrInvalidArguments(msg.sig); removeds[i] = _bridgeOperatorSet.contains(bridgeOperator) && _governorSet.contains(governor); if (removeds[i]) { _governorSet.remove(governor); _bridgeOperatorSet.remove(bridgeOperator); delete _governorOf[bridgeOperator]; delete _governorToBridgeOperatorInfo[governor]; accumulatedWeight += bridgeOperatorInfo.voteWeight; } unchecked { ++i; } } TOTAL_WEIGHTS_SLOT.subAssign(accumulatedWeight); _notifyRegisters(IBridgeManagerCallback.onBridgeOperatorsRemoved.selector, abi.encode(bridgeOperators, removeds)); emit BridgeOperatorsRemoved(removeds, bridgeOperators); } /** * @dev Sets threshold and returns the old one. * * Emits the `ThresholdUpdated` event. * */ function _setThreshold( uint256 numerator, uint256 denominator ) internal virtual returns (uint256 previousNum, uint256 previousDenom) { if (numerator > denominator) revert ErrInvalidThreshold(msg.sig); previousNum = NUMERATOR_SLOT.load(); previousDenom = DENOMINATOR_SLOT.load(); NUMERATOR_SLOT.store(numerator); DENOMINATOR_SLOT.store(denominator); emit ThresholdUpdated(NONCE_SLOT.postIncrement(), numerator, denominator, previousNum, previousDenom); } /** * @dev Internal function to get all bridge operators. * @return bridgeOperators An array containing all the registered bridge operator addresses. */ function _getBridgeOperators() internal view returns (address[] memory) { return _getBridgeOperatorSet().values(); } /** * @dev Internal function to get all governors. * @return governors An array containing all the registered governor addresses. */ function _getGovernors() internal view returns (address[] memory) { return _getGovernorsSet().values(); } /** * @dev Internal function to get the vote weights of a given array of governors. * @param governors An array containing the addresses of governors. * @return weights An array containing the vote weights of the corresponding governors. */ function _getGovernorWeights(address[] memory governors) internal view returns (uint96[] memory weights) { uint256 length = governors.length; weights = new uint96[](length); mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo(); for (uint256 i; i < length; ) { weights[i] = _governorToBridgeOperatorInfo[governors[i]].voteWeight; unchecked { ++i; } } } /** * @dev Internal function to calculate the sum of vote weights for a given array of governors. * @param governors An array containing the addresses of governors to calculate the sum of vote weights. * @return sum The total sum of vote weights for the provided governors. * @notice The input array `governors` must contain unique addresses to avoid duplicate calculations. */ function _sumGovernorsWeight(address[] memory governors) internal view nonDuplicate(governors) returns (uint256 sum) { mapping(address => BridgeOperatorInfo) storage _governorToBridgeOperatorInfo = _getGovernorToBridgeOperatorInfo(); for (uint256 i; i < governors.length; ) { sum += _governorToBridgeOperatorInfo[governors[i]].voteWeight; unchecked { ++i; } } } /** * @dev Internal function to require that the caller has governor role access. * @param addr The address to check for governor role access. * @dev If the address does not have governor role access (vote weight is zero), a revert with the corresponding error message is triggered. */ function _requireGovernor(address addr) internal view { if (_getGovernorWeight(addr) == 0) { revert ErrUnauthorized(msg.sig, RoleAccess.GOVERNOR); } } /** * @dev Internal function to retrieve the vote weight of a specific governor. * @param governor The address of the governor to get the vote weight for. * @return voteWeight The vote weight of the specified governor. */ function _getGovernorWeight(address governor) internal view returns (uint96) { return _getGovernorToBridgeOperatorInfo()[governor].voteWeight; } /** * @dev Internal function to access the address set of bridge operators. * @return bridgeOperators the storage address set. */ function _getBridgeOperatorSet() internal pure returns (EnumerableSet.AddressSet storage bridgeOperators) { assembly ("memory-safe") { bridgeOperators.slot := BRIDGE_OPERATOR_SET_SLOT } } /** * @dev Internal function to access the address set of bridge operators. * @return governors the storage address set. */ function _getGovernorsSet() internal pure returns (EnumerableSet.AddressSet storage governors) { assembly ("memory-safe") { governors.slot := GOVERNOR_SET_SLOT } } /** * @dev Internal function to access the mapping from governor => BridgeOperatorInfo. * @return governorToBridgeOperatorInfo the mapping from governor => BridgeOperatorInfo. */ function _getGovernorToBridgeOperatorInfo() internal pure returns (mapping(address => BridgeOperatorInfo) storage governorToBridgeOperatorInfo) { assembly ("memory-safe") { governorToBridgeOperatorInfo.slot := GOVERNOR_TO_BRIDGE_OPERATOR_INFO_SLOT } } /** * @dev Internal function to access the mapping from bridge operator => governor. * @return governorOf the mapping from bridge operator => governor. */ function _getGovernorOf() internal pure returns (mapping(address => address) storage governorOf) { assembly ("memory-safe") { governorOf.slot := GOVENOR_OF_SLOT } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { IBridgeManagerCallbackRegister } from "../../interfaces/bridge/IBridgeManagerCallbackRegister.sol"; import { IBridgeManagerCallback } from "../../interfaces/bridge/IBridgeManagerCallback.sol"; import { TransparentUpgradeableProxyV2, IdentityGuard } from "../../utils/IdentityGuard.sol"; /** * @title BridgeManagerCallbackRegister * @dev A contract that manages callback registrations and execution for a bridge. */ abstract contract BridgeManagerCallbackRegister is IdentityGuard, IBridgeManagerCallbackRegister { using EnumerableSet for EnumerableSet.AddressSet; /** * @dev Storage slot for the address set of callback registers. * @dev Value is equal to keccak256("@ronin.dpos.gateway.BridgeAdmin.callbackRegisters.slot") - 1. */ bytes32 private constant CALLBACK_REGISTERS_SLOT = 0x5da136eb38f8d8e354915fc8a767c0dc81d49de5fb65d5477122a82ddd976240; constructor(address[] memory callbackRegisters) payable { _registerCallbacks(callbackRegisters); } /** * @inheritdoc IBridgeManagerCallbackRegister */ function registerCallbacks(address[] calldata registers) external onlySelfCall returns (bool[] memory registereds) { registereds = _registerCallbacks(registers); } /** * @inheritdoc IBridgeManagerCallbackRegister */ function unregisterCallbacks( address[] calldata registers ) external onlySelfCall returns (bool[] memory unregistereds) { unregistereds = _unregisterCallbacks(registers); } /** * @inheritdoc IBridgeManagerCallbackRegister */ function getCallbackRegisters() external view returns (address[] memory registers) { registers = _getCallbackRegisters().values(); } /** * @dev Internal function to register multiple callbacks with the bridge. * @param registers The array of callback addresses to register. * @return registereds An array indicating the success status of each registration. */ function _registerCallbacks( address[] memory registers ) internal nonDuplicate(registers) returns (bool[] memory registereds) { uint256 length = registers.length; registereds = new bool[](length); if (length == 0) return registereds; EnumerableSet.AddressSet storage _callbackRegisters = _getCallbackRegisters(); address register; bytes4 callbackInterface = type(IBridgeManagerCallback).interfaceId; for (uint256 i; i < length; ) { register = registers[i]; _requireHasCode(register); _requireSupportsInterface(register, callbackInterface); registereds[i] = _callbackRegisters.add(register); unchecked { ++i; } } } /** * @dev Internal function to unregister multiple callbacks from the bridge. * @param registers The array of callback addresses to unregister. * @return unregistereds An array indicating the success status of each unregistration. */ function _unregisterCallbacks( address[] memory registers ) internal nonDuplicate(registers) returns (bool[] memory unregistereds) { uint256 length = registers.length; unregistereds = new bool[](length); EnumerableSet.AddressSet storage _callbackRegisters = _getCallbackRegisters(); for (uint256 i; i < length; ) { unregistereds[i] = _callbackRegisters.remove(registers[i]); unchecked { ++i; } } } /** * @dev Internal function to notify all registered callbacks with the provided function signature and data. * @param callbackFnSig The function signature of the callback method. * @param inputs The data to pass to the callback method. */ function _notifyRegisters(bytes4 callbackFnSig, bytes memory inputs) internal { address[] memory registers = _getCallbackRegisters().values(); uint256 length = registers.length; if (length == 0) return; bool[] memory successes = new bool[](length); bytes[] memory returnDatas = new bytes[](length); bytes memory callData = abi.encodePacked(callbackFnSig, inputs); bytes memory proxyCallData = abi.encodeCall(TransparentUpgradeableProxyV2.functionDelegateCall, (callData)); for (uint256 i; i < length; ) { (successes[i], returnDatas[i]) = registers[i].call(callData); if (!successes[i]) { (successes[i], returnDatas[i]) = registers[i].call(proxyCallData); } unchecked { ++i; } } emit Notified(callData, registers, successes, returnDatas); } /** * @dev Internal function to retrieve the address set of callback registers. * @return callbackRegisters The storage reference to the callback registers. */ function _getCallbackRegisters() internal pure returns (EnumerableSet.AddressSet storage callbackRegisters) { assembly ("memory-safe") { callbackRegisters.slot := CALLBACK_REGISTERS_SLOT } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { HasProxyAdmin } from "./HasProxyAdmin.sol"; import "../../interfaces/collections/IHasContracts.sol"; import { IdentityGuard } from "../../utils/IdentityGuard.sol"; import { ErrUnexpectedInternalCall } from "../../utils/CommonErrors.sol"; /** * @title HasContracts * @dev A contract that provides functionality to manage multiple contracts with different roles. */ abstract contract HasContracts is HasProxyAdmin, IHasContracts, IdentityGuard { /// @dev value is equal to keccak256("@ronin.dpos.collections.HasContracts.slot") - 1 bytes32 private constant _STORAGE_SLOT = 0xdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb; /** * @dev Modifier to restrict access to functions only to contracts with a specific role. * @param contractType The contract type that allowed to call */ modifier onlyContract(ContractType contractType) virtual { _requireContract(contractType); _; } /** * @inheritdoc IHasContracts */ function setContract(ContractType contractType, address addr) external virtual onlyAdmin { _requireHasCode(addr); _setContract(contractType, addr); } /** * @inheritdoc IHasContracts */ function getContract(ContractType contractType) public view returns (address contract_) { contract_ = _getContractMap()[uint8(contractType)]; if (contract_ == address(0)) revert ErrContractTypeNotFound(contractType); } /** * @dev Internal function to set the address of a contract with a specific role. * @param contractType The contract type of the contract to set. * @param addr The address of the contract to set. */ function _setContract(ContractType contractType, address addr) internal virtual { _getContractMap()[uint8(contractType)] = addr; emit ContractUpdated(contractType, addr); } /** * @dev Internal function to access the mapping of contract addresses with roles. * @return contracts_ The mapping of contract addresses with roles. */ function _getContractMap() private pure returns (mapping(uint8 => address) storage contracts_) { assembly { contracts_.slot := _STORAGE_SLOT } } /** * @dev Internal function to check if the calling contract has a specific role. * @param contractType The contract type that the calling contract must have. * @dev Throws an error if the calling contract does not have the specified role. */ function _requireContract(ContractType contractType) private view { if (msg.sender != getContract(contractType)) { revert ErrUnexpectedInternalCall(msg.sig, contractType, msg.sender); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/StorageSlot.sol"; import "../../utils/CommonErrors.sol"; abstract contract HasProxyAdmin { // bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)); bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; modifier onlyAdmin() { _requireAdmin(); _; } /** * @dev Returns proxy admin. */ function _getAdmin() internal view virtual returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } function _requireAdmin() internal view { if (msg.sender != _getAdmin()) revert ErrUnauthorized(msg.sig, RoleAccess.ADMIN); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../libraries/Proposal.sol"; import "../../libraries/GlobalProposal.sol"; import "../../utils/CommonErrors.sol"; import "../../libraries/Ballot.sol"; import "../../interfaces/consumers/ChainTypeConsumer.sol"; import "../../interfaces/consumers/SignatureConsumer.sol"; import "../../interfaces/consumers/VoteStatusConsumer.sol"; abstract contract CoreGovernance is SignatureConsumer, VoteStatusConsumer, ChainTypeConsumer { using Proposal for Proposal.ProposalDetail; /** * @dev Error thrown when attempting to interact with a finalized vote. */ error ErrVoteIsFinalized(); /** * @dev Error thrown when the current proposal is not completed. */ error ErrCurrentProposalIsNotCompleted(); struct ProposalVote { VoteStatus status; bytes32 hash; uint256 againstVoteWeight; // Total weight of against votes uint256 forVoteWeight; // Total weight of for votes address[] forVoteds; // Array of addresses voting for address[] againstVoteds; // Array of addresses voting against uint256 expiryTimestamp; mapping(address => Signature) sig; mapping(address => bool) voted; } /// @dev Emitted when a proposal is created event ProposalCreated( uint256 indexed chainId, uint256 indexed round, bytes32 indexed proposalHash, Proposal.ProposalDetail proposal, address creator ); /// @dev Emitted when the proposal is voted event ProposalVoted(bytes32 indexed proposalHash, address indexed voter, Ballot.VoteType support, uint256 weight); /// @dev Emitted when the proposal is approved event ProposalApproved(bytes32 indexed proposalHash); /// @dev Emitted when the vote is reject event ProposalRejected(bytes32 indexed proposalHash); /// @dev Emitted when the vote is expired event ProposalExpired(bytes32 indexed proposalHash); /// @dev Emitted when the proposal is executed event ProposalExecuted(bytes32 indexed proposalHash, bool[] successCalls, bytes[] returnDatas); /// @dev Emitted when the proposal expiry duration is changed. event ProposalExpiryDurationChanged(uint256 indexed duration); /// @dev Mapping from chain id => vote round /// @notice chain id = 0 for global proposal mapping(uint256 => uint256) public round; /// @dev Mapping from chain id => vote round => proposal vote mapping(uint256 => mapping(uint256 => ProposalVote)) public vote; uint256 internal _proposalExpiryDuration; constructor(uint256 _expiryDuration) { _setProposalExpiryDuration(_expiryDuration); } /** * @dev Creates new voting round by calculating the `_round` number of chain `_chainId`. * Increases the `_round` number if the previous one is not expired. Delete the previous proposal * if it is expired and not increase the `_round`. */ function _createVotingRound(uint256 _chainId) internal returns (uint256 _round) { _round = round[_chainId]; // Skip checking for the first ever round if (_round == 0) { _round = round[_chainId] = 1; } else { ProposalVote storage _latestProposalVote = vote[_chainId][_round]; bool _isExpired = _tryDeleteExpiredVotingRound(_latestProposalVote); // Skip increasing round number if the latest round is expired, allow the vote to be overridden if (!_isExpired) { if (_latestProposalVote.status == VoteStatus.Pending) revert ErrCurrentProposalIsNotCompleted(); unchecked { _round = ++round[_chainId]; } } } } /** * @dev Saves new round voting for the proposal `_proposalHash` of chain `_chainId`. */ function _saveVotingRound(ProposalVote storage _vote, bytes32 _proposalHash, uint256 _expiryTimestamp) internal { _vote.hash = _proposalHash; _vote.expiryTimestamp = _expiryTimestamp; } /** * @dev Proposes for a new proposal. * * Requirements: * - The chain id is not equal to 0. * * Emits the `ProposalCreated` event. * */ function _proposeProposal( uint256 chainId, uint256 expiryTimestamp, address[] memory targets, uint256[] memory values, bytes[] memory calldatas, uint256[] memory gasAmounts, address creator ) internal virtual returns (Proposal.ProposalDetail memory proposal) { if (chainId == 0) revert ErrInvalidChainId(msg.sig, 0, block.chainid); uint256 round_ = _createVotingRound(chainId); proposal = Proposal.ProposalDetail(round_, chainId, expiryTimestamp, targets, values, calldatas, gasAmounts); proposal.validate(_proposalExpiryDuration); bytes32 proposalHash = proposal.hash(); _saveVotingRound(vote[chainId][round_], proposalHash, expiryTimestamp); emit ProposalCreated(chainId, round_, proposalHash, proposal, creator); } /** * @dev Proposes proposal struct. * * Requirements: * - The chain id is not equal to 0. * - The proposal nonce is equal to the new round. * * Emits the `ProposalCreated` event. * */ function _proposeProposalStruct( Proposal.ProposalDetail memory proposal, address creator ) internal virtual returns (uint256 round_) { uint256 chainId = proposal.chainId; if (chainId == 0) revert ErrInvalidChainId(msg.sig, 0, block.chainid); proposal.validate(_proposalExpiryDuration); bytes32 proposalHash = proposal.hash(); round_ = _createVotingRound(chainId); _saveVotingRound(vote[chainId][round_], proposalHash, proposal.expiryTimestamp); if (round_ != proposal.nonce) revert ErrInvalidProposalNonce(msg.sig); emit ProposalCreated(chainId, round_, proposalHash, proposal, creator); } /** * @dev Casts vote for the proposal with data and returns whether the voting is done. * * Requirements: * - The proposal nonce is equal to the round. * - The vote is not finalized. * - The voter has not voted for the round. * * Emits the `ProposalVoted` event. Emits the `ProposalApproved`, `ProposalExecuted` or `ProposalRejected` once the * proposal is approved, executed or rejected. * */ function _castVote( Proposal.ProposalDetail memory proposal, Ballot.VoteType support, uint256 minimumForVoteWeight, uint256 minimumAgainstVoteWeight, address voter, Signature memory signature, uint256 voterWeight ) internal virtual returns (bool done) { uint256 chainId = proposal.chainId; uint256 round_ = proposal.nonce; ProposalVote storage _vote = vote[chainId][round_]; if (_tryDeleteExpiredVotingRound(_vote)) { return true; } if (round[proposal.chainId] != round_) revert ErrInvalidProposalNonce(msg.sig); if (_vote.status != VoteStatus.Pending) revert ErrVoteIsFinalized(); if (_voted(_vote, voter)) revert ErrAlreadyVoted(voter); _vote.voted[voter] = true; // Stores the signature if it is not empty if (signature.r > 0 || signature.s > 0 || signature.v > 0) { _vote.sig[voter] = signature; } emit ProposalVoted(_vote.hash, voter, support, voterWeight); uint256 _forVoteWeight; uint256 _againstVoteWeight; if (support == Ballot.VoteType.For) { _vote.forVoteds.push(voter); _forVoteWeight = _vote.forVoteWeight += voterWeight; } else if (support == Ballot.VoteType.Against) { _vote.againstVoteds.push(voter); _againstVoteWeight = _vote.againstVoteWeight += voterWeight; } else revert ErrUnsupportedVoteType(msg.sig); if (_forVoteWeight >= minimumForVoteWeight) { done = true; _vote.status = VoteStatus.Approved; emit ProposalApproved(_vote.hash); _tryExecute(_vote, proposal); } else if (_againstVoteWeight >= minimumAgainstVoteWeight) { done = true; _vote.status = VoteStatus.Rejected; emit ProposalRejected(_vote.hash); } } /** * @dev When the contract is on Ronin chain, checks whether the proposal is expired and delete it if is expired. * * Emits the event `ProposalExpired` if the vote is expired. * * Note: This function assumes the vote `_proposalVote` is already created, consider verifying the vote's existence * before or it will emit an unexpected event of `ProposalExpired`. */ function _tryDeleteExpiredVotingRound(ProposalVote storage proposalVote) internal returns (bool isExpired) { isExpired = _getChainType() == ChainType.RoninChain && proposalVote.status == VoteStatus.Pending && proposalVote.expiryTimestamp <= block.timestamp; if (isExpired) { emit ProposalExpired(proposalVote.hash); for (uint256 _i; _i < proposalVote.forVoteds.length; ) { delete proposalVote.voted[proposalVote.forVoteds[_i]]; delete proposalVote.sig[proposalVote.forVoteds[_i]]; unchecked { ++_i; } } for (uint256 _i; _i < proposalVote.againstVoteds.length; ) { delete proposalVote.voted[proposalVote.againstVoteds[_i]]; delete proposalVote.sig[proposalVote.againstVoteds[_i]]; unchecked { ++_i; } } delete proposalVote.status; delete proposalVote.hash; delete proposalVote.againstVoteWeight; delete proposalVote.forVoteWeight; delete proposalVote.forVoteds; delete proposalVote.againstVoteds; delete proposalVote.expiryTimestamp; } } /** * @dev Executes the proposal and update the vote status once the proposal is executable. */ function _tryExecute(ProposalVote storage vote_, Proposal.ProposalDetail memory proposal) internal { if (proposal.executable()) { vote_.status = VoteStatus.Executed; (bool[] memory _successCalls, bytes[] memory _returnDatas) = proposal.execute(); emit ProposalExecuted(vote_.hash, _successCalls, _returnDatas); } } /** * @dev Sets the expiry duration for a new proposal. */ function _setProposalExpiryDuration(uint256 expiryDuration) internal { _proposalExpiryDuration = expiryDuration; emit ProposalExpiryDurationChanged(expiryDuration); } /** * @dev Returns the expiry duration for a new proposal. */ function _getProposalExpiryDuration() internal view returns (uint256) { return _proposalExpiryDuration; } /** * @dev Returns whether the voter casted for the proposal. */ function _voted(ProposalVote storage vote_, address voter) internal view returns (bool) { return vote_.voted[voter]; } /** * @dev Returns total weight from validators. */ function _getTotalWeight() internal view virtual returns (uint256); /** * @dev Returns minimum vote to pass a proposal. */ function _getMinimumVoteWeight() internal view virtual returns (uint256); /** * @dev Returns current context is running on whether Ronin chain or on mainchain. */ function _getChainType() internal view virtual returns (ChainType); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../libraries/Proposal.sol"; import "../../libraries/GlobalProposal.sol"; import "./CoreGovernance.sol"; abstract contract GlobalCoreGovernance is CoreGovernance { using Proposal for Proposal.ProposalDetail; using GlobalProposal for GlobalProposal.GlobalProposalDetail; mapping(GlobalProposal.TargetOption => address) internal _targetOptionsMap; /// @dev Emitted when a proposal is created event GlobalProposalCreated( uint256 indexed round, bytes32 indexed proposalHash, Proposal.ProposalDetail proposal, bytes32 globalProposalHash, GlobalProposal.GlobalProposalDetail globalProposal, address creator ); /// @dev Emitted when the target options are updated event TargetOptionUpdated(GlobalProposal.TargetOption indexed targetOption, address indexed addr); constructor(GlobalProposal.TargetOption[] memory targetOptions, address[] memory addrs) { _updateTargetOption(GlobalProposal.TargetOption.BridgeManager, address(this)); _updateManyTargetOption(targetOptions, addrs); } /** * @dev Proposes for a global proposal. * * Emits the `GlobalProposalCreated` event. * */ function _proposeGlobal( uint256 expiryTimestamp, GlobalProposal.TargetOption[] calldata targetOptions, uint256[] memory values, bytes[] memory calldatas, uint256[] memory gasAmounts, address creator ) internal virtual { uint256 round_ = _createVotingRound(0); GlobalProposal.GlobalProposalDetail memory globalProposal = GlobalProposal.GlobalProposalDetail( round_, expiryTimestamp, targetOptions, values, calldatas, gasAmounts ); Proposal.ProposalDetail memory proposal = globalProposal.intoProposalDetail( _resolveTargets({ targetOptions: targetOptions, strict: true }) ); proposal.validate(_proposalExpiryDuration); bytes32 proposalHash = proposal.hash(); _saveVotingRound(vote[0][round_], proposalHash, expiryTimestamp); emit GlobalProposalCreated(round_, proposalHash, proposal, globalProposal.hash(), globalProposal, creator); } /** * @dev Proposes global proposal struct. * * Requirements: * - The proposal nonce is equal to the new round. * * Emits the `GlobalProposalCreated` event. * */ function _proposeGlobalStruct( GlobalProposal.GlobalProposalDetail memory globalProposal, address creator ) internal virtual returns (Proposal.ProposalDetail memory proposal) { proposal = globalProposal.intoProposalDetail( _resolveTargets({ targetOptions: globalProposal.targetOptions, strict: true }) ); proposal.validate(_proposalExpiryDuration); bytes32 proposalHash = proposal.hash(); uint256 round_ = _createVotingRound(0); _saveVotingRound(vote[0][round_], proposalHash, globalProposal.expiryTimestamp); if (round_ != proposal.nonce) revert ErrInvalidProposalNonce(msg.sig); emit GlobalProposalCreated(round_, proposalHash, proposal, globalProposal.hash(), globalProposal, creator); } /** * @dev Returns corresponding address of target options. Return address(0) on non-existent target. */ function resolveTargets( GlobalProposal.TargetOption[] calldata targetOptions ) external view returns (address[] memory targets) { return _resolveTargets({ targetOptions: targetOptions, strict: false }); } /** * @dev Internal helper of {resolveTargets}. * * @param strict When the param is set to `true`, revert on non-existent target. */ function _resolveTargets( GlobalProposal.TargetOption[] memory targetOptions, bool strict ) internal view returns (address[] memory targets) { targets = new address[](targetOptions.length); for (uint256 i; i < targetOptions.length; ) { targets[i] = _targetOptionsMap[targetOptions[i]]; if (strict && targets[i] == address(0)) revert ErrInvalidArguments(msg.sig); unchecked { ++i; } } } /** * @dev Updates list of `targetOptions` to `targets`. * * Requirement: * - Only allow self-call through proposal. * */ function updateManyTargetOption( GlobalProposal.TargetOption[] memory targetOptions, address[] memory targets ) external { // HACK: Cannot reuse the existing library due to too deep stack if (msg.sender != address(this)) revert ErrOnlySelfCall(msg.sig); _updateManyTargetOption(targetOptions, targets); } /** * @dev Updates list of `targetOptions` to `targets`. */ function _updateManyTargetOption( GlobalProposal.TargetOption[] memory targetOptions, address[] memory targets ) internal { for (uint256 i; i < targetOptions.length; ) { if (targets[i] == address(this)) revert ErrInvalidArguments(msg.sig); _updateTargetOption(targetOptions[i], targets[i]); unchecked { ++i; } } } /** * @dev Updates `targetOption` to `target`. * * Requirement: * - Emit a `TargetOptionUpdated` event. */ function _updateTargetOption(GlobalProposal.TargetOption targetOption, address target) internal { _targetOptionsMap[targetOption] = target; emit TargetOptionUpdated(targetOption, target); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../CoreGovernance.sol"; abstract contract CommonGovernanceRelay is CoreGovernance { using Proposal for Proposal.ProposalDetail; using GlobalProposal for GlobalProposal.GlobalProposalDetail; /** * @dev Relays votes by signatures. * * @notice Does not store the voter signature into storage. * */ function _relayVotesBySignatures( Proposal.ProposalDetail memory _proposal, Ballot.VoteType[] calldata _supports, Signature[] calldata _signatures, bytes32 _forDigest, bytes32 _againstDigest ) internal { if (!(_supports.length > 0 && _supports.length == _signatures.length)) revert ErrLengthMismatch(msg.sig); uint256 _forVoteCount; uint256 _againstVoteCount; address[] memory _forVoteSigners = new address[](_signatures.length); address[] memory _againstVoteSigners = new address[](_signatures.length); { address _signer; address _lastSigner; Ballot.VoteType _support; Signature calldata _sig; for (uint256 _i; _i < _signatures.length; ) { _sig = _signatures[_i]; _support = _supports[_i]; if (_support == Ballot.VoteType.For) { _signer = ECDSA.recover(_forDigest, _sig.v, _sig.r, _sig.s); _forVoteSigners[_forVoteCount++] = _signer; } else if (_support == Ballot.VoteType.Against) { _signer = ECDSA.recover(_againstDigest, _sig.v, _sig.r, _sig.s); _againstVoteSigners[_againstVoteCount++] = _signer; } else revert ErrUnsupportedVoteType(msg.sig); if (_lastSigner >= _signer) revert ErrInvalidOrder(msg.sig); _lastSigner = _signer; unchecked { ++_i; } } } assembly { mstore(_forVoteSigners, _forVoteCount) mstore(_againstVoteSigners, _againstVoteCount) } ProposalVote storage _vote = vote[_proposal.chainId][_proposal.nonce]; uint256 _minimumForVoteWeight = _getMinimumVoteWeight(); uint256 _totalForVoteWeight = _sumWeight(_forVoteSigners); if (_totalForVoteWeight >= _minimumForVoteWeight) { if (_totalForVoteWeight == 0) revert ErrInvalidVoteWeight(msg.sig); _vote.status = VoteStatus.Approved; emit ProposalApproved(_vote.hash); _tryExecute(_vote, _proposal); return; } uint256 _minimumAgainstVoteWeight = _getTotalWeight() - _minimumForVoteWeight + 1; uint256 _totalAgainstVoteWeight = _sumWeight(_againstVoteSigners); if (_totalAgainstVoteWeight >= _minimumAgainstVoteWeight) { if (_totalAgainstVoteWeight == 0) revert ErrInvalidVoteWeight(msg.sig); _vote.status = VoteStatus.Rejected; emit ProposalRejected(_vote.hash); return; } revert ErrRelayFailed(msg.sig); } /** * @dev Returns the weight of the governor list. */ function _sumWeight(address[] memory _governors) internal view virtual returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../GlobalCoreGovernance.sol"; import "./CommonGovernanceRelay.sol"; abstract contract GlobalGovernanceRelay is CommonGovernanceRelay, GlobalCoreGovernance { using GlobalProposal for GlobalProposal.GlobalProposalDetail; /** * @dev Returns whether the voter `_voter` casted vote for the proposal. */ function globalProposalRelayed(uint256 _round) external view returns (bool) { return vote[0][_round].status != VoteStatus.Pending; } /** * @dev Relays voted global proposal. * * Requirements: * - The relay proposal is finalized. * */ function _relayGlobalProposal( GlobalProposal.GlobalProposalDetail calldata globalProposal, Ballot.VoteType[] calldata supports_, Signature[] calldata signatures, bytes32 domainSeparator, address creator ) internal { Proposal.ProposalDetail memory _proposal = _proposeGlobalStruct(globalProposal, creator); bytes32 globalProposalHash = globalProposal.hash(); _relayVotesBySignatures( _proposal, supports_, signatures, ECDSA.toTypedDataHash(domainSeparator, Ballot.hash(globalProposalHash, Ballot.VoteType.For)), ECDSA.toTypedDataHash(domainSeparator, Ballot.hash(globalProposalHash, Ballot.VoteType.Against)) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../CoreGovernance.sol"; import "./CommonGovernanceRelay.sol"; abstract contract GovernanceRelay is CoreGovernance, CommonGovernanceRelay { using Proposal for Proposal.ProposalDetail; using GlobalProposal for GlobalProposal.GlobalProposalDetail; /** * @dev Relays voted proposal. * * Requirements: * - The relay proposal is finalized. * */ function _relayProposal( Proposal.ProposalDetail calldata _proposal, Ballot.VoteType[] calldata _supports, Signature[] calldata _signatures, bytes32 _domainSeparator, address _creator ) internal { _proposeProposalStruct(_proposal, _creator); bytes32 _proposalHash = _proposal.hash(); _relayVotesBySignatures( _proposal, _supports, _signatures, ECDSA.toTypedDataHash(_domainSeparator, Ballot.hash(_proposalHash, Ballot.VoteType.For)), ECDSA.toTypedDataHash(_domainSeparator, Ballot.hash(_proposalHash, Ballot.VoteType.Against)) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IQuorum { /// @dev Emitted when the threshold is updated event ThresholdUpdated( uint256 indexed nonce, uint256 indexed numerator, uint256 indexed denominator, uint256 previousNumerator, uint256 previousDenominator ); /** * @dev Returns the threshold. */ function getThreshold() external view returns (uint256 _num, uint256 _denom); /** * @dev Checks whether the `_voteWeight` passes the threshold. */ function checkThreshold(uint256 _voteWeight) external view returns (bool); /** * @dev Returns the minimum vote weight to pass the threshold. */ function minimumVoteWeight() external view returns (uint256); /** * @dev Sets the threshold. * * Requirements: * - The method caller is admin. * * Emits the `ThresholdUpdated` event. * */ function setThreshold( uint256 _numerator, uint256 _denominator ) external returns (uint256 _previousNum, uint256 _previousDenom); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IBridgeManagerEvents } from "./events/IBridgeManagerEvents.sol"; /** * @title IBridgeManager * @dev The interface for managing bridge operators. */ interface IBridgeManager is IBridgeManagerEvents { /** * @dev The domain separator used for computing hash digests in the contract. */ function DOMAIN_SEPARATOR() external view returns (bytes32); /** * @dev Returns the total number of bridge operators. * @return The total number of bridge operators. */ function totalBridgeOperator() external view returns (uint256); /** * @dev Checks if the given address is a bridge operator. * @param addr The address to check. * @return A boolean indicating whether the address is a bridge operator. */ function isBridgeOperator(address addr) external view returns (bool); /** * @dev Retrieves the full information of all registered bridge operators. * * This external function allows external callers to obtain the full information of all the registered bridge operators. * The returned arrays include the addresses of governors, bridge operators, and their corresponding vote weights. * * @return governors An array of addresses representing the governors of each bridge operator. * @return bridgeOperators An array of addresses representing the registered bridge operators. * @return weights An array of uint256 values representing the vote weights of each bridge operator. * * Note: The length of each array will be the same, and the order of elements corresponds to the same bridge operator. * * Example Usage: * ``` * (address[] memory governors, address[] memory bridgeOperators, uint256[] memory weights) = getFullBridgeOperatorInfos(); * for (uint256 i = 0; i < bridgeOperators.length; i++) { * // Access individual information for each bridge operator. * address governor = governors[i]; * address bridgeOperator = bridgeOperators[i]; * uint256 weight = weights[i]; * // ... (Process or use the information as required) ... * } * ``` * */ function getFullBridgeOperatorInfos() external view returns (address[] memory governors, address[] memory bridgeOperators, uint96[] memory weights); /** * @dev Returns total weights of the governor list. */ function sumGovernorsWeight(address[] calldata governors) external view returns (uint256 sum); /** * @dev Returns total weights. */ function getTotalWeight() external view returns (uint256); /** * @dev Returns an array of all bridge operators. * @return An array containing the addresses of all bridge operators. */ function getBridgeOperators() external view returns (address[] memory); /** * @dev Returns an array of bridge operators correspoding to governor addresses. * @return bridgeOperators_ An array containing the addresses of all bridge operators. */ function getBridgeOperatorOf(address[] calldata gorvernors) external view returns (address[] memory bridgeOperators_); /** * @dev Retrieves the governors corresponding to a given array of bridge operators. * This external function allows external callers to obtain the governors associated with a given array of bridge operators. * The function takes an input array `bridgeOperators` containing bridge operator addresses and returns an array of corresponding governors. * @param bridgeOperators An array of bridge operator addresses for which governors are to be retrieved. * @return governors An array of addresses representing the governors corresponding to the provided bridge operators. */ function getGovernorsOf(address[] calldata bridgeOperators) external view returns (address[] memory governors); /** * @dev External function to retrieve the vote weight of a specific governor. * @param governor The address of the governor to get the vote weight for. * @return voteWeight The vote weight of the specified governor. */ function getGovernorWeight(address governor) external view returns (uint96); /** * @dev External function to retrieve the vote weight of a specific bridge operator. * @param bridgeOperator The address of the bridge operator to get the vote weight for. * @return weight The vote weight of the specified bridge operator. */ function getBridgeOperatorWeight(address bridgeOperator) external view returns (uint96 weight); /** * @dev Returns the weights of a list of governor addresses. */ function getGovernorWeights(address[] calldata governors) external view returns (uint96[] memory weights); /** * @dev Returns an array of all governors. * @return An array containing the addresses of all governors. */ function getGovernors() external view returns (address[] memory); /** * @dev Adds multiple bridge operators. * @param governors An array of addresses of hot/cold wallets for bridge operator to update their node address. * @param bridgeOperators An array of addresses representing the bridge operators to add. * @return addeds An array of booleans indicating whether each bridge operator was added successfully. * * Note: return boolean array `addeds` indicates whether a group (voteWeight, governor, operator) are recorded. * It is expected that FE/BE staticcall to the function first to get the return values and handle it correctly. * Governors are expected to see the outcome of this function and decide if they want to vote for the proposal or not. * * Example Usage: * Making an `eth_call` in ethers.js * ``` * const {addeds} = await bridgeManagerContract.callStatic.addBridgeOperators( * voteWeights, * governors, * bridgeOperators, * // overriding the caller to the contract itself since we use `onlySelfCall` guard * {from: bridgeManagerContract.address} * ) * const filteredOperators = bridgeOperators.filter((_, index) => addeds[index]); * const filteredWeights = weights.filter((_, index) => addeds[index]); * const filteredGovernors = governors.filter((_, index) => addeds[index]); * // ... (Process or use the information as required) ... * ``` */ function addBridgeOperators( uint96[] calldata voteWeights, address[] calldata governors, address[] calldata bridgeOperators ) external returns (bool[] memory addeds); /** * @dev Removes multiple bridge operators. * @param bridgeOperators An array of addresses representing the bridge operators to remove. * @return removeds An array of booleans indicating whether each bridge operator was removed successfully. * * * Note: return boolean array `removeds` indicates whether a group (voteWeight, governor, operator) are recorded. * It is expected that FE/BE staticcall to the function first to get the return values and handle it correctly. * Governors are expected to see the outcome of this function and decide if they want to vote for the proposal or not. * * Example Usage: * Making an `eth_call` in ethers.js * ``` * const {removeds} = await bridgeManagerContract.callStatic.removeBridgeOperators( * bridgeOperators, * // overriding the caller to the contract itself since we use `onlySelfCall` guard * {from: bridgeManagerContract.address} * ) * const filteredOperators = bridgeOperators.filter((_, index) => removeds[index]); * // ... (Process or use the information as required) ... * ``` */ function removeBridgeOperators(address[] calldata bridgeOperators) external returns (bool[] memory removeds); /** * @dev Governor updates their corresponding governor and/or operator address. * Requirements: * - The caller must the governor of the operator that is requested changes. * @param bridgeOperator The address of the bridge operator to update. */ function updateBridgeOperator(address bridgeOperator) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @title IBridgeManagerCallback * @dev Interface for the callback functions to be implemented by the Bridge Manager contract. */ interface IBridgeManagerCallback is IERC165 { /** * @dev Handles the event when bridge operators are added. * @param bridgeOperators The addresses of the bridge operators. * @param addeds The corresponding boolean values indicating whether the operators were added or not. * @return selector The selector of the function being called. */ function onBridgeOperatorsAdded( address[] memory bridgeOperators, bool[] memory addeds ) external returns (bytes4 selector); /** * @dev Handles the event when bridge operators are removed. * @param bridgeOperators The addresses of the bridge operators. * @param removeds The corresponding boolean values indicating whether the operators were removed or not. * @return selector The selector of the function being called. */ function onBridgeOperatorsRemoved( address[] memory bridgeOperators, bool[] memory removeds ) external returns (bytes4 selector); /** * @dev Handles the event when a bridge operator is updated. * @param currentBridgeOperator The address of the current bridge operator. * @param newbridgeOperator The new address of the bridge operator. * @return selector The selector of the function being called. */ function onBridgeOperatorUpdated( address currentBridgeOperator, address newbridgeOperator ) external returns (bytes4 selector); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBridgeManagerCallbackRegister { /** * @dev Emitted when the contract notifies multiple registers with statuses and return data. */ event Notified(bytes callData, address[] registers, bool[] statuses, bytes[] returnDatas); /** * @dev Retrieves the addresses of registered callbacks. * @return registers An array containing the addresses of registered callbacks. */ function getCallbackRegisters() external view returns (address[] memory registers); /** * @dev Registers multiple callbacks with the bridge. * @param registers The array of callback addresses to register. * @return registereds An array indicating the success status of each registration. */ function registerCallbacks(address[] calldata registers) external returns (bool[] memory registereds); /** * @dev Unregisters multiple callbacks from the bridge. * @param registers The array of callback addresses to unregister. * @return unregistereds An array indicating the success status of each unregistration. */ function unregisterCallbacks(address[] calldata registers) external returns (bool[] memory unregistereds); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBridgeManagerEvents { /** * @dev The structure representing information about a bridge operator. * @param addr The address of the bridge operator. * @param voteWeight The vote weight assigned to the bridge operator. */ struct BridgeOperatorInfo { address addr; uint96 voteWeight; } /** * @dev Emitted when new bridge operators are added. * @param statuses The array of boolean values represents whether the corresponding bridge operator is added successfully. * @param voteWeights The array of vote weights assigned to the added bridge operators. * @param governors The array of addresses representing the governors associated with the added bridge operators. * @param bridgeOperators The array of addresses representing the added bridge operators. */ event BridgeOperatorsAdded(bool[] statuses, uint96[] voteWeights, address[] governors, address[] bridgeOperators); /** * @dev Emitted when bridge operators are removed. * @param statuses The array of boolean values representing the statuses of the removed bridge operators. * @param bridgeOperators The array of addresses representing the removed bridge operators. */ event BridgeOperatorsRemoved(bool[] statuses, address[] bridgeOperators); /** * @dev Emitted when a bridge operator is updated. * @param governor The address of the governor initiating the update. * @param fromBridgeOperator The address of the bridge operator being updated. * @param toBridgeOperator The updated address of the bridge operator. */ event BridgeOperatorUpdated( address indexed governor, address indexed fromBridgeOperator, address indexed toBridgeOperator ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; import { ContractType } from "../../utils/ContractType.sol"; interface IHasContracts { /// @dev Error of invalid role. error ErrContractTypeNotFound(ContractType contractType); /// @dev Emitted when a contract is updated. event ContractUpdated(ContractType indexed contractType, address indexed addr); /** * @dev Returns the address of a contract with a specific role. * Throws an error if no contract is set for the specified role. * * @param contractType The role of the contract to retrieve. * @return contract_ The address of the contract with the specified role. */ function getContract(ContractType contractType) external view returns (address contract_); /** * @dev Sets the address of a contract with a specific role. * Emits the event {ContractUpdated}. * @param contractType The role of the contract to set. * @param addr The address of the contract to set. */ function setContract(ContractType contractType, address addr) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ChainTypeConsumer { enum ChainType { RoninChain, Mainchain } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface SignatureConsumer { struct Signature { uint8 v; bytes32 r; bytes32 s; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VoteStatusConsumer { enum VoteStatus { Pending, Approved, Executed, Rejected, Expired } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; library AddressArrayUtils { /** * @dev Error thrown when a duplicated element is detected in an array. * @param msgSig The function signature that invoke the error. */ error ErrDuplicated(bytes4 msgSig); /** * @dev Returns whether or not there's a duplicate. Runs in O(n^2). * @param A Array to search * @return Returns true if duplicate, false otherwise */ function hasDuplicate(address[] memory A) internal pure returns (bool) { if (A.length == 0) { return false; } unchecked { for (uint256 i = 0; i < A.length - 1; i++) { for (uint256 j = i + 1; j < A.length; j++) { if (A[i] == A[j]) { return true; } } } } return false; } /** * @dev Returns whether two arrays of addresses are equal or not. */ function isEqual(address[] memory _this, address[] memory _other) internal pure returns (bool yes_) { // Hashing two arrays and compare their hash assembly { let _thisHash := keccak256(add(_this, 32), mul(mload(_this), 32)) let _otherHash := keccak256(add(_other, 32), mul(mload(_other), 32)) yes_ := eq(_thisHash, _otherHash) } } /** * @dev Return the concatenated array from a and b. */ function extend(address[] memory a, address[] memory b) internal pure returns (address[] memory c) { uint256 lengthA = a.length; uint256 lengthB = b.length; unchecked { c = new address[](lengthA + lengthB); } uint256 i; for (; i < lengthA; ) { c[i] = a[i]; unchecked { ++i; } } for (uint256 j; j < lengthB; ) { c[i] = b[j]; unchecked { ++i; ++j; } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; library Ballot { using ECDSA for bytes32; enum VoteType { For, Against } // keccak256("Ballot(bytes32 proposalHash,uint8 support)"); bytes32 private constant BALLOT_TYPEHASH = 0xd900570327c4c0df8dd6bdd522b7da7e39145dd049d2fd4602276adcd511e3c2; function hash(bytes32 _proposalHash, VoteType _support) internal pure returns (bytes32 digest) { // return keccak256(abi.encode(BALLOT_TYPEHASH, _proposalHash, _support)); assembly { let ptr := mload(0x40) mstore(ptr, BALLOT_TYPEHASH) mstore(add(ptr, 0x20), _proposalHash) mstore(add(ptr, 0x40), _support) digest := keccak256(ptr, 0x60) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Proposal.sol"; library GlobalProposal { /** * @dev Error thrown when attempting to interact with an unsupported target. */ error ErrUnsupportedTarget(bytes32 proposalHash, uint256 targetNumber); enum TargetOption { /* 0 */ BridgeManager, /* 1 */ GatewayContract, /* 2 */ BridgeReward, /* 3 */ BridgeSlash, /* 4 */ BridgeTracking } struct GlobalProposalDetail { // Nonce to make sure proposals are executed in order uint256 nonce; uint256 expiryTimestamp; TargetOption[] targetOptions; uint256[] values; bytes[] calldatas; uint256[] gasAmounts; } // keccak256("GlobalProposalDetail(uint256 nonce,uint256 expiryTimestamp,uint8[] targetOptions,uint256[] values,bytes[] calldatas,uint256[] gasAmounts)"); bytes32 public constant TYPE_HASH = 0x1463f426c05aff2c1a7a0957a71c9898bc8b47142540538e79ee25ee91141350; /** * @dev Returns struct hash of the proposal. */ function hash(GlobalProposalDetail memory self) internal pure returns (bytes32 digest_) { uint256[] memory values = self.values; TargetOption[] memory targets = self.targetOptions; bytes32[] memory calldataHashList = new bytes32[](self.calldatas.length); uint256[] memory gasAmounts = self.gasAmounts; for (uint256 i; i < calldataHashList.length; ) { calldataHashList[i] = keccak256(self.calldatas[i]); unchecked { ++i; } } /* * return * keccak256( * abi.encode( * TYPE_HASH, * _proposal.nonce, * _proposal.expiryTimestamp, * _targetsHash, * _valuesHash, * _calldatasHash, * _gasAmountsHash * ) * ); */ assembly { let ptr := mload(0x40) mstore(ptr, TYPE_HASH) mstore(add(ptr, 0x20), mload(self)) // _proposal.nonce mstore(add(ptr, 0x40), mload(add(self, 0x20))) // _proposal.expiryTimestamp let arrayHashed arrayHashed := keccak256(add(targets, 32), mul(mload(targets), 32)) // targetsHash mstore(add(ptr, 0x60), arrayHashed) arrayHashed := keccak256(add(values, 32), mul(mload(values), 32)) // _valuesHash mstore(add(ptr, 0x80), arrayHashed) arrayHashed := keccak256(add(calldataHashList, 32), mul(mload(calldataHashList), 32)) // _calldatasHash mstore(add(ptr, 0xa0), arrayHashed) arrayHashed := keccak256(add(gasAmounts, 32), mul(mload(gasAmounts), 32)) // _gasAmountsHash mstore(add(ptr, 0xc0), arrayHashed) digest_ := keccak256(ptr, 0xe0) } } /** * @dev Converts into the normal proposal. */ function intoProposalDetail( GlobalProposalDetail memory self, address[] memory targets ) internal pure returns (Proposal.ProposalDetail memory detail_) { detail_.nonce = self.nonce; detail_.expiryTimestamp = self.expiryTimestamp; detail_.chainId = 0; detail_.targets = new address[](self.targetOptions.length); detail_.values = self.values; detail_.calldatas = self.calldatas; detail_.gasAmounts = self.gasAmounts; for (uint256 i; i < self.targetOptions.length; ) { detail_.targets[i] = targets[i]; unchecked { ++i; } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { ErrInvalidChainId, ErrLengthMismatch } from "../utils/CommonErrors.sol"; library Proposal { /** * @dev Error thrown when there is insufficient gas to execute a function. */ error ErrInsufficientGas(bytes32 proposalHash); /** * @dev Error thrown when an invalid expiry timestamp is provided. */ error ErrInvalidExpiryTimestamp(); struct ProposalDetail { // Nonce to make sure proposals are executed in order uint256 nonce; // Value 0: all chain should run this proposal // Other values: only specifc chain has to execute uint256 chainId; uint256 expiryTimestamp; address[] targets; uint256[] values; bytes[] calldatas; uint256[] gasAmounts; } // keccak256("ProposalDetail(uint256 nonce,uint256 chainId,uint256 expiryTimestamp,address[] targets,uint256[] values,bytes[] calldatas,uint256[] gasAmounts)"); bytes32 public constant TYPE_HASH = 0xd051578048e6ff0bbc9fca3b65a42088dbde10f36ca841de566711087ad9b08a; /** * @dev Validates the proposal. */ function validate(ProposalDetail memory _proposal, uint256 _maxExpiryDuration) internal view { if ( !(_proposal.targets.length > 0 && _proposal.targets.length == _proposal.values.length && _proposal.targets.length == _proposal.calldatas.length && _proposal.targets.length == _proposal.gasAmounts.length) ) { revert ErrLengthMismatch(msg.sig); } if (_proposal.expiryTimestamp > block.timestamp + _maxExpiryDuration) { revert ErrInvalidExpiryTimestamp(); } } /** * @dev Returns struct hash of the proposal. */ function hash(ProposalDetail memory _proposal) internal pure returns (bytes32 digest_) { uint256[] memory _values = _proposal.values; address[] memory _targets = _proposal.targets; bytes32[] memory _calldataHashList = new bytes32[](_proposal.calldatas.length); uint256[] memory _gasAmounts = _proposal.gasAmounts; for (uint256 _i; _i < _calldataHashList.length; ) { _calldataHashList[_i] = keccak256(_proposal.calldatas[_i]); unchecked { ++_i; } } // return // keccak256( // abi.encode( // TYPE_HASH, // _proposal.nonce, // _proposal.chainId, // _targetsHash, // _valuesHash, // _calldatasHash, // _gasAmountsHash // ) // ); // / assembly { let ptr := mload(0x40) mstore(ptr, TYPE_HASH) mstore(add(ptr, 0x20), mload(_proposal)) // _proposal.nonce mstore(add(ptr, 0x40), mload(add(_proposal, 0x20))) // _proposal.chainId mstore(add(ptr, 0x60), mload(add(_proposal, 0x40))) // expiry timestamp let arrayHashed arrayHashed := keccak256(add(_targets, 32), mul(mload(_targets), 32)) // targetsHash mstore(add(ptr, 0x80), arrayHashed) arrayHashed := keccak256(add(_values, 32), mul(mload(_values), 32)) // _valuesHash mstore(add(ptr, 0xa0), arrayHashed) arrayHashed := keccak256(add(_calldataHashList, 32), mul(mload(_calldataHashList), 32)) // _calldatasHash mstore(add(ptr, 0xc0), arrayHashed) arrayHashed := keccak256(add(_gasAmounts, 32), mul(mload(_gasAmounts), 32)) // _gasAmountsHash mstore(add(ptr, 0xe0), arrayHashed) digest_ := keccak256(ptr, 0x100) } } /** * @dev Returns whether the proposal is executable for the current chain. * * @notice Does not check whether the call result is successful or not. Please use `execute` instead. * */ function executable(ProposalDetail memory _proposal) internal view returns (bool _result) { return _proposal.chainId == 0 || _proposal.chainId == block.chainid; } /** * @dev Executes the proposal. */ function execute( ProposalDetail memory _proposal ) internal returns (bool[] memory _successCalls, bytes[] memory _returnDatas) { if (!executable(_proposal)) revert ErrInvalidChainId(msg.sig, _proposal.chainId, block.chainid); _successCalls = new bool[](_proposal.targets.length); _returnDatas = new bytes[](_proposal.targets.length); for (uint256 _i = 0; _i < _proposal.targets.length; ) { if (gasleft() <= _proposal.gasAmounts[_i]) revert ErrInsufficientGas(hash(_proposal)); (_successCalls[_i], _returnDatas[_i]) = _proposal.targets[_i].call{ value: _proposal.values[_i], gas: _proposal.gasAmounts[_i] }(_proposal.calldatas[_i]); unchecked { ++_i; } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { LibTUint256Slot } from "./operations/LibTUint256Slot.sol"; type TUint256Slot is bytes32; using { LibTUint256Slot.add, LibTUint256Slot.sub, LibTUint256Slot.mul, LibTUint256Slot.div, LibTUint256Slot.load, LibTUint256Slot.store, LibTUint256Slot.addAssign, LibTUint256Slot.subAssign, LibTUint256Slot.preDecrement, LibTUint256Slot.postDecrement, LibTUint256Slot.preIncrement, LibTUint256Slot.postIncrement } for TUint256Slot global;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { TUint256Slot } from "../Types.sol"; /** * @title LibTUint256Slot * @dev Library for handling unsigned 256-bit integers. */ library LibTUint256Slot { /// @dev value is equal to bytes4(keccak256("Panic(uint256)")) /// @dev see: https://github.com/foundry-rs/forge-std/blob/master/src/StdError.sol uint256 private constant PANIC_ERROR_SIGNATURE = 0x4e487b71; /// @dev error code for {Arithmetic over/underflow} error uint256 private constant ARITHMETIC_ERROR_CODE = 0x11; /// @dev error code for {Division or modulo by 0} error uint256 private constant DIVISION_ERROR_CODE = 0x12; /** * @dev Loads the value of the TUint256Slot variable. * @param self The TUint256Slot variable. * @return val The loaded value. */ function load(TUint256Slot self) internal view returns (uint256 val) { assembly { val := sload(self) } } /** * @dev Stores a value into the TUint256Slot variable. * @param self The TUint256Slot variable. * @param other The value to be stored. */ function store(TUint256Slot self, uint256 other) internal { assembly { sstore(self, other) } } /** * @dev Multiplies the TUint256Slot variable by a given value. * @param self The TUint256Slot variable. * @param other The value to multiply by. * @return res The resulting value after multiplication. */ function mul(TUint256Slot self, uint256 other) internal view returns (uint256 res) { assembly { let storedVal := sload(self) if iszero(iszero(storedVal)) { res := mul(storedVal, other) // Overflow check if iszero(eq(other, div(res, storedVal))) { // Store 4 bytes the function selector of Panic(uint256) // Equivalent to revert Panic(uint256) mstore(0x00, PANIC_ERROR_SIGNATURE) // Store 4 bytes of division error code in the next slot mstore(0x20, ARITHMETIC_ERROR_CODE) // Revert 36 bytes of error starting from 0x1c revert(0x1c, 0x24) } } } } /** * @dev Divides the TUint256Slot variable by a given value. * @param self The TUint256Slot variable. * @param other The value to divide by. * @return res The resulting value after division. */ function div(TUint256Slot self, uint256 other) internal view returns (uint256 res) { assembly { let storedVal := sload(self) // revert if divide by zero if iszero(other) { // Store 4 bytes the function selector of Panic(uint256) // Equivalent to revert Panic(uint256) mstore(0x00, PANIC_ERROR_SIGNATURE) // Store 4 bytes of division error code in the next slot mstore(0x20, DIVISION_ERROR_CODE) // Revert 36 bytes of error starting from 0x1c revert(0x1c, 0x24) } res := div(storedVal, other) } } /** * @dev Subtracts a given value from the TUint256Slot variable. * @param self The TUint256Slot variable. * @param other The value to subtract. * @return res The resulting value after subtraction. */ function sub(TUint256Slot self, uint256 other) internal view returns (uint256 res) { assembly { let storedVal := sload(self) // Underflow check if lt(storedVal, other) { // Store 4 bytes the function selector of Panic(uint256) // Equivalent to revert Panic(uint256) mstore(0x00, PANIC_ERROR_SIGNATURE) // Store 4 bytes of division error code in the next slot mstore(0x20, ARITHMETIC_ERROR_CODE) // Revert 36 bytes of error starting from 0x1c revert(0x1c, 0x24) } res := sub(storedVal, other) } } /** * @dev Adds a given value to the TUint256Slot variable. * @param self The TUint256Slot variable. * @param other The value to add. * @return res The resulting value after addition. */ function add(TUint256Slot self, uint256 other) internal view returns (uint256 res) { assembly { let storedVal := sload(self) res := add(storedVal, other) // Overflow check if lt(res, other) { // Store 4 bytes the function selector of Panic(uint256) // Equivalent to revert Panic(uint256) mstore(0x00, PANIC_ERROR_SIGNATURE) // Store 4 bytes of division error code in the next slot mstore(0x20, ARITHMETIC_ERROR_CODE) // Revert 36 bytes of error starting from 0x1c revert(0x1c, 0x24) } } } /** * @dev Increments the TUint256Slot variable by 1 and returns the new value. * @param self The TUint256Slot variable. * @return res The resulting value after incrementing. */ function preIncrement(TUint256Slot self) internal returns (uint256 res) { res = addAssign(self, 1); } /** * @dev Increments the TUint256Slot variable by 1 and returns the original value. * @param self The TUint256Slot variable. * @return res The original value before incrementing. */ function postIncrement(TUint256Slot self) internal returns (uint256 res) { res = load(self); store(self, res + 1); } /** * @dev Decrements the TUint256Slot variable by 1 and returns the new value. * @param self The TUint256Slot variable. * @return res The resulting value after decrementing. */ function preDecrement(TUint256Slot self) internal returns (uint256 res) { res = subAssign(self, 1); } /** * @dev Decrements the TUint256Slot variable by 1 and returns the new value. * @param self The TUint256Slot variable. * @return res The resulting value before decrementing. */ function postDecrement(TUint256Slot self) internal returns (uint256 res) { res = load(self); store(self, res - 1); } /** * @dev Adds a given value to the TUint256Slot variable and stores the result. * @param self The TUint256Slot variable. * @param other The value to add. * @return res The resulting value after addition and storage. */ function addAssign(TUint256Slot self, uint256 other) internal returns (uint256 res) { store(self, res = add(self, other)); } /** * @dev Subtracts a given value from the TUint256Slot variable and stores the result. * @param self The TUint256Slot variable. * @param other The value to subtract. * @return res The resulting value after subtraction and storage. */ function subAssign(TUint256Slot self, uint256 other) internal returns (uint256 res) { store(self, res = sub(self, other)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { ContractType } from "./ContractType.sol"; import { RoleAccess } from "./RoleAccess.sol"; error ErrSyncTooFarPeriod(uint256 period, uint256 latestRewardedPeriod); /** * @dev Error thrown when an address is expected to be an already created externally owned account (EOA). * This error indicates that the provided address is invalid for certain contract operations that require already created EOA. */ error ErrAddressIsNotCreatedEOA(address addr, bytes32 codehash); /** * @dev Error raised when a bridge operator update operation fails. * @param bridgeOperator The address of the bridge operator that failed to update. */ error ErrBridgeOperatorUpdateFailed(address bridgeOperator); /** * @dev Error thrown when attempting to add a bridge operator that already exists in the contract. * This error indicates that the provided bridge operator address is already registered as a bridge operator in the contract. */ error ErrBridgeOperatorAlreadyExisted(address bridgeOperator); /** * @dev The error indicating an unsupported interface. * @param interfaceId The bytes4 interface identifier that is not supported. * @param addr The address where the unsupported interface was encountered. */ error ErrUnsupportedInterface(bytes4 interfaceId, address addr); /** * @dev Error thrown when the return data from a callback function is invalid. * @param callbackFnSig The signature of the callback function that returned invalid data. * @param register The address of the register where the callback function was invoked. * @param returnData The invalid return data received from the callback function. */ error ErrInvalidReturnData(bytes4 callbackFnSig, address register, bytes returnData); /** * @dev Error of set to non-contract. */ error ErrZeroCodeContract(address addr); /** * @dev Error indicating that arguments are invalid. */ error ErrInvalidArguments(bytes4 msgSig); /** * @dev Error indicating that given address is null when it should not. */ error ErrZeroAddress(bytes4 msgSig); /** * @dev Error indicating that the provided threshold is invalid for a specific function signature. * @param msgSig The function signature (bytes4) that the invalid threshold applies to. */ error ErrInvalidThreshold(bytes4 msgSig); /** * @dev Error indicating that a function can only be called by the contract itself. * @param msgSig The function signature (bytes4) that can only be called by the contract itself. */ error ErrOnlySelfCall(bytes4 msgSig); /** * @dev Error indicating that the caller is unauthorized to perform a specific function. * @param msgSig The function signature (bytes4) that the caller is unauthorized to perform. * @param expectedRole The role required to perform the function. */ error ErrUnauthorized(bytes4 msgSig, RoleAccess expectedRole); /** * @dev Error indicating that the caller is unauthorized to perform a specific function. * @param msgSig The function signature (bytes4) that the caller is unauthorized to perform. */ error ErrUnauthorizedCall(bytes4 msgSig); /** * @dev Error indicating that the caller is unauthorized to perform a specific function. * @param msgSig The function signature (bytes4). * @param expectedContractType The contract type required to perform the function. * @param actual The actual address that called to the function. */ error ErrUnexpectedInternalCall(bytes4 msgSig, ContractType expectedContractType, address actual); /** * @dev Error indicating that an array is empty when it should contain elements. */ error ErrEmptyArray(); /** * @dev Error indicating a mismatch in the length of input parameters or arrays for a specific function. * @param msgSig The function signature (bytes4) that has a length mismatch. */ error ErrLengthMismatch(bytes4 msgSig); /** * @dev Error indicating that a proxy call to an external contract has failed. * @param msgSig The function signature (bytes4) of the proxy call that failed. * @param extCallSig The function signature (bytes4) of the external contract call that failed. */ error ErrProxyCallFailed(bytes4 msgSig, bytes4 extCallSig); /** * @dev Error indicating that a function tried to call a precompiled contract that is not allowed. * @param msgSig The function signature (bytes4) that attempted to call a precompiled contract. */ error ErrCallPrecompiled(bytes4 msgSig); /** * @dev Error indicating that a native token transfer has failed. * @param msgSig The function signature (bytes4) of the token transfer that failed. */ error ErrNativeTransferFailed(bytes4 msgSig); /** * @dev Error indicating that an order is invalid. * @param msgSig The function signature (bytes4) of the operation that encountered an invalid order. */ error ErrInvalidOrder(bytes4 msgSig); /** * @dev Error indicating that the chain ID is invalid. * @param msgSig The function signature (bytes4) of the operation that encountered an invalid chain ID. * @param actual Current chain ID that executing function. * @param expected Expected chain ID required for the tx to success. */ error ErrInvalidChainId(bytes4 msgSig, uint256 actual, uint256 expected); /** * @dev Error indicating that a vote type is not supported. * @param msgSig The function signature (bytes4) of the operation that encountered an unsupported vote type. */ error ErrUnsupportedVoteType(bytes4 msgSig); /** * @dev Error indicating that the proposal nonce is invalid. * @param msgSig The function signature (bytes4) of the operation that encountered an invalid proposal nonce. */ error ErrInvalidProposalNonce(bytes4 msgSig); /** * @dev Error indicating that a voter has already voted. * @param voter The address of the voter who has already voted. */ error ErrAlreadyVoted(address voter); /** * @dev Error indicating that a signature is invalid for a specific function signature. * @param msgSig The function signature (bytes4) that encountered an invalid signature. */ error ErrInvalidSignatures(bytes4 msgSig); /** * @dev Error indicating that a relay call has failed. * @param msgSig The function signature (bytes4) of the relay call that failed. */ error ErrRelayFailed(bytes4 msgSig); /** * @dev Error indicating that a vote weight is invalid for a specific function signature. * @param msgSig The function signature (bytes4) that encountered an invalid vote weight. */ error ErrInvalidVoteWeight(bytes4 msgSig); /** * @dev Error indicating that a query was made for an outdated bridge operator set. */ error ErrQueryForOutdatedBridgeOperatorSet(); /** * @dev Error indicating that a request is invalid. */ error ErrInvalidRequest(); /** * @dev Error indicating that a token standard is invalid. */ error ErrInvalidTokenStandard(); /** * @dev Error indicating that a token is not supported. */ error ErrUnsupportedToken(); /** * @dev Error indicating that a receipt kind is invalid. */ error ErrInvalidReceiptKind(); /** * @dev Error indicating that a receipt is invalid. */ error ErrInvalidReceipt(); /** * @dev Error indicating that an address is not payable. */ error ErrNonpayableAddress(address); /** * @dev Error indicating that the period is already processed, i.e. scattered reward. */ error ErrPeriodAlreadyProcessed(uint256 requestingPeriod, uint256 latestPeriod); /** * @dev Error thrown when an invalid vote hash is provided. */ error ErrInvalidVoteHash(); /** * @dev Error thrown when querying for an empty vote. */ error ErrQueryForEmptyVote(); /** * @dev Error thrown when querying for an expired vote. */ error ErrQueryForExpiredVote(); /** * @dev Error thrown when querying for a non-existent vote. */ error ErrQueryForNonExistentVote(); /** * @dev Error indicating that the method is only called once per block. */ error ErrOncePerBlock(); /** * @dev Error of method caller must be coinbase */ error ErrCallerMustBeCoinbase();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; enum ContractType { /* 0 */ UNKNOWN, /* 1 */ PAUSE_ENFORCER, /* 2 */ BRIDGE, /* 3 */ BRIDGE_TRACKING, /* 4 */ GOVERNANCE_ADMIN, /* 5 */ MAINTENANCE, /* 6 */ SLASH_INDICATOR, /* 7 */ STAKING_VESTING, /* 8 */ VALIDATOR, /* 9 */ STAKING, /* 10 */ RONIN_TRUSTED_ORGANIZATION, /* 11 */ BRIDGE_MANAGER, /* 12 */ BRIDGE_SLASH, /* 13 */ BRIDGE_REWARD, /* 14 */ FAST_FINALITY_TRACKING, /* 15 */ PROFILE }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { AddressArrayUtils } from "../libraries/AddressArrayUtils.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { TransparentUpgradeableProxyV2 } from "../extensions/TransparentUpgradeableProxyV2.sol"; import { ErrAddressIsNotCreatedEOA, ErrZeroAddress, ErrOnlySelfCall, ErrZeroCodeContract, ErrUnsupportedInterface } from "./CommonErrors.sol"; abstract contract IdentityGuard { using AddressArrayUtils for address[]; /// @dev value is equal to keccak256(abi.encode()) /// @dev see: https://eips.ethereum.org/EIPS/eip-1052 bytes32 internal constant CREATED_ACCOUNT_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; /** * @dev Modifier to restrict functions to only be called by this contract. * @dev Reverts if the caller is not this contract. */ modifier onlySelfCall() virtual { _requireSelfCall(); _; } /** * @dev Modifier to ensure that the elements in the `arr` array are non-duplicates. * It calls the internal `_checkDuplicate` function to perform the duplicate check. * * Requirements: * - The elements in the `arr` array must not contain any duplicates. */ modifier nonDuplicate(address[] memory arr) virtual { _requireNonDuplicate(arr); _; } /** * @dev Internal method to check the method caller. * @dev Reverts if the method caller is not this contract. */ function _requireSelfCall() internal view virtual { if (msg.sender != address(this)) revert ErrOnlySelfCall(msg.sig); } /** * @dev Internal function to check if a contract address has code. * @param addr The address of the contract to check. * @dev Throws an error if the contract address has no code. */ function _requireHasCode(address addr) internal view { if (addr.code.length == 0) revert ErrZeroCodeContract(addr); } /** * @dev Checks if an address is zero and reverts if it is. * @param addr The address to check. */ function _requireNonZeroAddress(address addr) internal pure { if (addr == address(0)) revert ErrZeroAddress(msg.sig); } /** * @dev Check if arr is empty and revert if it is. * Checks if an array contains any duplicate addresses and reverts if duplicates are found. * @param arr The array of addresses to check. */ function _requireNonDuplicate(address[] memory arr) internal pure { if (arr.hasDuplicate()) revert AddressArrayUtils.ErrDuplicated(msg.sig); } /** * @dev Internal function to require that the provided address is a created externally owned account (EOA). * This internal function is used to ensure that the provided address is a valid externally owned account (EOA). * It checks the codehash of the address against a predefined constant to confirm that the address is a created EOA. * @notice This method only works with non-state EOA accounts */ function _requireCreatedEOA(address addr) internal view { _requireNonZeroAddress(addr); bytes32 codehash = addr.codehash; if (codehash != CREATED_ACCOUNT_HASH) revert ErrAddressIsNotCreatedEOA(addr, codehash); } /** * @dev Internal function to require that the specified contract supports the given interface. This method handle in * both case that the callee is either or not the proxy admin of the caller. If the contract does not support the * interface `interfaceId` or EIP165, a revert with the corresponding error message is triggered. * * @param contractAddr The address of the contract to check for interface support. * @param interfaceId The interface ID to check for support. */ function _requireSupportsInterface(address contractAddr, bytes4 interfaceId) internal view { bytes memory supportsInterfaceParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId)); (bool success, bytes memory returnOrRevertData) = contractAddr.staticcall(supportsInterfaceParams); if (!success) { (success, returnOrRevertData) = contractAddr.staticcall( abi.encodeCall(TransparentUpgradeableProxyV2.functionDelegateCall, (supportsInterfaceParams)) ); if (!success) revert ErrUnsupportedInterface(interfaceId, contractAddr); } if (!abi.decode(returnOrRevertData, (bool))) revert ErrUnsupportedInterface(interfaceId, contractAddr); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; enum RoleAccess { /* 0 */ UNKNOWN, /* 1 */ ADMIN, /* 2 */ COINBASE, /* 3 */ GOVERNOR, /* 4 */ CANDIDATE_ADMIN, /* 5 */ WITHDRAWAL_MIGRATOR, /* 6 */ __DEPRECATED_BRIDGE_OPERATOR, /* 7 */ BLOCK_PRODUCER, /* 8 */ VALIDATOR_CANDIDATE, /* 9 */ CONSENSUS, /* 10 */ TREASURY }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"},{"internalType":"uint256","name":"denom","type":"uint256"},{"internalType":"uint256","name":"roninChainId","type":"uint256"},{"internalType":"address","name":"bridgeContract","type":"address"},{"internalType":"address[]","name":"callbackRegisters","type":"address[]"},{"internalType":"address[]","name":"bridgeOperators","type":"address[]"},{"internalType":"address[]","name":"governors","type":"address[]"},{"internalType":"uint96[]","name":"voteWeights","type":"uint96[]"},{"internalType":"enum GlobalProposal.TargetOption[]","name":"targetOptions","type":"uint8[]"},{"internalType":"address[]","name":"targets","type":"address[]"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"bridgeOperator","type":"address"}],"name":"ErrBridgeOperatorAlreadyExisted","type":"error"},{"inputs":[{"internalType":"address","name":"bridgeOperator","type":"address"}],"name":"ErrBridgeOperatorUpdateFailed","type":"error"},{"inputs":[{"internalType":"enum ContractType","name":"contractType","type":"uint8"}],"name":"ErrContractTypeNotFound","type":"error"},{"inputs":[],"name":"ErrCurrentProposalIsNotCompleted","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrDuplicated","type":"error"},{"inputs":[{"internalType":"bytes32","name":"proposalHash","type":"bytes32"}],"name":"ErrInsufficientGas","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrInvalidArguments","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"},{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"ErrInvalidChainId","type":"error"},{"inputs":[],"name":"ErrInvalidExpiryTimestamp","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrInvalidOrder","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrInvalidProposalNonce","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrInvalidThreshold","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrInvalidVoteWeight","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrLengthMismatch","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrOnlySelfCall","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrRelayFailed","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"},{"internalType":"enum RoleAccess","name":"expectedRole","type":"uint8"}],"name":"ErrUnauthorized","type":"error"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"},{"internalType":"address","name":"addr","type":"address"}],"name":"ErrUnsupportedInterface","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrUnsupportedVoteType","type":"error"},{"inputs":[],"name":"ErrVoteIsFinalized","type":"error"},{"inputs":[{"internalType":"bytes4","name":"msgSig","type":"bytes4"}],"name":"ErrZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"ErrZeroCodeContract","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"governor","type":"address"},{"indexed":true,"internalType":"address","name":"fromBridgeOperator","type":"address"},{"indexed":true,"internalType":"address","name":"toBridgeOperator","type":"address"}],"name":"BridgeOperatorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool[]","name":"statuses","type":"bool[]"},{"indexed":false,"internalType":"uint96[]","name":"voteWeights","type":"uint96[]"},{"indexed":false,"internalType":"address[]","name":"governors","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"bridgeOperators","type":"address[]"}],"name":"BridgeOperatorsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool[]","name":"statuses","type":"bool[]"},{"indexed":false,"internalType":"address[]","name":"bridgeOperators","type":"address[]"}],"name":"BridgeOperatorsRemoved","type":"event"},{"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":true,"internalType":"uint256","name":"round","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"proposalHash","type":"bytes32"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"uint256[]","name":"gasAmounts","type":"uint256[]"}],"indexed":false,"internalType":"struct Proposal.ProposalDetail","name":"proposal","type":"tuple"},{"indexed":false,"internalType":"bytes32","name":"globalProposalHash","type":"bytes32"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"},{"internalType":"enum GlobalProposal.TargetOption[]","name":"targetOptions","type":"uint8[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"uint256[]","name":"gasAmounts","type":"uint256[]"}],"indexed":false,"internalType":"struct GlobalProposal.GlobalProposalDetail","name":"globalProposal","type":"tuple"},{"indexed":false,"internalType":"address","name":"creator","type":"address"}],"name":"GlobalProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"callData","type":"bytes"},{"indexed":false,"internalType":"address[]","name":"registers","type":"address[]"},{"indexed":false,"internalType":"bool[]","name":"statuses","type":"bool[]"},{"indexed":false,"internalType":"bytes[]","name":"returnDatas","type":"bytes[]"}],"name":"Notified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"proposalHash","type":"bytes32"}],"name":"ProposalApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"round","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"proposalHash","type":"bytes32"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"uint256[]","name":"gasAmounts","type":"uint256[]"}],"indexed":false,"internalType":"struct Proposal.ProposalDetail","name":"proposal","type":"tuple"},{"indexed":false,"internalType":"address","name":"creator","type":"address"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"proposalHash","type":"bytes32"},{"indexed":false,"internalType":"bool[]","name":"successCalls","type":"bool[]"},{"indexed":false,"internalType":"bytes[]","name":"returnDatas","type":"bytes[]"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"proposalHash","type":"bytes32"}],"name":"ProposalExpired","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"ProposalExpiryDurationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"proposalHash","type":"bytes32"}],"name":"ProposalRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"proposalHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"enum Ballot.VoteType","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"ProposalVoted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum GlobalProposal.TargetOption","name":"targetOption","type":"uint8"},{"indexed":true,"internalType":"address","name":"addr","type":"address"}],"name":"TargetOptionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"numerator","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"denominator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"previousNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"previousDenominator","type":"uint256"}],"name":"ThresholdUpdated","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96[]","name":"voteWeights","type":"uint96[]"},{"internalType":"address[]","name":"governors","type":"address[]"},{"internalType":"address[]","name":"bridgeOperators","type":"address[]"}],"name":"addBridgeOperators","outputs":[{"internalType":"bool[]","name":"addeds","type":"bool[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_voteWeight","type":"uint256"}],"name":"checkThreshold","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"governors","type":"address[]"}],"name":"getBridgeOperatorOf","outputs":[{"internalType":"address[]","name":"bridgeOperators","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bridgeOperator","type":"address"}],"name":"getBridgeOperatorWeight","outputs":[{"internalType":"uint96","name":"weight","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBridgeOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCallbackRegisters","outputs":[{"internalType":"address[]","name":"registers","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ContractType","name":"contractType","type":"uint8"}],"name":"getContract","outputs":[{"internalType":"address","name":"contract_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFullBridgeOperatorInfos","outputs":[{"internalType":"address[]","name":"governors","type":"address[]"},{"internalType":"address[]","name":"bridgeOperators","type":"address[]"},{"internalType":"uint96[]","name":"weights","type":"uint96[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"getGovernorWeight","outputs":[{"internalType":"uint96","name":"weight","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"governors","type":"address[]"}],"name":"getGovernorWeights","outputs":[{"internalType":"uint96[]","name":"weights","type":"uint96[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGovernors","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"bridgeOperators","type":"address[]"}],"name":"getGovernorsOf","outputs":[{"internalType":"address[]","name":"governors","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProposalExpiryDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getThreshold","outputs":[{"internalType":"uint256","name":"num_","type":"uint256"},{"internalType":"uint256","name":"denom_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"globalProposalRelayed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isBridgeOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumVoteWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"registers","type":"address[]"}],"name":"registerCallbacks","outputs":[{"internalType":"bool[]","name":"registereds","type":"bool[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"},{"internalType":"enum GlobalProposal.TargetOption[]","name":"targetOptions","type":"uint8[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"uint256[]","name":"gasAmounts","type":"uint256[]"}],"internalType":"struct GlobalProposal.GlobalProposalDetail","name":"globalProposal","type":"tuple"},{"internalType":"enum Ballot.VoteType[]","name":"supports_","type":"uint8[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureConsumer.Signature[]","name":"signatures","type":"tuple[]"}],"name":"relayGlobalProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"uint256[]","name":"gasAmounts","type":"uint256[]"}],"internalType":"struct Proposal.ProposalDetail","name":"proposal","type":"tuple"},{"internalType":"enum Ballot.VoteType[]","name":"supports_","type":"uint8[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureConsumer.Signature[]","name":"signatures","type":"tuple[]"}],"name":"relayProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"bridgeOperators","type":"address[]"}],"name":"removeBridgeOperators","outputs":[{"internalType":"bool[]","name":"removeds","type":"bool[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum GlobalProposal.TargetOption[]","name":"targetOptions","type":"uint8[]"}],"name":"resolveTargets","outputs":[{"internalType":"address[]","name":"targets","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"round","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"setThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"governors","type":"address[]"}],"name":"sumGovernorsWeight","outputs":[{"internalType":"uint256","name":"sum","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBridgeOperator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"registers","type":"address[]"}],"name":"unregisterCallbacks","outputs":[{"internalType":"bool[]","name":"unregistereds","type":"bool[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newBridgeOperator","type":"address"}],"name":"updateBridgeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum GlobalProposal.TargetOption[]","name":"targetOptions","type":"uint8[]"},{"internalType":"address[]","name":"targets","type":"address[]"}],"name":"updateManyTargetOption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"vote","outputs":[{"internalType":"enum VoteStatusConsumer.VoteStatus","name":"status","type":"uint8"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"againstVoteWeight","type":"uint256"},{"internalType":"uint256","name":"forVoteWeight","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040526040516200668038038062006680833981016040819052620000269162001625565b8181600160ff1b8c8c8c8c8c8c8c8c836200004181620001bd565b50506200007060016000805160206200666083398151915260001b620002da60201b62000ed61790919060201c565b6200007c8888620002de565b506200008c90506002866200044e565b604080516020808201839052600c60608301526b212924a223a2afa0a226a4a760a11b6080808401919091528284018a905283518084038201815260a0840185528051908301207f599a80fcaa47b95e2323ab4d34d34e0cc9feda4b843edafcc30c7bdf60ea15bf60c08501527f9d3fa1662ea89365eb7af36506f0ad5413bd7e078960d8481ff4718763aaa8e960e08501527fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a561010085015261012080850191909152845180850390910181526101409093019093528151910120905262000177818385620004f8565b50505050505050505062000191816200098b60201b60201c565b506200019f600030620009be565b620001ab828262000a5a565b50505050505050505050505062001a6e565b606081620001cb8162000b1d565b8251806001600160401b03811115620001e857620001e862001444565b60405190808252806020026020018201604052801562000212578160200160208202803683370190505b50925080600003620002255750620002d4565b6000805160206200662083398151915260006314d72edb60e21b815b84811015620002ce578781815181106200025f576200025f62001760565b602002602001015192506200027a8362000b6460201b60201c565b62000286838362000b9c565b620002a0838562000d7b60201b62000eda1790919060201c565b878281518110620002b557620002b562001760565b9115156020928302919091019091015260010162000241565b50505050505b50919050565b9055565b6000808284111562000316576040516387f6f09560e01b81526001600160e01b03196000351660048201526024015b60405180910390fd5b6200033e6000805160206200664083398151915260001b62000d9b60201b62000eef1760201c565b9150620003797fac1ff16a4f04f2a37a9ba5252a69baa100b460e517d1f8019c054a5ad698f9ff60001b62000d9b60201b62000eef1760201c565b9050620003a7846000805160206200664083398151915260001b620002da60201b62000ed61790919060201c565b620003e4837fac1ff16a4f04f2a37a9ba5252a69baa100b460e517d1f8019c054a5ad698f9ff60001b620002da60201b62000ed61790919060201c565b82846200040e6000805160206200666083398151915260001b62000d9f60201b62000ef31760201c565b60408051868152602081018690527f976f8a9c5bdf8248dec172376d6e2b80a8e3df2f0328e381c6db8e1cf138c0f8910160405180910390a49250929050565b807fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600084600f81111562000487576200048762001776565b60ff168152602081019190915260400160002080546001600160a01b0319166001600160a01b03928316179055811682600f811115620004cb57620004cb62001776565b6040517f865d1c228a8ea13709cfe61f346f7ff67f1bbd4a18ff31ad3e7147350d317c5990600090a35050565b606062000514828462000dc360201b62000f0e1790919060201c565b6200051f8162000b1d565b8251855181148015620005325750845181145b6200055f576040516306b5667560e21b81526001600160e01b03196000351660048201526024016200030d565b806001600160401b038111156200057a576200057a62001444565b604051908082528060200260200182016040528015620005a4578160200160208202803683370190505b50925080600003620005b7575062000983565b604080518082019091526000808252602082018190527f546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c917f8400683eb2cb350596d73644c0c89fe45f108600003457374f4ab3e87b4f3aa3917fd38c234075fde25875da8a6b7e36b58b86681d483271a99eeeee1d78e258a24d917f88547008e60f5748911f2e59feb3093b7e4c2e87b2dd69d61f112fcc932de8e3919081908190815b89811015620008c4578d81815181106200067a576200067a62001760565b602002602001015194508c818151811062000699576200069962001760565b60200260200101519350620006b48562000ee160201b60201c565b620006bf8462000ee1565b8e8181518110620006d457620006d462001760565b60200260200101516001600160601b03166000036200071557604051637f11b8a360e11b81526001600160e01b03196000351660048201526024016200030d565b6200072f858a62000f1860201b620010181790919060201c565b8062000750575062000750848a62000f1860201b620010181790919060201c565b8062000771575062000771858862000f1860201b620010181790919060201c565b8062000792575062000792848862000f1860201b620010181790919060201c565b158c8281518110620007a857620007a862001760565b6020026020010190151590811515815250508b8181518110620007cf57620007cf62001760565b602002602001015115620008bb57620007f7858a62000d7b60201b62000eda1790919060201c565b5062000812848862000d7b60201b62000eda1790919060201c565b506001600160a01b03848116600081815260208b90526040902080546001600160a01b0319169288169290921790915582528e518f90829081106200085b576200085b62001760565b6020908102919091018101516001600160601b03169083018190526200088290846200178c565b6001600160a01b038087166000908152602089815260409091208551918601516001600160601b0316600160a01b029190921617905592505b6001016200065c565b5062000902827f6924fe71b0c8b61aea02ca498b5f53b29bd95726278b1fe4eb791bb24a42644c60001b62000f3b60201b6200103a1790919060201c565b506200093a635ebae8a060e01b8d8d6040516020016200092492919062001828565b60408051601f1981840301815291905262000f55565b7f897810999654e525e272b5909785c4d0ceaee1bbf9c87d9091a37558b0423b788b8f8f8f6040516200097194939291906200185a565b60405180910390a15050505050505050505b509392505050565b600281905560405181907fe5cd1c123a8cf63fa1b7229678db61fe8ae99dbbd27889370b6667c8cae97da190600090a250565b8060036000846004811115620009d857620009d862001776565b6004811115620009ec57620009ec62001776565b8152602081019190915260400160002080546001600160a01b0319166001600160a01b03928316179055811682600481111562000a2d5762000a2d62001776565b6040517f356c8c57e9e84b99b1cb58b13c985b2c979f78cbdf4d0fa70fe2a98bb09a099d90600090a35050565b60005b825181101562000b1857306001600160a01b031682828151811062000a865762000a8662001760565b60200260200101516001600160a01b03160362000ac55760405163053265f160e01b81526001600160e01b03196000351660048201526024016200030d565b62000b0f83828151811062000ade5762000ade62001760565b602002602001015183838151811062000afb5762000afb62001760565b6020026020010151620009be60201b60201c565b60010162000a5d565b505050565b62000b33816200129b60201b620010511760201c565b1562000b6157604051630d697db160e11b81526001600160e01b03196000351660048201526024016200030d565b50565b806001600160a01b03163b60000362000b6157604051630bfc64a360e21b81526001600160a01b03821660048201526024016200030d565b6040516001600160e01b03198216602482015260009060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b1790525190915060009081906001600160a01b0386169062000c0090859062001910565b600060405180830381855afa9150503d806000811462000c3d576040519150601f19603f3d011682016040523d82523d6000602084013e62000c42565b606091505b50915091508162000d2457846001600160a01b03168360405160240162000c6a91906200195c565b60408051601f198184030181529181526020820180516001600160e01b03166325da93a560e11b1790525162000ca1919062001910565b600060405180830381855afa9150503d806000811462000cde576040519150601f19603f3d011682016040523d82523d6000602084013e62000ce3565b606091505b5090925090508162000d245760405163069d427960e11b81526001600160e01b0319851660048201526001600160a01b03861660248201526044016200030d565b8080602001905181019062000d3a919062001971565b62000d745760405163069d427960e11b81526001600160e01b0319851660048201526001600160a01b03861660248201526044016200030d565b5050505050565b600062000d92836001600160a01b03841662001346565b90505b92915050565b5490565b600062000daa825490565b905062000dbe82620002da8360016200178c565b919050565b81518151606091908082016001600160401b0381111562000de85762000de862001444565b60405190808252806020026020018201604052801562000e12578160200160208202803683370190505b50925060005b8281101562000e745785818151811062000e365762000e3662001760565b602002602001015184828151811062000e535762000e5362001760565b6001600160a01b039092166020928302919091019091015260010162000e18565b60005b8281101562000ed75785818151811062000e955762000e9562001760565b602002602001015185838151811062000eb25762000eb262001760565b6001600160a01b03909216602092830291909101909101526001918201910162000e77565b5050505092915050565b6001600160a01b03811662000b615760405163104c66df60e31b81526001600160e01b03196000351660048201526024016200030d565b6001600160a01b0381166000908152600183016020526040812054151562000d92565b600062000d958362000f4e818562001398565b9250829055565b600062000f7c60008051602062006620833981519152620013b860201b620010f01760201c565b8051909150600081900362000f915750505050565b6000816001600160401b0381111562000fae5762000fae62001444565b60405190808252806020026020018201604052801562000fd8578160200160208202803683370190505b5090506000826001600160401b0381111562000ff85762000ff862001444565b6040519080825280602002602001820160405280156200102d57816020015b6060815260200190600190039081620010175790505b509050600086866040516020016200104792919062001995565b60405160208183030381529060405290506000816040516024016200106d91906200195c565b60408051601f198184030181529190526020810180516001600160e01b03166325da93a560e11b179052905060005b858110156200125157868181518110620010ba57620010ba62001760565b60200260200101516001600160a01b031683604051620010db919062001910565b6000604051808303816000865af19150503d80600081146200111a576040519150601f19603f3d011682016040523d82523d6000602084013e6200111f565b606091505b5086838151811062001135576200113562001760565b6020026020010186848151811062001151576200115162001760565b60200260200101829052821515151581525050508481815181106200117a576200117a62001760565b602002602001015162001248578681815181106200119c576200119c62001760565b60200260200101516001600160a01b031682604051620011bd919062001910565b6000604051808303816000865af19150503d8060008114620011fc576040519150601f19603f3d011682016040523d82523d6000602084013e62001201565b606091505b5086838151811062001217576200121762001760565b6020026020010186848151811062001233576200123362001760565b60200260200101829052821515151581525050505b6001016200109c565b507fc0b07a27e66788f39cc91405f012f34066b16f31b4bda9438c52f2dae0cc5b6382878686604051620012899493929190620019c8565b60405180910390a15050505050505050565b60008151600003620012af57506000919050565b60005b60018351038110156200133d57600181015b83518110156200133357838181518110620012e357620012e362001760565b60200260200101516001600160a01b031684838151811062001309576200130962001760565b60200260200101516001600160a01b0316036200132a575060019392505050565b600101620012c4565b50600101620012b2565b50600092915050565b60008181526001830160205260408120546200138f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000d95565b50600062000d95565b815481018181101562000d9557634e487b7160005260116020526024601cfd5b60606000620013c783620013ce565b9392505050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156200142057602002820191906000526020600020905b8154815260200190600101908083116200140b575b50505050509050919050565b80516001600160a01b038116811462000dbe57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562001485576200148562001444565b604052919050565b60006001600160401b03821115620014a957620014a962001444565b5060051b60200190565b600082601f830112620014c557600080fd5b81516020620014de620014d8836200148d565b6200145a565b82815260059290921b84018101918181019086841115620014fe57600080fd5b8286015b84811015620015245762001516816200142c565b835291830191830162001502565b509695505050505050565b600082601f8301126200154157600080fd5b8151602062001554620014d8836200148d565b82815260059290921b840181019181810190868411156200157457600080fd5b8286015b84811015620015245780516001600160601b03811681146200159a5760008081fd5b835291830191830162001578565b600082601f830112620015ba57600080fd5b81516020620015cd620014d8836200148d565b828152600592831b8501820192828201919087851115620015ed57600080fd5b8387015b85811015620016185780518281106200160a5760008081fd5b8452928401928401620015f1565b5090979650505050505050565b6000806000806000806000806000806101408b8d0312156200164657600080fd5b8a51995060208b0151985060408b015197506200166660608c016200142c565b60808c01519097506001600160401b03808211156200168457600080fd5b620016928e838f01620014b3565b975060a08d0151915080821115620016a957600080fd5b620016b78e838f01620014b3565b965060c08d0151915080821115620016ce57600080fd5b620016dc8e838f01620014b3565b955060e08d0151915080821115620016f357600080fd5b620017018e838f016200152f565b94506101008d01519150808211156200171957600080fd5b620017278e838f01620015a8565b93506101208d01519150808211156200173f57600080fd5b506200174e8d828e01620014b3565b9150509295989b9194979a5092959850565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b8082018082111562000d9557634e487b7160e01b600052601160045260246000fd5b600081518084526020808501945080840160005b83811015620017e95781516001600160a01b031687529582019590820190600101620017c2565b509495945050505050565b600081518084526020808501945080840160005b83811015620017e957815115158752958201959082019060010162001808565b6040815260006200183d6040830185620017ae565b8281036020840152620018518185620017f4565b95945050505050565b6080815260006200186f6080830187620017f4565b82810360208481019190915286518083528782019282019060005b81811015620018b15784516001600160601b0316835293830193918301916001016200188a565b50508481036040860152620018c78188620017ae565b925050508281036060840152620018df8185620017ae565b979650505050505050565b60005b8381101562001907578181015183820152602001620018ed565b50506000910152565b6000825162001924818460208701620018ea565b9190910192915050565b6000815180845262001948816020860160208601620018ea565b601f01601f19169290920160200192915050565b60208152600062000d9260208301846200192e565b6000602082840312156200198457600080fd5b81518015158114620013c757600080fd5b6001600160e01b0319831681528151600090620019ba816004850160208701620018ea565b919091016004019392505050565b608081526000620019dd60808301876200192e565b602083820381850152620019f28288620017ae565b9150838203604085015262001a088287620017f4565b915083820360608501528185518084528284019150828160051b85010183880160005b8381101562001a5d57601f1987840301855262001a4a8383516200192e565b9486019492509085019060010162001a2b565b50909b9a5050505050505050505050565b608051614b8862001a98600039600081816102c5015281816107c501526108510152614b886000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80639b19dbfd1161011a578063cc7e6b3b116100ad578063de981f1b1161007c578063de981f1b1461050c578063e75235b814610537578063e9c034981461053f578063f80b535214610552578063fdc4fa471461055a57600080fd5b8063cc7e6b3b146104be578063d0a50db0146104de578063d78392f8146104e6578063dafae408146104f957600080fd5b8063b9c36209116100e9578063b9c3620914610464578063bc9182fd1461048c578063bc96180b1461049f578063c441c4a8146104a757600080fd5b80639b19dbfd146103db5780639b2ee437146103e3578063b384abef146103f6578063b405aaf21461045157600080fd5b80633644e515116101925780637de5dedd116101615780637de5dedd14610332578063800eaab31461033a578063865e6fd31461034d578063901979d51461036057600080fd5b80633644e515146102c05780635e05cf9e146102e7578063776fb1ec146102fc5780637d465f791461031f57600080fd5b80631f425338116101ce5780631f425338146102675780632d6d7d731461027a57806334d5f37b1461028d57806335da8121146102ad57600080fd5b806301a5f43f1461020057806306aba0e1146102295780630a44fa431461023f5780630f7c318914610252575b600080fd5b61021361020e366004613b7d565b61056d565b6040516102209190613c53565b60405180910390f35b610231610620565b604051908152602001610220565b61023161024d366004613c66565b61063d565b61025a6106c2565b6040516102209190613ce0565b610213610275366004613c66565b6106db565b61025a610288366004613c66565b610728565b61023161029b366004613cf3565b60006020819052908152604090205481565b6102136102bb366004613c66565b61076c565b6102317f000000000000000000000000000000000000000000000000000000000000000081565b6102fa6102f5366004613d50565b6107b2565b005b61030f61030a366004613cf3565b6107f1565b6040519015158152602001610220565b6102fa61032d366004613dec565b61083e565b610231610876565b6102fa610348366004613fe0565b6108f2565b6102fa61035b366004614052565b610937565b6103c361036e366004614085565b6001600160a01b039081166000908152600080516020614af383398151915260209081526040808320549093168252600080516020614ad383398151915290522054600160a01b90046001600160601b031690565b6040516001600160601b039091168152602001610220565b61025a610952565b6102fa6103f1366004614085565b61095c565b6104406104043660046140a0565b600160208181526000938452604080852090915291835291208054918101546002820154600383015460069093015460ff909416939192909185565b6040516102209594939291906140e8565b61030f61045f366004614085565b610af3565b6104776104723660046140a0565b610b0d565b60408051928352602083019190915201610220565b61025a61049a366004614116565b610b2e565b610231610c1f565b6104af610c2a565b60405161022093929190614183565b6104d16104cc366004613c66565b610c54565b60405161022091906141c6565b610231610c92565b6103c36104f4366004614085565b610cab565b61030f610507366004613cf3565b610cb6565b61051f61051a3660046141d9565b610cf3565b6040516001600160a01b039091168152602001610220565b610477610d6e565b61021361054d366004613c66565b610d9f565b61025a610de5565b61025a610568366004613c66565b610def565b60606105776110fd565b61061587878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a92508991829185019084908082843760009201919091525050604080516020808a0282810182019093528982529093508992508891829185019084908082843760009201919091525061112d92505050565b979650505050505050565b6000610638600080516020614b338339815191525490565b905090565b600082828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061067e92508391506114a99050565b6106ba8484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506114e192505050565b949350505050565b6060610638600080516020614a738339815191526110f0565b60606106e56110fd565b61072183838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061156592505050565b9392505050565b606061072183838080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509250611630915050565b92915050565b60606107766110fd565b61072183838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061178a92505050565b6107bb3361187c565b6107ea85858585857f0000000000000000000000000000000000000000000000000000000000000000336118be565b5050505050565b60008060008381527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602052604090205460ff166004811115610836576108366140c2565b141592915050565b6108473361187c565b6107ea85858585857f000000000000000000000000000000000000000000000000000000000000000033611963565b600061088e600080516020614a938339815191525490565b60016108a6600080516020614a938339815191525490565b6108d46108bf600080516020614b338339815191525490565b600080516020614ab3833981519152906119bf565b6108de919061420a565b6108e8919061421d565b6106389190614230565b333014610929576000356001600160e01b0319166040516307337e1960e41b81526004016109209190614252565b60405180910390fd5b61093382826119ea565b5050565b61093f6110fd565b61094881611a98565b6109338282611ace565b6060610638611b72565b6109653361187c565b61096e81611b8b565b336000908152600080516020614ad383398151915260208190526040909120546001600160a01b0390811690831681036109c657604051630669b93360e31b81526001600160a01b0384166004820152602401610920565b600080516020614b1383398151915260006109e18284611bc0565b80156109f257506109f28286610eda565b905080610a1d5760405163080fab4b60e31b81526001600160a01b0386166004820152602401610920565b6001600160a01b038381166000818152600080516020614af38339815191526020818152604080842080546001600160a01b0319908116909155958b16808552818520805488163390811790915585528a8352938190208054909616841790955584519081019390935292820152610ab0906364b18d0960e11b906060015b604051602081830303815290604052611bd5565b6040516001600160a01b03808816919086169033907fcef34cd748f30a1b7a2f214fd1651779f79bc6c1be02785cad5c1f0ee877213d90600090a4505050505050565b6000610766600080516020614b1383398151915283611018565b600080610b186110fd565b610b228484611edd565b915091505b9250929050565b8051606090806001600160401b03811115610b4b57610b4b613e2f565b604051908082528060200260200182016040528015610b74578160200160208202803683370190505b509150600080516020614ad383398151915260005b82811015610c1757816000868381518110610ba657610ba6614267565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a90046001600160a01b0316848281518110610bf757610bf7614267565b6001600160a01b0390921660209283029190910190910152600101610b89565b505050919050565b600061063860025490565b6060806060610c37611fd2565b9250610c4283610b2e565b9150610c4d83611ffd565b9050909192565b6060610721838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611ffd92505050565b6000610638600080516020614b138339815191526120e6565b6000610766826120f0565b6000610cd16108bf600080516020614b338339815191525490565b600080516020614a9383398151915254610ceb908461427d565b101592915050565b60007fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600083600f811115610d2a57610d2a6140c2565b60ff1681526020810191909152604001600020546001600160a01b0316905080610d69578160405163409140df60e11b81526004016109209190614294565b919050565b600080610d87600080516020614ab38339815191525490565b600080516020614a9383398151915254915091509091565b6060610da96110fd565b61072183838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061212892505050565b6060610638611fd2565b606081806001600160401b03811115610e0a57610e0a613e2f565b604051908082528060200260200182016040528015610e33578160200160208202803683370190505b509150600080516020614af383398151915260005b82811015610ecd57816000878784818110610e6557610e65614267565b9050602002016020810190610e7a9190614085565b6001600160a01b0390811682526020820192909252604001600020548551911690859083908110610ead57610ead614267565b6001600160a01b0390921660209283029190910190910152600101610e48565b50505092915050565b9055565b6000610721836001600160a01b03841661240d565b5490565b6000610efd825490565b9050610d6982610ed683600161420a565b81518151606091908082016001600160401b03811115610f3057610f30613e2f565b604051908082528060200260200182016040528015610f59578160200160208202803683370190505b50925060005b82811015610fb357858181518110610f7957610f79614267565b6020026020010151848281518110610f9357610f93614267565b6001600160a01b0390921660209283029190910190910152600101610f5f565b60005b8281101561100e57858181518110610fd057610fd0614267565b6020026020010151858381518110610fea57610fea614267565b6001600160a01b039092166020928302919091019091015260019182019101610fb6565b5050505092915050565b6001600160a01b03811660009081526001830160205260408120541515610721565b60006107668361104a858561245c565b9250829055565b6000815160000361106457506000919050565b60005b60018351038110156110e757600181015b83518110156110de5783818151811061109357611093614267565b60200260200101516001600160a01b03168483815181106110b6576110b6614267565b60200260200101516001600160a01b0316036110d6575060019392505050565b600101611078565b50600101611067565b50600092915050565b606060006107218361247b565b33301461112b576000356001600160e01b0319166040516307337e1960e41b81526004016109209190614252565b565b60606111398383610f0e565b611142816114a9565b82518551811480156111545750845181145b61117f576000356001600160e01b0319166040516306b5667560e21b81526004016109209190614252565b806001600160401b0381111561119757611197613e2f565b6040519080825280602002602001820160405280156111c0578160200160208202803683370190505b509250806000036111d157506114a1565b604080518082019091526000808252602082018190527f546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c91600080516020614af383398151915291600080516020614b1383398151915291600080516020614ad3833981519152919081908190815b89811015611422578d818151811061125a5761125a614267565b602002602001015194508c818151811061127657611276614267565b6020026020010151935061128985611b8b565b61129284611b8b565b8e81815181106112a4576112a4614267565b60200260200101516001600160601b03166000036112e3576000356001600160e01b031916604051637f11b8a360e11b81526004016109209190614252565b6112ed8986611018565b806112fd57506112fd8985611018565b8061130d575061130d8786611018565b8061131d575061131d8785611018565b158c828151811061133057611330614267565b6020026020010190151590811515815250508b818151811061135457611354614267565b60200260200101511561141a5761136b8986610eda565b506113768785610eda565b506001600160a01b03848116600081815260208b90526040902080546001600160a01b0319169288169290921790915582528e518f90829081106113bc576113bc614267565b6020908102919091018101516001600160601b03169083018190526113e1908461420a565b6001600160a01b038087166000908152602089815260409091208551918601516001600160601b0316600160a01b029190921617905592505b600101611240565b5061143b600080516020614b338339815191528361103a565b5061145a635ebae8a060e01b8d8d604051602001610a9c9291906142ae565b7f897810999654e525e272b5909785c4d0ceaee1bbf9c87d9091a37558b0423b788b8f8f8f60405161148f94939291906142dc565b60405180910390a15050505050505050505b509392505050565b6114b281611051565b156114de576000356001600160e01b031916604051630d697db160e11b81526004016109209190614252565b50565b6000816114ed816114a9565b600080516020614ad383398151915260005b8451811015610c175781600086838151811061151d5761151d614267565b6020908102919091018101516001600160a01b031682528101919091526040016000205461155b90600160a01b90046001600160601b03168561420a565b93506001016114ff565b606081611571816114a9565b8251806001600160401b0381111561158b5761158b613e2f565b6040519080825280602002602001820160405280156115b4578160200160208202803683370190505b509250600080516020614a7383398151915260005b82811015611627576115fd8682815181106115e6576115e6614267565b602002602001015183611bc090919063ffffffff16565b85828151811061160f5761160f614267565b911515602092830291909101909101526001016115c9565b50505050919050565b606082516001600160401b0381111561164b5761164b613e2f565b604051908082528060200260200182016040528015611674578160200160208202803683370190505b50905060005b8351811015611783576003600085838151811061169957611699614267565b602002602001015160048111156116b2576116b26140c2565b60048111156116c3576116c36140c2565b815260200190815260200160002060009054906101000a90046001600160a01b03168282815181106116f7576116f7614267565b60200260200101906001600160a01b031690816001600160a01b03168152505082801561174f575060006001600160a01b031682828151811061173c5761173c614267565b60200260200101516001600160a01b0316145b1561177b576000356001600160e01b03191660405163053265f160e01b81526004016109209190614252565b60010161167a565b5092915050565b606081611796816114a9565b8251806001600160401b038111156117b0576117b0613e2f565b6040519080825280602002602001820160405280156117d9578160200160208202803683370190505b509250806000036117ea5750611876565b600080516020614a7383398151915260006314d72edb60e21b815b848110156118705787818151811061181f5761181f614267565b6020026020010151925061183283611a98565b61183c83836124d7565b6118468484610eda565b87828151811061185857611858614267565b91151560209283029190910190910152600101611805565b50505050505b50919050565b611885816120f0565b6001600160601b03166000036114de576000356001600160e01b0319166003604051620f948f60ea1b8152600401610920929190614329565b6118d06118ca88614495565b8261266a565b5060006118e46118df89614495565b612770565b90506119596118f289614495565b88888888611945896119058960006128af565b60405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6119548a6119058a60016128af565b6128e8565b5050505050505050565b600061197761197189614569565b83612cdf565b9050600061198c6119878a614569565b612e29565b90506119b482898989896119a58a6119058960006128af565b6119548b6119058a60016128af565b505050505050505050565b600082548015611783578281029150808204831461178357634e487b7160005260116020526024601cfd5b60005b8251811015611a9357306001600160a01b0316828281518110611a1257611a12614267565b60200260200101516001600160a01b031603611a4f576000356001600160e01b03191660405163053265f160e01b81526004016109209190614252565b611a8b838281518110611a6457611a64614267565b6020026020010151838381518110611a7e57611a7e614267565b6020026020010151612f60565b6001016119ed565b505050565b806001600160a01b03163b6000036114de57604051630bfc64a360e21b81526001600160a01b0382166004820152602401610920565b807fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600084600f811115611b0457611b046140c2565b60ff168152602081019190915260400160002080546001600160a01b0319166001600160a01b03928316179055811682600f811115611b4557611b456140c2565b6040517f865d1c228a8ea13709cfe61f346f7ff67f1bbd4a18ff31ad3e7147350d317c5990600090a35050565b6060610638600080516020614b138339815191526110f0565b6001600160a01b0381166114de576000356001600160e01b03191660405163104c66df60e31b81526004016109209190614252565b6000610721836001600160a01b038416612ff3565b6000611bee600080516020614a738339815191526110f0565b80519091506000819003611c025750505050565b6000816001600160401b03811115611c1c57611c1c613e2f565b604051908082528060200260200182016040528015611c45578160200160208202803683370190505b5090506000826001600160401b03811115611c6257611c62613e2f565b604051908082528060200260200182016040528015611c9557816020015b6060815260200190600190039081611c805790505b50905060008686604051602001611cad929190614657565b6040516020818303038152906040529050600081604051602401611cd191906146b4565b60408051601f198184030181529190526020810180516001600160e01b03166325da93a560e11b179052905060005b85811015611e9557868181518110611d1a57611d1a614267565b60200260200101516001600160a01b031683604051611d3991906146c7565b6000604051808303816000865af19150503d8060008114611d76576040519150601f19603f3d011682016040523d82523d6000602084013e611d7b565b606091505b50868381518110611d8e57611d8e614267565b60200260200101868481518110611da757611da7614267565b6020026020010182905282151515158152505050848181518110611dcd57611dcd614267565b6020026020010151611e8d57868181518110611deb57611deb614267565b60200260200101516001600160a01b031682604051611e0a91906146c7565b6000604051808303816000865af19150503d8060008114611e47576040519150601f19603f3d011682016040523d82523d6000602084013e611e4c565b606091505b50868381518110611e5f57611e5f614267565b60200260200101868481518110611e7857611e78614267565b60200260200101829052821515151581525050505b600101611d00565b507fc0b07a27e66788f39cc91405f012f34066b16f31b4bda9438c52f2dae0cc5b6382878686604051611ecb9493929190614728565b60405180910390a15050505050505050565b60008082841115611f0f576000356001600160e01b0319166040516387f6f09560e01b81526004016109209190614252565b600080516020614ab3833981519152549150611f37600080516020614a938339815191525490565b9050611f50600080516020614ab3833981519152859055565b611f67600080516020614a93833981519152849055565b8284611f927f92872d32822c9d44b36a2537d3e0d4c46fc4de1ce154ccfaed560a8a58445f1d610ef3565b60408051868152602081018690527f976f8a9c5bdf8248dec172376d6e2b80a8e3df2f0328e381c6db8e1cf138c0f8910160405180910390a49250929050565b60606106387f546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c6110f0565b8051606090806001600160401b0381111561201a5761201a613e2f565b604051908082528060200260200182016040528015612043578160200160208202803683370190505b509150600080516020614ad383398151915260005b82811015610c175781600086838151811061207557612075614267565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060000160149054906101000a90046001600160601b03168482815181106120c6576120c6614267565b6001600160601b0390921660209283029190910190910152600101612058565b6000610766825490565b6001600160a01b03166000908152600080516020614ad38339815191526020526040902054600160a01b90046001600160601b031690565b606081612134816114a9565b8251806001600160401b0381111561214e5761214e613e2f565b604051908082528060200260200182016040528015612177578160200160208202803683370190505b509250806000036121885750611876565b60408051808201909152600080825260208201819052600080516020614af3833981519152917f546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c91600080516020614b1383398151915291600080516020614ad3833981519152919081908190815b8981101561238d578c818151811061221157612211614267565b6020908102919091018101516001600160a01b038082166000908152928c90526040909220549091169550935061224785611b8b565b61225084611b8b565b6001600160a01b0385811660009081526020888152604091829020825180840190935254808416808452600160a01b9091046001600160601b031691830191909152909350908516146122c4576000356001600160e01b03191660405163053265f160e01b81526004016109209190614252565b6122ce8785611018565b80156122df57506122df8886611018565b8c82815181106122f1576122f1614267565b6020026020010190151590811515815250508b818151811061231557612315614267565b6020026020010151156123855761232c8886611bc0565b506123378785611bc0565b506001600160a01b03808516600090815260208b8152604080832080546001600160a01b0319169055928816825288815291812055820151612382906001600160601b03168461420a565b92505b6001016121f7565b506123a6600080516020614b33833981519152836130e6565b506123c563c48549de60e01b8d8d604051602001610a9c9291906142ae565b7fdf3dcd7987202f64648f3acdbf12401e3a2bb23e77e19f99826b5475cbb863698b8d6040516123f6929190614775565b60405180910390a150505050505050505050919050565b600081815260018301602052604081205461245457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610766565b506000610766565b815481018181101561076657634e487b7160005260116020526024601cfd5b6060816000018054806020026020016040519081016040528092919081815260200182805480156124cb57602002820191906000526020600020905b8154815260200190600101908083116124b7575b50505050509050919050565b6000816040516024016124ea9190614252565b60408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b1790525190915060009081906001600160a01b038616906125339085906146c7565b600060405180830381855afa9150503d806000811461256e576040519150601f19603f3d011682016040523d82523d6000602084013e612573565b606091505b50915091508161263557846001600160a01b03168360405160240161259891906146b4565b60408051601f198184030181529181526020820180516001600160e01b03166325da93a560e11b179052516125cd91906146c7565b600060405180830381855afa9150503d8060008114612608576040519150601f19603f3d011682016040523d82523d6000602084013e61260d565b606091505b5090925090508161263557838560405163069d427960e11b815260040161092092919061479a565b8080602001905181019061264991906147bd565b6107ea57838560405163069d427960e11b815260040161092092919061479a565b60208201516000908082036126ac5760405163092048d160e11b8152600080356001600160e01b03191660048301526024820152466044820152606401610920565b6002546126ba9085906130f6565b60006126c585612770565b90506126d082613197565b6000838152600160208181526040808420858552909152918290209188015190820184905560069091015592508451831461272c576000356001600160e01b03191660405163d4cec26960e01b81526004016109209190614252565b8083837fa57d40f1496988cf60ab7c9d5ba4ff83647f67d3898d441a3aaf21b651678fd988886040516127609291906148c9565b60405180910390a4505092915050565b6080810151606082015160a083015151600092919083906001600160401b0381111561279e5761279e613e2f565b6040519080825280602002602001820160405280156127c7578160200160208202803683370190505b5060c086015190915060005b8251811015612826578660a0015181815181106127f2576127f2614267565b60200260200101518051906020012083828151811061281357612813614267565b60209081029190910101526001016127d3565b50604080517fd051578048e6ff0bbc9fca3b65a42088dbde10f36ca841de566711087ad9b08a8152875160208083019190915280890151828401529790910151606082015283518702938701939093206080840152835186029386019390932060a0830152805185029085012060c082015281518402919093012060e083015250610100902090565b604080517fd900570327c4c0df8dd6bdd522b7da7e39145dd049d2fd4602276adcd511e3c2815260208101939093528201526060902090565b84158015906128f657508483145b612921576000356001600160e01b0319166040516306b5667560e21b81526004016109209190614252565b60008080856001600160401b0381111561293d5761293d613e2f565b604051908082528060200260200182016040528015612966578160200160208202803683370190505b5090506000866001600160401b0381111561298357612983613e2f565b6040519080825280602002602001820160405280156129ac578160200160208202803683370190505b50905060008060003660005b8b811015612b3d578c8c828181106129d2576129d2614267565b90506060020191508e8e828181106129ec576129ec614267565b9050602002016020810190612a0191906148f3565b92506000836001811115612a1757612a176140c2565b03612a8157612a3c8b612a2d6020850185614914565b84602001358560400135613233565b945084878a612a4a81614937565b9b5081518110612a5c57612a5c614267565b60200260200101906001600160a01b031690816001600160a01b031681525050612af2565b6001836001811115612a9557612a956140c2565b03612acb57612aab8a612a2d6020850185614914565b9450848689612ab981614937565b9a5081518110612a5c57612a5c614267565b6000356001600160e01b031916604051630612418f60e11b81526004016109209190614252565b846001600160a01b0316846001600160a01b031610612b32576000356001600160e01b031916604051635d3dcd3160e01b81526004016109209190614252565b8493506001016129b8565b50505085845250508281526020808c015160009081526001825260408082208e51835290925290812090612b6f61325b565b90506000612b7c85613265565b9050818110612c035780600003612bb4576000356001600160e01b031916604051637f11b8a360e11b81526004016109209190614252565b825460ff1916600190811784558301546040517f5c819725ea53655a3b898f3df59b66489761935454e9212ca1e5ebd759953d0b90600090a2612bf7838f613270565b50505050505050612cd6565b600082612c0e6132dd565b612c18919061421d565b612c2390600161420a565b90506000612c3086613265565b9050818110612caf5780600003612c68576000356001600160e01b031916604051637f11b8a360e11b81526004016109209190614252565b845460ff1916600317855560018501546040517f55295d4ce992922fa2e5ffbf3a3dcdb367de0a15e125ace083456017fd22060f90600090a2505050505050505050612cd6565b6000356001600160e01b031916604051634ccfe64360e11b81526004016109209190614252565b50505050505050565b612d1f6040518060e00160405280600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b612d38612d3184604001516001611630565b84906132e7565b9050612d4f600254826130f690919063ffffffff16565b6000612d5a82612770565b90506000612d686000613197565b60008181527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602090815260409091209087015160018201859055600690910155905082518114612dda576000356001600160e01b03191660405163d4cec26960e01b81526004016109209190614252565b81817f771d78ae9e5fca95a532fb0971d575d0ce9b59d14823c063e08740137e0e0eca85612e0789612e29565b8989604051612e199493929190614950565b60405180910390a3505092915050565b60608101516040820151608083015151600092919083906001600160401b03811115612e5757612e57613e2f565b604051908082528060200260200182016040528015612e80578160200160208202803683370190505b5060a086015190915060005b8251811015612edf5786608001518181518110612eab57612eab614267565b602002602001015180519060200120838281518110612ecc57612ecc614267565b6020908102919091010152600101612e8c565b50604080517f1463f426c05aff2c1a7a0957a71c9898bc8b47142540538e79ee25ee911413508152875160208083019190915297880151918101919091528351870293870193909320606084015283518602938601939093206080830152805185029085012060a082015281518402919093012060c08301525060e0902090565b8060036000846004811115612f7757612f776140c2565b6004811115612f8857612f886140c2565b8152602081019190915260400160002080546001600160a01b0319166001600160a01b039283161790558116826004811115612fc657612fc66140c2565b6040517f356c8c57e9e84b99b1cb58b13c985b2c979f78cbdf4d0fa70fe2a98bb09a099d90600090a35050565b600081815260018301602052604081205480156130dc57600061301760018361421d565b855490915060009061302b9060019061421d565b905081811461309057600086600001828154811061304b5761304b614267565b906000526020600020015490508087600001848154811061306e5761306e614267565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806130a1576130a1614a37565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610766565b6000915050610766565b60006107668361104a8585613411565b60008260600151511180156131145750816080015151826060015151145b801561312957508160a0015151826060015151145b801561313e57508160c0015151826060015151145b613169576000356001600160e01b0319166040516306b5667560e21b81526004016109209190614252565b613173814261420a565b826040015111156109335760405163ad89be9d60e01b815260040160405180910390fd5b600081815260208190526040812054908190036131c65750600090815260208190526040902060019081905590565b60008281526001602090815260408083208484529091528120906000825460ff1660048111156131f8576131f86140c2565b036132165760405163757a436360e01b815260040160405180910390fd5b505050600090815260208190526040902080546001019081905590565b6000806000613244878787876135ec565b91509150613251816136d9565b5095945050505050565b6000610638610876565b6000610766826114e1565b6132798161388f565b1561093357815460ff19166002178255600080613295836138a9565b9150915083600101547fe134987599ae266ec90edeff1b26125b287dbb57b10822649432d1bb26537fba83836040516132cf929190614a4d565b60405180910390a250505050565b6000610638610620565b6133276040518060e00160405280600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b82518152602080840151604080840191909152600091830191909152830151516001600160401b0381111561335e5761335e613e2f565b604051908082528060200260200182016040528015613387578160200160208202803683370190505b5060608083019190915283015160808083019190915283015160a08083019190915283015160c082015260005b836040015151811015611783578281815181106133d3576133d3614267565b6020026020010151826060015182815181106133f1576133f1614267565b6001600160a01b03909216602092830291909101909101526001016133b4565b600082548281101561343057634e487b7160005260116020526024601cfd5b9190910392915050565b60048301548110156134ed5782600801600084600401838154811061346157613461614267565b60009182526020808320909101546001600160a01b031683528201929092526040018120805460ff1916905560048401805460078601929190849081106134aa576134aa614267565b60009182526020808320909101546001600160a01b031683528201929092526040018120805460ff1916815560018181018390556002909101919091550161343a565b5060005b60058301548110156135a45782600801600084600501838154811061351857613518614267565b60009182526020808320909101546001600160a01b031683528201929092526040018120805460ff19169055600584018054600786019291908490811061356157613561614267565b60009182526020808320909101546001600160a01b031683528201929092526040018120805460ff191681556001818101839055600290910191909155016134f1565b50815460ff1916825560006001830181905560028301819055600383018190556135d2906004840190613b07565b6135e0600583016000613b07565b60006006830155919050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561362357506000905060036136d0565b8460ff16601b1415801561363b57508460ff16601c14155b1561364c57506000905060046136d0565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156136a0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166136c9576000600192509250506136d0565b9150600090505b94509492505050565b60008160048111156136ed576136ed6140c2565b036136f55750565b6001816004811115613709576137096140c2565b036137565760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610920565b600281600481111561376a5761376a6140c2565b036137b75760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610920565b60038160048111156137cb576137cb6140c2565b036138235760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610920565b6004816004811115613837576138376140c2565b036114de5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610920565b600081602001516000148061076657505060200151461490565b6060806138b58361388f565b6138f357602083015160405163092048d160e11b81526000356001600160e01b03191660048201526024810191909152466044820152606401610920565b8260600151516001600160401b0381111561391057613910613e2f565b604051908082528060200260200182016040528015613939578160200160208202803683370190505b5091508260600151516001600160401b0381111561395957613959613e2f565b60405190808252806020026020018201604052801561398c57816020015b60608152602001906001900390816139775790505b50905060005b836060015151811015613b01578360c0015181815181106139b5576139b5614267565b60200260200101515a116139e8576139cc84612770565b6040516307aec4ab60e21b815260040161092091815260200190565b836060015181815181106139fe576139fe614267565b60200260200101516001600160a01b031684608001518281518110613a2557613a25614267565b60200260200101518560c001518381518110613a4357613a43614267565b6020026020010151908660a001518481518110613a6257613a62614267565b6020026020010151604051613a7791906146c7565b600060405180830381858888f193505050503d8060008114613ab5576040519150601f19603f3d011682016040523d82523d6000602084013e613aba565b606091505b50848381518110613acd57613acd614267565b60200260200101848481518110613ae657613ae6614267565b60209081029190910101919091529015159052600101613992565b50915091565b50805460008255906000526020600020908101906114de91905b80821115613b355760008155600101613b21565b5090565b60008083601f840112613b4b57600080fd5b5081356001600160401b03811115613b6257600080fd5b6020830191508360208260051b8501011115610b2757600080fd5b60008060008060008060608789031215613b9657600080fd5b86356001600160401b0380821115613bad57600080fd5b613bb98a838b01613b39565b90985096506020890135915080821115613bd257600080fd5b613bde8a838b01613b39565b90965094506040890135915080821115613bf757600080fd5b50613c0489828a01613b39565b979a9699509497509295939492505050565b600081518084526020808501945080840160005b83811015613c48578151151587529582019590820190600101613c2a565b509495945050505050565b6020815260006107216020830184613c16565b60008060208385031215613c7957600080fd5b82356001600160401b03811115613c8f57600080fd5b613c9b85828601613b39565b90969095509350505050565b600081518084526020808501945080840160005b83811015613c485781516001600160a01b031687529582019590820190600101613cbb565b6020815260006107216020830184613ca7565b600060208284031215613d0557600080fd5b5035919050565b60008083601f840112613d1e57600080fd5b5081356001600160401b03811115613d3557600080fd5b602083019150836020606083028501011115610b2757600080fd5b600080600080600060608688031215613d6857600080fd5b85356001600160401b0380821115613d7f57600080fd5b9087019060e0828a031215613d9357600080fd5b90955060208701359080821115613da957600080fd5b613db589838a01613b39565b90965094506040880135915080821115613dce57600080fd5b50613ddb88828901613d0c565b969995985093965092949392505050565b600080600080600060608688031215613e0457600080fd5b85356001600160401b0380821115613e1b57600080fd5b9087019060c0828a031215613d9357600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715613e6757613e67613e2f565b60405290565b60405160c081016001600160401b0381118282101715613e6757613e67613e2f565b604051601f8201601f191681016001600160401b0381118282101715613eb757613eb7613e2f565b604052919050565b60006001600160401b03821115613ed857613ed8613e2f565b5060051b60200190565b600082601f830112613ef357600080fd5b81356020613f08613f0383613ebf565b613e8f565b828152600592831b8501820192828201919087851115613f2757600080fd5b8387015b85811015613f4f578035828110613f425760008081fd5b8452928401928401613f2b565b5090979650505050505050565b80356001600160a01b0381168114610d6957600080fd5b600082601f830112613f8457600080fd5b81356020613f94613f0383613ebf565b82815260059290921b84018101918181019086841115613fb357600080fd5b8286015b84811015613fd557613fc881613f5c565b8352918301918301613fb7565b509695505050505050565b60008060408385031215613ff357600080fd5b82356001600160401b038082111561400a57600080fd5b61401686838701613ee2565b9350602085013591508082111561402c57600080fd5b5061403985828601613f73565b9150509250929050565b803560108110610d6957600080fd5b6000806040838503121561406557600080fd5b61406e83614043565b915061407c60208401613f5c565b90509250929050565b60006020828403121561409757600080fd5b61072182613f5c565b600080604083850312156140b357600080fd5b50508035926020909101359150565b634e487b7160e01b600052602160045260246000fd5b600581106114de576114de6140c2565b60a081016140f5876140d8565b95815260208101949094526040840192909252606083015260809091015290565b60006020828403121561412857600080fd5b81356001600160401b0381111561413e57600080fd5b6106ba84828501613f73565b600081518084526020808501945080840160005b83811015613c485781516001600160601b03168752958201959082019060010161415e565b6060815260006141966060830186613ca7565b82810360208401526141a88186613ca7565b905082810360408401526141bc818561414a565b9695505050505050565b602081526000610721602083018461414a565b6000602082840312156141eb57600080fd5b61072182614043565b634e487b7160e01b600052601160045260246000fd5b80820180821115610766576107666141f4565b81810381811115610766576107666141f4565b60008261424d57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160e01b031991909116815260200190565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610766576107666141f4565b60208101601083106142a8576142a86140c2565b91905290565b6040815260006142c16040830185613ca7565b82810360208401526142d38185613c16565b95945050505050565b6080815260006142ef6080830187613c16565b8281036020840152614301818761414a565b905082810360408401526143158186613ca7565b905082810360608401526106158185613ca7565b6001600160e01b03198316815260408101600b831061434a5761434a6140c2565b8260208301529392505050565b600082601f83011261436857600080fd5b81356020614378613f0383613ebf565b82815260059290921b8401810191818101908684111561439757600080fd5b8286015b84811015613fd5578035835291830191830161439b565b6000601f83818401126143c457600080fd5b823560206143d4613f0383613ebf565b82815260059290921b850181019181810190878411156143f357600080fd5b8287015b848110156144895780356001600160401b03808211156144175760008081fd5b818a0191508a603f83011261442c5760008081fd5b8582013560408282111561444257614442613e2f565b614453828b01601f19168901613e8f565b92508183528c8183860101111561446a5760008081fd5b81818501898501375060009082018701528452509183019183016143f7565b50979650505050505050565b600060e082360312156144a757600080fd5b6144af613e45565b82358152602083013560208201526040830135604082015260608301356001600160401b03808211156144e157600080fd5b6144ed36838701613f73565b6060840152608085013591508082111561450657600080fd5b61451236838701614357565b608084015260a085013591508082111561452b57600080fd5b614537368387016143b2565b60a084015260c085013591508082111561455057600080fd5b5061455d36828601614357565b60c08301525092915050565b600060c0823603121561457b57600080fd5b614583613e6d565b823581526020830135602082015260408301356001600160401b03808211156145ab57600080fd5b6145b736838701613ee2565b604084015260608501359150808211156145d057600080fd5b6145dc36838701614357565b606084015260808501359150808211156145f557600080fd5b614601368387016143b2565b608084015260a085013591508082111561461a57600080fd5b5061462736828601614357565b60a08301525092915050565b60005b8381101561464e578181015183820152602001614636565b50506000910152565b6001600160e01b031983168152815160009061467a816004850160208701614633565b919091016004019392505050565b600081518084526146a0816020860160208601614633565b601f01601f19169290920160200192915050565b6020815260006107216020830184614688565b600082516146d9818460208701614633565b9190910192915050565b6000815180845260208085019450848260051b860182860160005b85811015613f4f578383038952614716838351614688565b988501989250908401906001016146fe565b60808152600061473b6080830187614688565b828103602084015261474d8187613ca7565b905082810360408401526147618186613c16565b9050828103606084015261061581856146e3565b6040815260006147886040830185613c16565b82810360208401526142d38185613ca7565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b6000602082840312156147cf57600080fd5b8151801515811461072157600080fd5b600081518084526020808501945080840160005b83811015613c48578151875295820195908201906001016147f3565b600060e08301825184526020808401518186015260408401516040860152606084015160e06060870152828151808552610100880191508383019450600092505b808310156148795784516001600160a01b03168252938301936001929092019190830190614850565b5060808601519350868103608088015261489381856147df565b935050505060a083015184820360a08601526148af82826146e3565b91505060c083015184820360c08601526142d382826147df565b6040815260006148dc604083018561480f565b905060018060a01b03831660208301529392505050565b60006020828403121561490557600080fd5b81356002811061072157600080fd5b60006020828403121561492657600080fd5b813560ff8116811461072157600080fd5b600060018201614949576149496141f4565b5060010190565b608081526000614963608083018761480f565b60208681850152838203604085015260c08201865183528187015182840152604087015160c0604085015281815180845260e0860191508483019350600092505b808310156149cd5783516149b7816140d8565b82529284019260019290920191908401906149a4565b506060890151935084810360608601526149e781856147df565b935050505060808601518282036080840152614a0382826146e3565b91505060a086015182820360a0840152614a1d82826147df565b93505050506142d360608301846001600160a01b03169052565b634e487b7160e01b600052603160045260246000fd5b604081526000614a606040830185613c16565b82810360208401526142d381856146e356fe5da136eb38f8d8e354915fc8a767c0dc81d49de5fb65d5477122a82ddd976240ac1ff16a4f04f2a37a9ba5252a69baa100b460e517d1f8019c054a5ad698f9ffc55405a488814eaa0e2a685a0131142785b8d033d311c8c8244e34a7c12ca40f88547008e60f5748911f2e59feb3093b7e4c2e87b2dd69d61f112fcc932de8e38400683eb2cb350596d73644c0c89fe45f108600003457374f4ab3e87b4f3aa3d38c234075fde25875da8a6b7e36b58b86681d483271a99eeeee1d78e258a24d6924fe71b0c8b61aea02ca498b5f53b29bd95726278b1fe4eb791bb24a42644ca2646970667358221220e24c473cb9b7f8fce5e9e8b7bcf5aa6cef6921786fda11dfa2a2fe81c2fbf42764736f6c634300081100335da136eb38f8d8e354915fc8a767c0dc81d49de5fb65d5477122a82ddd976240c55405a488814eaa0e2a685a0131142785b8d033d311c8c8244e34a7c12ca40f92872d32822c9d44b36a2537d3e0d4c46fc4de1ce154ccfaed560a8a58445f1d0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000007e400000000000000000000000064192819ac13ef72bf6b5ae239ac672b43a9af080000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000032015e8b982c61bc8a593816fdbf03a603eec82300000000000000000000000000000000000000000000000000000000000000010000000000000000000000003200a8eb56767c3760e108aa27c65bfff036d8e60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000064192819ac13ef72bf6b5ae239ac672b43a9af08
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c80639b19dbfd1161011a578063cc7e6b3b116100ad578063de981f1b1161007c578063de981f1b1461050c578063e75235b814610537578063e9c034981461053f578063f80b535214610552578063fdc4fa471461055a57600080fd5b8063cc7e6b3b146104be578063d0a50db0146104de578063d78392f8146104e6578063dafae408146104f957600080fd5b8063b9c36209116100e9578063b9c3620914610464578063bc9182fd1461048c578063bc96180b1461049f578063c441c4a8146104a757600080fd5b80639b19dbfd146103db5780639b2ee437146103e3578063b384abef146103f6578063b405aaf21461045157600080fd5b80633644e515116101925780637de5dedd116101615780637de5dedd14610332578063800eaab31461033a578063865e6fd31461034d578063901979d51461036057600080fd5b80633644e515146102c05780635e05cf9e146102e7578063776fb1ec146102fc5780637d465f791461031f57600080fd5b80631f425338116101ce5780631f425338146102675780632d6d7d731461027a57806334d5f37b1461028d57806335da8121146102ad57600080fd5b806301a5f43f1461020057806306aba0e1146102295780630a44fa431461023f5780630f7c318914610252575b600080fd5b61021361020e366004613b7d565b61056d565b6040516102209190613c53565b60405180910390f35b610231610620565b604051908152602001610220565b61023161024d366004613c66565b61063d565b61025a6106c2565b6040516102209190613ce0565b610213610275366004613c66565b6106db565b61025a610288366004613c66565b610728565b61023161029b366004613cf3565b60006020819052908152604090205481565b6102136102bb366004613c66565b61076c565b6102317f9408194fe4a32106a620466afdd1b7827ec744a26bd1d6e99423a57405e1ed6381565b6102fa6102f5366004613d50565b6107b2565b005b61030f61030a366004613cf3565b6107f1565b6040519015158152602001610220565b6102fa61032d366004613dec565b61083e565b610231610876565b6102fa610348366004613fe0565b6108f2565b6102fa61035b366004614052565b610937565b6103c361036e366004614085565b6001600160a01b039081166000908152600080516020614af383398151915260209081526040808320549093168252600080516020614ad383398151915290522054600160a01b90046001600160601b031690565b6040516001600160601b039091168152602001610220565b61025a610952565b6102fa6103f1366004614085565b61095c565b6104406104043660046140a0565b600160208181526000938452604080852090915291835291208054918101546002820154600383015460069093015460ff909416939192909185565b6040516102209594939291906140e8565b61030f61045f366004614085565b610af3565b6104776104723660046140a0565b610b0d565b60408051928352602083019190915201610220565b61025a61049a366004614116565b610b2e565b610231610c1f565b6104af610c2a565b60405161022093929190614183565b6104d16104cc366004613c66565b610c54565b60405161022091906141c6565b610231610c92565b6103c36104f4366004614085565b610cab565b61030f610507366004613cf3565b610cb6565b61051f61051a3660046141d9565b610cf3565b6040516001600160a01b039091168152602001610220565b610477610d6e565b61021361054d366004613c66565b610d9f565b61025a610de5565b61025a610568366004613c66565b610def565b60606105776110fd565b61061587878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a92508991829185019084908082843760009201919091525050604080516020808a0282810182019093528982529093508992508891829185019084908082843760009201919091525061112d92505050565b979650505050505050565b6000610638600080516020614b338339815191525490565b905090565b600082828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061067e92508391506114a99050565b6106ba8484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506114e192505050565b949350505050565b6060610638600080516020614a738339815191526110f0565b60606106e56110fd565b61072183838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061156592505050565b9392505050565b606061072183838080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509250611630915050565b92915050565b60606107766110fd565b61072183838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061178a92505050565b6107bb3361187c565b6107ea85858585857f9408194fe4a32106a620466afdd1b7827ec744a26bd1d6e99423a57405e1ed63336118be565b5050505050565b60008060008381527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602052604090205460ff166004811115610836576108366140c2565b141592915050565b6108473361187c565b6107ea85858585857f9408194fe4a32106a620466afdd1b7827ec744a26bd1d6e99423a57405e1ed6333611963565b600061088e600080516020614a938339815191525490565b60016108a6600080516020614a938339815191525490565b6108d46108bf600080516020614b338339815191525490565b600080516020614ab3833981519152906119bf565b6108de919061420a565b6108e8919061421d565b6106389190614230565b333014610929576000356001600160e01b0319166040516307337e1960e41b81526004016109209190614252565b60405180910390fd5b61093382826119ea565b5050565b61093f6110fd565b61094881611a98565b6109338282611ace565b6060610638611b72565b6109653361187c565b61096e81611b8b565b336000908152600080516020614ad383398151915260208190526040909120546001600160a01b0390811690831681036109c657604051630669b93360e31b81526001600160a01b0384166004820152602401610920565b600080516020614b1383398151915260006109e18284611bc0565b80156109f257506109f28286610eda565b905080610a1d5760405163080fab4b60e31b81526001600160a01b0386166004820152602401610920565b6001600160a01b038381166000818152600080516020614af38339815191526020818152604080842080546001600160a01b0319908116909155958b16808552818520805488163390811790915585528a8352938190208054909616841790955584519081019390935292820152610ab0906364b18d0960e11b906060015b604051602081830303815290604052611bd5565b6040516001600160a01b03808816919086169033907fcef34cd748f30a1b7a2f214fd1651779f79bc6c1be02785cad5c1f0ee877213d90600090a4505050505050565b6000610766600080516020614b1383398151915283611018565b600080610b186110fd565b610b228484611edd565b915091505b9250929050565b8051606090806001600160401b03811115610b4b57610b4b613e2f565b604051908082528060200260200182016040528015610b74578160200160208202803683370190505b509150600080516020614ad383398151915260005b82811015610c1757816000868381518110610ba657610ba6614267565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a90046001600160a01b0316848281518110610bf757610bf7614267565b6001600160a01b0390921660209283029190910190910152600101610b89565b505050919050565b600061063860025490565b6060806060610c37611fd2565b9250610c4283610b2e565b9150610c4d83611ffd565b9050909192565b6060610721838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611ffd92505050565b6000610638600080516020614b138339815191526120e6565b6000610766826120f0565b6000610cd16108bf600080516020614b338339815191525490565b600080516020614a9383398151915254610ceb908461427d565b101592915050565b60007fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600083600f811115610d2a57610d2a6140c2565b60ff1681526020810191909152604001600020546001600160a01b0316905080610d69578160405163409140df60e11b81526004016109209190614294565b919050565b600080610d87600080516020614ab38339815191525490565b600080516020614a9383398151915254915091509091565b6060610da96110fd565b61072183838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061212892505050565b6060610638611fd2565b606081806001600160401b03811115610e0a57610e0a613e2f565b604051908082528060200260200182016040528015610e33578160200160208202803683370190505b509150600080516020614af383398151915260005b82811015610ecd57816000878784818110610e6557610e65614267565b9050602002016020810190610e7a9190614085565b6001600160a01b0390811682526020820192909252604001600020548551911690859083908110610ead57610ead614267565b6001600160a01b0390921660209283029190910190910152600101610e48565b50505092915050565b9055565b6000610721836001600160a01b03841661240d565b5490565b6000610efd825490565b9050610d6982610ed683600161420a565b81518151606091908082016001600160401b03811115610f3057610f30613e2f565b604051908082528060200260200182016040528015610f59578160200160208202803683370190505b50925060005b82811015610fb357858181518110610f7957610f79614267565b6020026020010151848281518110610f9357610f93614267565b6001600160a01b0390921660209283029190910190910152600101610f5f565b60005b8281101561100e57858181518110610fd057610fd0614267565b6020026020010151858381518110610fea57610fea614267565b6001600160a01b039092166020928302919091019091015260019182019101610fb6565b5050505092915050565b6001600160a01b03811660009081526001830160205260408120541515610721565b60006107668361104a858561245c565b9250829055565b6000815160000361106457506000919050565b60005b60018351038110156110e757600181015b83518110156110de5783818151811061109357611093614267565b60200260200101516001600160a01b03168483815181106110b6576110b6614267565b60200260200101516001600160a01b0316036110d6575060019392505050565b600101611078565b50600101611067565b50600092915050565b606060006107218361247b565b33301461112b576000356001600160e01b0319166040516307337e1960e41b81526004016109209190614252565b565b60606111398383610f0e565b611142816114a9565b82518551811480156111545750845181145b61117f576000356001600160e01b0319166040516306b5667560e21b81526004016109209190614252565b806001600160401b0381111561119757611197613e2f565b6040519080825280602002602001820160405280156111c0578160200160208202803683370190505b509250806000036111d157506114a1565b604080518082019091526000808252602082018190527f546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c91600080516020614af383398151915291600080516020614b1383398151915291600080516020614ad3833981519152919081908190815b89811015611422578d818151811061125a5761125a614267565b602002602001015194508c818151811061127657611276614267565b6020026020010151935061128985611b8b565b61129284611b8b565b8e81815181106112a4576112a4614267565b60200260200101516001600160601b03166000036112e3576000356001600160e01b031916604051637f11b8a360e11b81526004016109209190614252565b6112ed8986611018565b806112fd57506112fd8985611018565b8061130d575061130d8786611018565b8061131d575061131d8785611018565b158c828151811061133057611330614267565b6020026020010190151590811515815250508b818151811061135457611354614267565b60200260200101511561141a5761136b8986610eda565b506113768785610eda565b506001600160a01b03848116600081815260208b90526040902080546001600160a01b0319169288169290921790915582528e518f90829081106113bc576113bc614267565b6020908102919091018101516001600160601b03169083018190526113e1908461420a565b6001600160a01b038087166000908152602089815260409091208551918601516001600160601b0316600160a01b029190921617905592505b600101611240565b5061143b600080516020614b338339815191528361103a565b5061145a635ebae8a060e01b8d8d604051602001610a9c9291906142ae565b7f897810999654e525e272b5909785c4d0ceaee1bbf9c87d9091a37558b0423b788b8f8f8f60405161148f94939291906142dc565b60405180910390a15050505050505050505b509392505050565b6114b281611051565b156114de576000356001600160e01b031916604051630d697db160e11b81526004016109209190614252565b50565b6000816114ed816114a9565b600080516020614ad383398151915260005b8451811015610c175781600086838151811061151d5761151d614267565b6020908102919091018101516001600160a01b031682528101919091526040016000205461155b90600160a01b90046001600160601b03168561420a565b93506001016114ff565b606081611571816114a9565b8251806001600160401b0381111561158b5761158b613e2f565b6040519080825280602002602001820160405280156115b4578160200160208202803683370190505b509250600080516020614a7383398151915260005b82811015611627576115fd8682815181106115e6576115e6614267565b602002602001015183611bc090919063ffffffff16565b85828151811061160f5761160f614267565b911515602092830291909101909101526001016115c9565b50505050919050565b606082516001600160401b0381111561164b5761164b613e2f565b604051908082528060200260200182016040528015611674578160200160208202803683370190505b50905060005b8351811015611783576003600085838151811061169957611699614267565b602002602001015160048111156116b2576116b26140c2565b60048111156116c3576116c36140c2565b815260200190815260200160002060009054906101000a90046001600160a01b03168282815181106116f7576116f7614267565b60200260200101906001600160a01b031690816001600160a01b03168152505082801561174f575060006001600160a01b031682828151811061173c5761173c614267565b60200260200101516001600160a01b0316145b1561177b576000356001600160e01b03191660405163053265f160e01b81526004016109209190614252565b60010161167a565b5092915050565b606081611796816114a9565b8251806001600160401b038111156117b0576117b0613e2f565b6040519080825280602002602001820160405280156117d9578160200160208202803683370190505b509250806000036117ea5750611876565b600080516020614a7383398151915260006314d72edb60e21b815b848110156118705787818151811061181f5761181f614267565b6020026020010151925061183283611a98565b61183c83836124d7565b6118468484610eda565b87828151811061185857611858614267565b91151560209283029190910190910152600101611805565b50505050505b50919050565b611885816120f0565b6001600160601b03166000036114de576000356001600160e01b0319166003604051620f948f60ea1b8152600401610920929190614329565b6118d06118ca88614495565b8261266a565b5060006118e46118df89614495565b612770565b90506119596118f289614495565b88888888611945896119058960006128af565b60405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6119548a6119058a60016128af565b6128e8565b5050505050505050565b600061197761197189614569565b83612cdf565b9050600061198c6119878a614569565b612e29565b90506119b482898989896119a58a6119058960006128af565b6119548b6119058a60016128af565b505050505050505050565b600082548015611783578281029150808204831461178357634e487b7160005260116020526024601cfd5b60005b8251811015611a9357306001600160a01b0316828281518110611a1257611a12614267565b60200260200101516001600160a01b031603611a4f576000356001600160e01b03191660405163053265f160e01b81526004016109209190614252565b611a8b838281518110611a6457611a64614267565b6020026020010151838381518110611a7e57611a7e614267565b6020026020010151612f60565b6001016119ed565b505050565b806001600160a01b03163b6000036114de57604051630bfc64a360e21b81526001600160a01b0382166004820152602401610920565b807fdea3103d22025c269050bea94c0c84688877f12fa22b7e6d2d5d78a9a49aa1cb600084600f811115611b0457611b046140c2565b60ff168152602081019190915260400160002080546001600160a01b0319166001600160a01b03928316179055811682600f811115611b4557611b456140c2565b6040517f865d1c228a8ea13709cfe61f346f7ff67f1bbd4a18ff31ad3e7147350d317c5990600090a35050565b6060610638600080516020614b138339815191526110f0565b6001600160a01b0381166114de576000356001600160e01b03191660405163104c66df60e31b81526004016109209190614252565b6000610721836001600160a01b038416612ff3565b6000611bee600080516020614a738339815191526110f0565b80519091506000819003611c025750505050565b6000816001600160401b03811115611c1c57611c1c613e2f565b604051908082528060200260200182016040528015611c45578160200160208202803683370190505b5090506000826001600160401b03811115611c6257611c62613e2f565b604051908082528060200260200182016040528015611c9557816020015b6060815260200190600190039081611c805790505b50905060008686604051602001611cad929190614657565b6040516020818303038152906040529050600081604051602401611cd191906146b4565b60408051601f198184030181529190526020810180516001600160e01b03166325da93a560e11b179052905060005b85811015611e9557868181518110611d1a57611d1a614267565b60200260200101516001600160a01b031683604051611d3991906146c7565b6000604051808303816000865af19150503d8060008114611d76576040519150601f19603f3d011682016040523d82523d6000602084013e611d7b565b606091505b50868381518110611d8e57611d8e614267565b60200260200101868481518110611da757611da7614267565b6020026020010182905282151515158152505050848181518110611dcd57611dcd614267565b6020026020010151611e8d57868181518110611deb57611deb614267565b60200260200101516001600160a01b031682604051611e0a91906146c7565b6000604051808303816000865af19150503d8060008114611e47576040519150601f19603f3d011682016040523d82523d6000602084013e611e4c565b606091505b50868381518110611e5f57611e5f614267565b60200260200101868481518110611e7857611e78614267565b60200260200101829052821515151581525050505b600101611d00565b507fc0b07a27e66788f39cc91405f012f34066b16f31b4bda9438c52f2dae0cc5b6382878686604051611ecb9493929190614728565b60405180910390a15050505050505050565b60008082841115611f0f576000356001600160e01b0319166040516387f6f09560e01b81526004016109209190614252565b600080516020614ab3833981519152549150611f37600080516020614a938339815191525490565b9050611f50600080516020614ab3833981519152859055565b611f67600080516020614a93833981519152849055565b8284611f927f92872d32822c9d44b36a2537d3e0d4c46fc4de1ce154ccfaed560a8a58445f1d610ef3565b60408051868152602081018690527f976f8a9c5bdf8248dec172376d6e2b80a8e3df2f0328e381c6db8e1cf138c0f8910160405180910390a49250929050565b60606106387f546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c6110f0565b8051606090806001600160401b0381111561201a5761201a613e2f565b604051908082528060200260200182016040528015612043578160200160208202803683370190505b509150600080516020614ad383398151915260005b82811015610c175781600086838151811061207557612075614267565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060000160149054906101000a90046001600160601b03168482815181106120c6576120c6614267565b6001600160601b0390921660209283029190910190910152600101612058565b6000610766825490565b6001600160a01b03166000908152600080516020614ad38339815191526020526040902054600160a01b90046001600160601b031690565b606081612134816114a9565b8251806001600160401b0381111561214e5761214e613e2f565b604051908082528060200260200182016040528015612177578160200160208202803683370190505b509250806000036121885750611876565b60408051808201909152600080825260208201819052600080516020614af3833981519152917f546f6b46ab35b030b6816596b352aef78857377176c8b24baa2046a62cf1998c91600080516020614b1383398151915291600080516020614ad3833981519152919081908190815b8981101561238d578c818151811061221157612211614267565b6020908102919091018101516001600160a01b038082166000908152928c90526040909220549091169550935061224785611b8b565b61225084611b8b565b6001600160a01b0385811660009081526020888152604091829020825180840190935254808416808452600160a01b9091046001600160601b031691830191909152909350908516146122c4576000356001600160e01b03191660405163053265f160e01b81526004016109209190614252565b6122ce8785611018565b80156122df57506122df8886611018565b8c82815181106122f1576122f1614267565b6020026020010190151590811515815250508b818151811061231557612315614267565b6020026020010151156123855761232c8886611bc0565b506123378785611bc0565b506001600160a01b03808516600090815260208b8152604080832080546001600160a01b0319169055928816825288815291812055820151612382906001600160601b03168461420a565b92505b6001016121f7565b506123a6600080516020614b33833981519152836130e6565b506123c563c48549de60e01b8d8d604051602001610a9c9291906142ae565b7fdf3dcd7987202f64648f3acdbf12401e3a2bb23e77e19f99826b5475cbb863698b8d6040516123f6929190614775565b60405180910390a150505050505050505050919050565b600081815260018301602052604081205461245457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610766565b506000610766565b815481018181101561076657634e487b7160005260116020526024601cfd5b6060816000018054806020026020016040519081016040528092919081815260200182805480156124cb57602002820191906000526020600020905b8154815260200190600101908083116124b7575b50505050509050919050565b6000816040516024016124ea9190614252565b60408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b1790525190915060009081906001600160a01b038616906125339085906146c7565b600060405180830381855afa9150503d806000811461256e576040519150601f19603f3d011682016040523d82523d6000602084013e612573565b606091505b50915091508161263557846001600160a01b03168360405160240161259891906146b4565b60408051601f198184030181529181526020820180516001600160e01b03166325da93a560e11b179052516125cd91906146c7565b600060405180830381855afa9150503d8060008114612608576040519150601f19603f3d011682016040523d82523d6000602084013e61260d565b606091505b5090925090508161263557838560405163069d427960e11b815260040161092092919061479a565b8080602001905181019061264991906147bd565b6107ea57838560405163069d427960e11b815260040161092092919061479a565b60208201516000908082036126ac5760405163092048d160e11b8152600080356001600160e01b03191660048301526024820152466044820152606401610920565b6002546126ba9085906130f6565b60006126c585612770565b90506126d082613197565b6000838152600160208181526040808420858552909152918290209188015190820184905560069091015592508451831461272c576000356001600160e01b03191660405163d4cec26960e01b81526004016109209190614252565b8083837fa57d40f1496988cf60ab7c9d5ba4ff83647f67d3898d441a3aaf21b651678fd988886040516127609291906148c9565b60405180910390a4505092915050565b6080810151606082015160a083015151600092919083906001600160401b0381111561279e5761279e613e2f565b6040519080825280602002602001820160405280156127c7578160200160208202803683370190505b5060c086015190915060005b8251811015612826578660a0015181815181106127f2576127f2614267565b60200260200101518051906020012083828151811061281357612813614267565b60209081029190910101526001016127d3565b50604080517fd051578048e6ff0bbc9fca3b65a42088dbde10f36ca841de566711087ad9b08a8152875160208083019190915280890151828401529790910151606082015283518702938701939093206080840152835186029386019390932060a0830152805185029085012060c082015281518402919093012060e083015250610100902090565b604080517fd900570327c4c0df8dd6bdd522b7da7e39145dd049d2fd4602276adcd511e3c2815260208101939093528201526060902090565b84158015906128f657508483145b612921576000356001600160e01b0319166040516306b5667560e21b81526004016109209190614252565b60008080856001600160401b0381111561293d5761293d613e2f565b604051908082528060200260200182016040528015612966578160200160208202803683370190505b5090506000866001600160401b0381111561298357612983613e2f565b6040519080825280602002602001820160405280156129ac578160200160208202803683370190505b50905060008060003660005b8b811015612b3d578c8c828181106129d2576129d2614267565b90506060020191508e8e828181106129ec576129ec614267565b9050602002016020810190612a0191906148f3565b92506000836001811115612a1757612a176140c2565b03612a8157612a3c8b612a2d6020850185614914565b84602001358560400135613233565b945084878a612a4a81614937565b9b5081518110612a5c57612a5c614267565b60200260200101906001600160a01b031690816001600160a01b031681525050612af2565b6001836001811115612a9557612a956140c2565b03612acb57612aab8a612a2d6020850185614914565b9450848689612ab981614937565b9a5081518110612a5c57612a5c614267565b6000356001600160e01b031916604051630612418f60e11b81526004016109209190614252565b846001600160a01b0316846001600160a01b031610612b32576000356001600160e01b031916604051635d3dcd3160e01b81526004016109209190614252565b8493506001016129b8565b50505085845250508281526020808c015160009081526001825260408082208e51835290925290812090612b6f61325b565b90506000612b7c85613265565b9050818110612c035780600003612bb4576000356001600160e01b031916604051637f11b8a360e11b81526004016109209190614252565b825460ff1916600190811784558301546040517f5c819725ea53655a3b898f3df59b66489761935454e9212ca1e5ebd759953d0b90600090a2612bf7838f613270565b50505050505050612cd6565b600082612c0e6132dd565b612c18919061421d565b612c2390600161420a565b90506000612c3086613265565b9050818110612caf5780600003612c68576000356001600160e01b031916604051637f11b8a360e11b81526004016109209190614252565b845460ff1916600317855560018501546040517f55295d4ce992922fa2e5ffbf3a3dcdb367de0a15e125ace083456017fd22060f90600090a2505050505050505050612cd6565b6000356001600160e01b031916604051634ccfe64360e11b81526004016109209190614252565b50505050505050565b612d1f6040518060e00160405280600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b612d38612d3184604001516001611630565b84906132e7565b9050612d4f600254826130f690919063ffffffff16565b6000612d5a82612770565b90506000612d686000613197565b60008181527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49602090815260409091209087015160018201859055600690910155905082518114612dda576000356001600160e01b03191660405163d4cec26960e01b81526004016109209190614252565b81817f771d78ae9e5fca95a532fb0971d575d0ce9b59d14823c063e08740137e0e0eca85612e0789612e29565b8989604051612e199493929190614950565b60405180910390a3505092915050565b60608101516040820151608083015151600092919083906001600160401b03811115612e5757612e57613e2f565b604051908082528060200260200182016040528015612e80578160200160208202803683370190505b5060a086015190915060005b8251811015612edf5786608001518181518110612eab57612eab614267565b602002602001015180519060200120838281518110612ecc57612ecc614267565b6020908102919091010152600101612e8c565b50604080517f1463f426c05aff2c1a7a0957a71c9898bc8b47142540538e79ee25ee911413508152875160208083019190915297880151918101919091528351870293870193909320606084015283518602938601939093206080830152805185029085012060a082015281518402919093012060c08301525060e0902090565b8060036000846004811115612f7757612f776140c2565b6004811115612f8857612f886140c2565b8152602081019190915260400160002080546001600160a01b0319166001600160a01b039283161790558116826004811115612fc657612fc66140c2565b6040517f356c8c57e9e84b99b1cb58b13c985b2c979f78cbdf4d0fa70fe2a98bb09a099d90600090a35050565b600081815260018301602052604081205480156130dc57600061301760018361421d565b855490915060009061302b9060019061421d565b905081811461309057600086600001828154811061304b5761304b614267565b906000526020600020015490508087600001848154811061306e5761306e614267565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806130a1576130a1614a37565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610766565b6000915050610766565b60006107668361104a8585613411565b60008260600151511180156131145750816080015151826060015151145b801561312957508160a0015151826060015151145b801561313e57508160c0015151826060015151145b613169576000356001600160e01b0319166040516306b5667560e21b81526004016109209190614252565b613173814261420a565b826040015111156109335760405163ad89be9d60e01b815260040160405180910390fd5b600081815260208190526040812054908190036131c65750600090815260208190526040902060019081905590565b60008281526001602090815260408083208484529091528120906000825460ff1660048111156131f8576131f86140c2565b036132165760405163757a436360e01b815260040160405180910390fd5b505050600090815260208190526040902080546001019081905590565b6000806000613244878787876135ec565b91509150613251816136d9565b5095945050505050565b6000610638610876565b6000610766826114e1565b6132798161388f565b1561093357815460ff19166002178255600080613295836138a9565b9150915083600101547fe134987599ae266ec90edeff1b26125b287dbb57b10822649432d1bb26537fba83836040516132cf929190614a4d565b60405180910390a250505050565b6000610638610620565b6133276040518060e00160405280600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b82518152602080840151604080840191909152600091830191909152830151516001600160401b0381111561335e5761335e613e2f565b604051908082528060200260200182016040528015613387578160200160208202803683370190505b5060608083019190915283015160808083019190915283015160a08083019190915283015160c082015260005b836040015151811015611783578281815181106133d3576133d3614267565b6020026020010151826060015182815181106133f1576133f1614267565b6001600160a01b03909216602092830291909101909101526001016133b4565b600082548281101561343057634e487b7160005260116020526024601cfd5b9190910392915050565b60048301548110156134ed5782600801600084600401838154811061346157613461614267565b60009182526020808320909101546001600160a01b031683528201929092526040018120805460ff1916905560048401805460078601929190849081106134aa576134aa614267565b60009182526020808320909101546001600160a01b031683528201929092526040018120805460ff1916815560018181018390556002909101919091550161343a565b5060005b60058301548110156135a45782600801600084600501838154811061351857613518614267565b60009182526020808320909101546001600160a01b031683528201929092526040018120805460ff19169055600584018054600786019291908490811061356157613561614267565b60009182526020808320909101546001600160a01b031683528201929092526040018120805460ff191681556001818101839055600290910191909155016134f1565b50815460ff1916825560006001830181905560028301819055600383018190556135d2906004840190613b07565b6135e0600583016000613b07565b60006006830155919050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561362357506000905060036136d0565b8460ff16601b1415801561363b57508460ff16601c14155b1561364c57506000905060046136d0565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156136a0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166136c9576000600192509250506136d0565b9150600090505b94509492505050565b60008160048111156136ed576136ed6140c2565b036136f55750565b6001816004811115613709576137096140c2565b036137565760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610920565b600281600481111561376a5761376a6140c2565b036137b75760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610920565b60038160048111156137cb576137cb6140c2565b036138235760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610920565b6004816004811115613837576138376140c2565b036114de5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610920565b600081602001516000148061076657505060200151461490565b6060806138b58361388f565b6138f357602083015160405163092048d160e11b81526000356001600160e01b03191660048201526024810191909152466044820152606401610920565b8260600151516001600160401b0381111561391057613910613e2f565b604051908082528060200260200182016040528015613939578160200160208202803683370190505b5091508260600151516001600160401b0381111561395957613959613e2f565b60405190808252806020026020018201604052801561398c57816020015b60608152602001906001900390816139775790505b50905060005b836060015151811015613b01578360c0015181815181106139b5576139b5614267565b60200260200101515a116139e8576139cc84612770565b6040516307aec4ab60e21b815260040161092091815260200190565b836060015181815181106139fe576139fe614267565b60200260200101516001600160a01b031684608001518281518110613a2557613a25614267565b60200260200101518560c001518381518110613a4357613a43614267565b6020026020010151908660a001518481518110613a6257613a62614267565b6020026020010151604051613a7791906146c7565b600060405180830381858888f193505050503d8060008114613ab5576040519150601f19603f3d011682016040523d82523d6000602084013e613aba565b606091505b50848381518110613acd57613acd614267565b60200260200101848481518110613ae657613ae6614267565b60209081029190910101919091529015159052600101613992565b50915091565b50805460008255906000526020600020908101906114de91905b80821115613b355760008155600101613b21565b5090565b60008083601f840112613b4b57600080fd5b5081356001600160401b03811115613b6257600080fd5b6020830191508360208260051b8501011115610b2757600080fd5b60008060008060008060608789031215613b9657600080fd5b86356001600160401b0380821115613bad57600080fd5b613bb98a838b01613b39565b90985096506020890135915080821115613bd257600080fd5b613bde8a838b01613b39565b90965094506040890135915080821115613bf757600080fd5b50613c0489828a01613b39565b979a9699509497509295939492505050565b600081518084526020808501945080840160005b83811015613c48578151151587529582019590820190600101613c2a565b509495945050505050565b6020815260006107216020830184613c16565b60008060208385031215613c7957600080fd5b82356001600160401b03811115613c8f57600080fd5b613c9b85828601613b39565b90969095509350505050565b600081518084526020808501945080840160005b83811015613c485781516001600160a01b031687529582019590820190600101613cbb565b6020815260006107216020830184613ca7565b600060208284031215613d0557600080fd5b5035919050565b60008083601f840112613d1e57600080fd5b5081356001600160401b03811115613d3557600080fd5b602083019150836020606083028501011115610b2757600080fd5b600080600080600060608688031215613d6857600080fd5b85356001600160401b0380821115613d7f57600080fd5b9087019060e0828a031215613d9357600080fd5b90955060208701359080821115613da957600080fd5b613db589838a01613b39565b90965094506040880135915080821115613dce57600080fd5b50613ddb88828901613d0c565b969995985093965092949392505050565b600080600080600060608688031215613e0457600080fd5b85356001600160401b0380821115613e1b57600080fd5b9087019060c0828a031215613d9357600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715613e6757613e67613e2f565b60405290565b60405160c081016001600160401b0381118282101715613e6757613e67613e2f565b604051601f8201601f191681016001600160401b0381118282101715613eb757613eb7613e2f565b604052919050565b60006001600160401b03821115613ed857613ed8613e2f565b5060051b60200190565b600082601f830112613ef357600080fd5b81356020613f08613f0383613ebf565b613e8f565b828152600592831b8501820192828201919087851115613f2757600080fd5b8387015b85811015613f4f578035828110613f425760008081fd5b8452928401928401613f2b565b5090979650505050505050565b80356001600160a01b0381168114610d6957600080fd5b600082601f830112613f8457600080fd5b81356020613f94613f0383613ebf565b82815260059290921b84018101918181019086841115613fb357600080fd5b8286015b84811015613fd557613fc881613f5c565b8352918301918301613fb7565b509695505050505050565b60008060408385031215613ff357600080fd5b82356001600160401b038082111561400a57600080fd5b61401686838701613ee2565b9350602085013591508082111561402c57600080fd5b5061403985828601613f73565b9150509250929050565b803560108110610d6957600080fd5b6000806040838503121561406557600080fd5b61406e83614043565b915061407c60208401613f5c565b90509250929050565b60006020828403121561409757600080fd5b61072182613f5c565b600080604083850312156140b357600080fd5b50508035926020909101359150565b634e487b7160e01b600052602160045260246000fd5b600581106114de576114de6140c2565b60a081016140f5876140d8565b95815260208101949094526040840192909252606083015260809091015290565b60006020828403121561412857600080fd5b81356001600160401b0381111561413e57600080fd5b6106ba84828501613f73565b600081518084526020808501945080840160005b83811015613c485781516001600160601b03168752958201959082019060010161415e565b6060815260006141966060830186613ca7565b82810360208401526141a88186613ca7565b905082810360408401526141bc818561414a565b9695505050505050565b602081526000610721602083018461414a565b6000602082840312156141eb57600080fd5b61072182614043565b634e487b7160e01b600052601160045260246000fd5b80820180821115610766576107666141f4565b81810381811115610766576107666141f4565b60008261424d57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160e01b031991909116815260200190565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610766576107666141f4565b60208101601083106142a8576142a86140c2565b91905290565b6040815260006142c16040830185613ca7565b82810360208401526142d38185613c16565b95945050505050565b6080815260006142ef6080830187613c16565b8281036020840152614301818761414a565b905082810360408401526143158186613ca7565b905082810360608401526106158185613ca7565b6001600160e01b03198316815260408101600b831061434a5761434a6140c2565b8260208301529392505050565b600082601f83011261436857600080fd5b81356020614378613f0383613ebf565b82815260059290921b8401810191818101908684111561439757600080fd5b8286015b84811015613fd5578035835291830191830161439b565b6000601f83818401126143c457600080fd5b823560206143d4613f0383613ebf565b82815260059290921b850181019181810190878411156143f357600080fd5b8287015b848110156144895780356001600160401b03808211156144175760008081fd5b818a0191508a603f83011261442c5760008081fd5b8582013560408282111561444257614442613e2f565b614453828b01601f19168901613e8f565b92508183528c8183860101111561446a5760008081fd5b81818501898501375060009082018701528452509183019183016143f7565b50979650505050505050565b600060e082360312156144a757600080fd5b6144af613e45565b82358152602083013560208201526040830135604082015260608301356001600160401b03808211156144e157600080fd5b6144ed36838701613f73565b6060840152608085013591508082111561450657600080fd5b61451236838701614357565b608084015260a085013591508082111561452b57600080fd5b614537368387016143b2565b60a084015260c085013591508082111561455057600080fd5b5061455d36828601614357565b60c08301525092915050565b600060c0823603121561457b57600080fd5b614583613e6d565b823581526020830135602082015260408301356001600160401b03808211156145ab57600080fd5b6145b736838701613ee2565b604084015260608501359150808211156145d057600080fd5b6145dc36838701614357565b606084015260808501359150808211156145f557600080fd5b614601368387016143b2565b608084015260a085013591508082111561461a57600080fd5b5061462736828601614357565b60a08301525092915050565b60005b8381101561464e578181015183820152602001614636565b50506000910152565b6001600160e01b031983168152815160009061467a816004850160208701614633565b919091016004019392505050565b600081518084526146a0816020860160208601614633565b601f01601f19169290920160200192915050565b6020815260006107216020830184614688565b600082516146d9818460208701614633565b9190910192915050565b6000815180845260208085019450848260051b860182860160005b85811015613f4f578383038952614716838351614688565b988501989250908401906001016146fe565b60808152600061473b6080830187614688565b828103602084015261474d8187613ca7565b905082810360408401526147618186613c16565b9050828103606084015261061581856146e3565b6040815260006147886040830185613c16565b82810360208401526142d38185613ca7565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b6000602082840312156147cf57600080fd5b8151801515811461072157600080fd5b600081518084526020808501945080840160005b83811015613c48578151875295820195908201906001016147f3565b600060e08301825184526020808401518186015260408401516040860152606084015160e06060870152828151808552610100880191508383019450600092505b808310156148795784516001600160a01b03168252938301936001929092019190830190614850565b5060808601519350868103608088015261489381856147df565b935050505060a083015184820360a08601526148af82826146e3565b91505060c083015184820360c08601526142d382826147df565b6040815260006148dc604083018561480f565b905060018060a01b03831660208301529392505050565b60006020828403121561490557600080fd5b81356002811061072157600080fd5b60006020828403121561492657600080fd5b813560ff8116811461072157600080fd5b600060018201614949576149496141f4565b5060010190565b608081526000614963608083018761480f565b60208681850152838203604085015260c08201865183528187015182840152604087015160c0604085015281815180845260e0860191508483019350600092505b808310156149cd5783516149b7816140d8565b82529284019260019290920191908401906149a4565b506060890151935084810360608601526149e781856147df565b935050505060808601518282036080840152614a0382826146e3565b91505060a086015182820360a0840152614a1d82826147df565b93505050506142d360608301846001600160a01b03169052565b634e487b7160e01b600052603160045260246000fd5b604081526000614a606040830185613c16565b82810360208401526142d381856146e356fe5da136eb38f8d8e354915fc8a767c0dc81d49de5fb65d5477122a82ddd976240ac1ff16a4f04f2a37a9ba5252a69baa100b460e517d1f8019c054a5ad698f9ffc55405a488814eaa0e2a685a0131142785b8d033d311c8c8244e34a7c12ca40f88547008e60f5748911f2e59feb3093b7e4c2e87b2dd69d61f112fcc932de8e38400683eb2cb350596d73644c0c89fe45f108600003457374f4ab3e87b4f3aa3d38c234075fde25875da8a6b7e36b58b86681d483271a99eeeee1d78e258a24d6924fe71b0c8b61aea02ca498b5f53b29bd95726278b1fe4eb791bb24a42644ca2646970667358221220e24c473cb9b7f8fce5e9e8b7bcf5aa6cef6921786fda11dfa2a2fe81c2fbf42764736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000007e400000000000000000000000064192819ac13ef72bf6b5ae239ac672b43a9af080000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000032015e8b982c61bc8a593816fdbf03a603eec82300000000000000000000000000000000000000000000000000000000000000010000000000000000000000003200a8eb56767c3760e108aa27c65bfff036d8e60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000064192819ac13ef72bf6b5ae239ac672b43a9af08
-----Decoded View---------------
Arg [0] : num (uint256): 70
Arg [1] : denom (uint256): 100
Arg [2] : roninChainId (uint256): 2020
Arg [3] : bridgeContract (address): 0x64192819Ac13Ef72bF6b5AE239AC672B43a9AF08
-----Encoded View---------------
21 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000046
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [2] : 00000000000000000000000000000000000000000000000000000000000007e4
Arg [3] : 00000000000000000000000064192819ac13ef72bf6b5ae239ac672b43a9af08
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [6] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [7] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000220
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [12] : 00000000000000000000000032015e8b982c61bc8a593816fdbf03a603eec823
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [14] : 0000000000000000000000003200a8eb56767c3760e108aa27c65bfff036d8e6
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [20] : 00000000000000000000000064192819ac13ef72bf6b5ae239ac672b43a9af08
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.