Source Code
Overview
ETH Balance
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 28303717 | 17 hrs ago | 0 ETH | ||||
| 28236261 | 2 days ago | 0 ETH | ||||
| 28218111 | 2 days ago | 0 ETH | ||||
| 28206715 | 3 days ago | 0 ETH | ||||
| 28204634 | 3 days ago | 0 ETH | ||||
| 28194340 | 3 days ago | 0 ETH | ||||
| 28189185 | 3 days ago | 0 ETH | ||||
| 28168370 | 4 days ago | 0 ETH | ||||
| 28127640 | 5 days ago | 0 ETH | ||||
| 28126039 | 5 days ago | 0 ETH | ||||
| 28103301 | 5 days ago | 0 ETH | ||||
| 28103289 | 5 days ago | 0 ETH | ||||
| 28097294 | 5 days ago | 0 ETH | ||||
| 28076244 | 6 days ago | 0 ETH | ||||
| 28051371 | 6 days ago | 0 ETH | ||||
| 28037739 | 7 days ago | 0 ETH | ||||
| 28020196 | 7 days ago | 0 ETH | ||||
| 28008293 | 7 days ago | 0 ETH | ||||
| 27980638 | 8 days ago | 0 ETH | ||||
| 27976318 | 8 days ago | 0 ETH | ||||
| 27958639 | 9 days ago | 0 ETH | ||||
| 27957921 | 9 days ago | 0 ETH | ||||
| 27928706 | 9 days ago | 0 ETH | ||||
| 27917423 | 10 days ago | 0 ETH | ||||
| 27911062 | 10 days ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SignatureVerifier
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;
import "./OraclesManager.sol";
import "../interfaces/ISignatureVerifier.sol";
import "../libraries/SignatureUtil.sol";
/// @dev It's used to verify that a transfer is signed by oracles.
contract SignatureVerifier is OraclesManager, ISignatureVerifier {
using SignatureUtil for bytes;
using SignatureUtil for bytes32;
/* ========== STATE VARIABLES ========== */
/// @dev Number of required confirmations per block after the extra check is enabled
uint8 public confirmationThreshold;
/// @dev submissions count in current block
uint40 public submissionsInBlock;
/// @dev Current block
uint40 public currentBlock;
/// @dev Debridge gate address
address public debridgeAddress;
/* ========== ERRORS ========== */
error DeBridgeGateBadRole();
error NotConfirmedByRequiredOracles();
error NotConfirmedThreshold();
error SubmissionNotConfirmed();
error DuplicateSignatures();
/* ========== MODIFIERS ========== */
modifier onlyDeBridgeGate() {
if (msg.sender != debridgeAddress) revert DeBridgeGateBadRole();
_;
}
/* ========== CONSTRUCTOR ========== */
/// @dev Constructor that initializes the most important configurations.
/// @param _minConfirmations Common confirmations count.
/// @param _confirmationThreshold Confirmations per block after the extra check is enabled.
/// @param _excessConfirmations Confirmations count in case of excess activity.
function initialize(
uint8 _minConfirmations,
uint8 _confirmationThreshold,
uint8 _excessConfirmations,
address _debridgeAddress
) public initializer {
OraclesManager.initialize(_minConfirmations, _excessConfirmations);
confirmationThreshold = _confirmationThreshold;
debridgeAddress = _debridgeAddress;
}
/// @inheritdoc ISignatureVerifier
function submit(
bytes32 _submissionId,
bytes memory _signatures,
uint8 _excessConfirmations
) external override onlyDeBridgeGate {
//Need confirmation to confirm submission
uint8 needConfirmations = _excessConfirmations > minConfirmations
? _excessConfirmations
: minConfirmations;
// Count of required(DSRM) oracles confirmation
uint256 currentRequiredOraclesCount;
// stack variable to aggregate confirmations and write to storage once
uint8 confirmations;
uint256 signaturesCount = _countSignatures(_signatures);
address[] memory validators = new address[](signaturesCount);
for (uint256 i = 0; i < signaturesCount; i++) {
(bytes32 r, bytes32 s, uint8 v) = _signatures.parseSignature(i * 65);
address oracle = ecrecover(_submissionId.getUnsignedMsg(), v, r, s);
if (getOracleInfo[oracle].isValid) {
for (uint256 k = 0; k < i; k++) {
if (validators[k] == oracle) revert DuplicateSignatures();
}
validators[i] = oracle;
confirmations += 1;
emit Confirmed(_submissionId, oracle);
if (getOracleInfo[oracle].required) {
currentRequiredOraclesCount += 1;
}
if (
confirmations >= needConfirmations &&
currentRequiredOraclesCount >= requiredOraclesCount
) {
break;
}
}
}
if (currentRequiredOraclesCount != requiredOraclesCount)
revert NotConfirmedByRequiredOracles();
if (confirmations >= minConfirmations) {
if (currentBlock == uint40(block.number)) {
submissionsInBlock += 1;
} else {
currentBlock = uint40(block.number);
submissionsInBlock = 1;
}
emit SubmissionApproved(_submissionId);
}
if (submissionsInBlock > confirmationThreshold) {
if (confirmations < excessConfirmations) revert NotConfirmedThreshold();
}
if (confirmations < needConfirmations) revert SubmissionNotConfirmed();
}
/* ========== ADMIN ========== */
/// @dev Sets minimal required confirmations.
/// @param _confirmationThreshold Confirmation info.
function setThreshold(uint8 _confirmationThreshold) external onlyAdmin {
if (_confirmationThreshold == 0) revert WrongArgument();
confirmationThreshold = _confirmationThreshold;
}
/// @dev Sets core debridge conrtact address.
/// @param _debridgeAddress Debridge address.
function setDebridgeAddress(address _debridgeAddress) external onlyAdmin {
debridgeAddress = _debridgeAddress;
}
/* ========== VIEW ========== */
/// @dev Check is valid signature
/// @param _submissionId Submission identifier.
/// @param _signature signature by oracle.
function isValidSignature(bytes32 _submissionId, bytes memory _signature)
external
view
returns (bool)
{
(bytes32 r, bytes32 s, uint8 v) = _signature.splitSignature();
address oracle = ecrecover(_submissionId.getUnsignedMsg(), v, r, s);
return getOracleInfo[oracle].isValid;
}
/* ========== INTERNAL ========== */
function _countSignatures(bytes memory _signatures) internal pure returns (uint256) {
return _signatures.length % 65 == 0 ? _signatures.length / 65 : 0;
}
// ============ Version Control ============
/// @dev Get this contract's version
function version() external pure returns (uint256) {
return 202; // 2.0.2
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "../interfaces/IOraclesManager.sol";
/// @dev The base contract for oracles management. Allows adding/removing oracles,
/// managing the minimal required amount of confirmations.
contract OraclesManager is Initializable, AccessControlUpgradeable, IOraclesManager {
/* ========== STATE VARIABLES ========== */
/// @dev Minimal required confirmations
uint8 public minConfirmations;
/// @dev Minimal required confirmations in case of too many confirmations
uint8 public excessConfirmations;
/// @dev Count of required oracles
uint8 public requiredOraclesCount;
/// @dev Oracle addresses
address[] public oracleAddresses;
/// @dev Maps an oracle address to the oracle details
mapping(address => OracleInfo) public getOracleInfo;
/* ========== ERRORS ========== */
error AdminBadRole();
error OracleBadRole();
error OracleAlreadyExist();
error OracleNotFound();
error WrongArgument();
error LowMinConfirmations();
/* ========== MODIFIERS ========== */
modifier onlyAdmin() {
if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert AdminBadRole();
_;
}
modifier onlyOracle() {
if (!getOracleInfo[msg.sender].isValid) revert OracleBadRole();
_;
}
/* ========== CONSTRUCTOR ========== */
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() initializer {
}
/// @dev Constructor that initializes the most important configurations.
/// @param _minConfirmations Minimal required confirmations.
/// @param _excessConfirmations Minimal required confirmations in case of too many confirmations.
function initialize(uint8 _minConfirmations, uint8 _excessConfirmations) internal {
if (_minConfirmations == 0 || _excessConfirmations < _minConfirmations) revert LowMinConfirmations();
minConfirmations = _minConfirmations;
excessConfirmations = _excessConfirmations;
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
/* ========== ADMIN ========== */
/// @dev Sets minimal required confirmations.
/// @param _minConfirmations Minimal required confirmations.
function setMinConfirmations(uint8 _minConfirmations) external onlyAdmin {
if (_minConfirmations < oracleAddresses.length / 2 + 1) revert LowMinConfirmations();
minConfirmations = _minConfirmations;
}
/// @dev Sets minimal required confirmations in case of too many confirmations.
/// @param _excessConfirmations Minimal required confirmations in case of too many confirmations.
function setExcessConfirmations(uint8 _excessConfirmations) external onlyAdmin {
if (_excessConfirmations < minConfirmations) revert LowMinConfirmations();
excessConfirmations = _excessConfirmations;
}
/// @dev Add oracles.
/// @param _oracles Oracles' addresses.
/// @param _required A transfer will not be confirmed without oracles having required set to true,
function addOracles(
address[] memory _oracles,
bool[] memory _required
) external onlyAdmin {
if (_oracles.length != _required.length) revert WrongArgument();
if (minConfirmations < (oracleAddresses.length + _oracles.length) / 2 + 1) revert LowMinConfirmations();
for (uint256 i = 0; i < _oracles.length; i++) {
OracleInfo storage oracleInfo = getOracleInfo[_oracles[i]];
if (oracleInfo.exist) revert OracleAlreadyExist();
oracleAddresses.push(_oracles[i]);
if (_required[i]) {
requiredOraclesCount += 1;
}
oracleInfo.exist = true;
oracleInfo.isValid = true;
oracleInfo.required = _required[i];
emit AddOracle(_oracles[i], _required[i]);
}
}
/// @dev Update an oracle.
/// @param _oracle An oracle address.
/// @param _isValid Is this oracle valid, i.e. should it be treated as an oracle.
/// @param _required If set to true a transfer will not be confirmed without this oracle.
function updateOracle(
address _oracle,
bool _isValid,
bool _required
) external onlyAdmin {
//If oracle is invalid, it must be not required
if (!_isValid && _required) revert WrongArgument();
OracleInfo storage oracleInfo = getOracleInfo[_oracle];
if (!oracleInfo.exist) revert OracleNotFound();
if (oracleInfo.required && !_required) {
requiredOraclesCount -= 1;
} else if (!oracleInfo.required && _required) {
requiredOraclesCount += 1;
}
if (oracleInfo.isValid && !_isValid) {
// remove oracle from oracleAddresses array without keeping an order
for (uint256 i = 0; i < oracleAddresses.length; i++) {
if (oracleAddresses[i] == _oracle) {
oracleAddresses[i] = oracleAddresses[oracleAddresses.length - 1];
oracleAddresses.pop();
break;
}
}
} else if (!oracleInfo.isValid && _isValid) {
if (minConfirmations < (oracleAddresses.length + 1) / 2 + 1) revert LowMinConfirmations();
oracleAddresses.push(_oracle);
}
oracleInfo.isValid = _isValid;
oracleInfo.required = _required;
emit UpdateOracle(_oracle, _required, _isValid);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface ISignatureVerifier {
/* ========== EVENTS ========== */
/// @dev Emitted once the submission is confirmed by one oracle.
event Confirmed(bytes32 submissionId, address operator);
/// @dev Emitted once the submission is confirmed by min required amount of oracles.
event DeployConfirmed(bytes32 deployId, address operator);
/* ========== FUNCTIONS ========== */
/// @dev Check confirmation (validate signatures) for the transfer request.
/// @param _submissionId Submission identifier.
/// @param _signatures Array of signatures by oracles.
/// @param _excessConfirmations override min confirmations count
function submit(
bytes32 _submissionId,
bytes memory _signatures,
uint8 _excessConfirmations
) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;
library SignatureUtil {
/* ========== ERRORS ========== */
error WrongArgumentLength();
error SignatureInvalidLength();
error SignatureInvalidV();
/// @dev Prepares raw msg that was signed by the oracle.
/// @param _submissionId Submission identifier.
function getUnsignedMsg(bytes32 _submissionId) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _submissionId));
}
/// @dev Splits signature bytes to r,s,v components.
/// @param _signature Signature bytes in format r+s+v.
function splitSignature(bytes memory _signature)
internal
pure
returns (
bytes32 r,
bytes32 s,
uint8 v
)
{
if (_signature.length != 65) revert SignatureInvalidLength();
return parseSignature(_signature, 0);
}
function parseSignature(bytes memory _signatures, uint256 offset)
internal
pure
returns (
bytes32 r,
bytes32 s,
uint8 v
)
{
assembly {
r := mload(add(_signatures, add(32, offset)))
s := mload(add(_signatures, add(64, offset)))
v := and(mload(add(_signatures, add(65, offset))), 0xff)
}
if (v < 27) v += 27;
if (v != 27 && v != 28) revert SignatureInvalidV();
}
function toUint256(bytes memory _bytes, uint256 _offset)
internal
pure
returns (uint256 result)
{
if (_bytes.length < _offset + 32) revert WrongArgumentLength();
assembly {
result := mload(add(add(_bytes, 0x20), _offset))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControlUpgradeable.sol";
import "../utils/ContextUpgradeable.sol";
import "../utils/StringsUpgradeable.sol";
import "../utils/introspection/ERC165Upgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {
function __AccessControl_init() internal initializer {
__Context_init_unchained();
__ERC165_init_unchained();
__AccessControl_init_unchained();
}
function __AccessControl_init_unchained() internal initializer {
}
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
StringsUpgradeable.toHexString(uint160(account), 20),
" is missing role ",
StringsUpgradeable.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface IOraclesManager {
/* ========== STRUCTS ========== */
struct OracleInfo {
bool exist; // exist oracle
bool isValid; // is valid oracle
bool required; // without this oracle (DSRM), the transfer will not be confirmed
}
/* ========== EVENTS ========== */
/// @dev Emitted when an oracle is added
/// @param oracle Address of an added oracle
/// @param required Is this oracle's signature required for every transfer
event AddOracle(address oracle, bool required);
/// @dev Emitted when an oracle is updated
/// @param oracle Address of an updated oracle
/// @param required Is this oracle's signature required for every transfer
/// @param isValid Is this oracle valid, i.e. should it be treated as an oracle
event UpdateOracle(address oracle, bool required, bool isValid);
/// @dev Emitted once the submission is confirmed by min required amount of oracles
event DeployApproved(bytes32 deployId);
/// @dev Emitted once the submission is confirmed by min required amount of oracles
event SubmissionApproved(bytes32 submissionId);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControlUpgradeable {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal initializer {
__ERC165_init_unchained();
}
function __ERC165_init_unchained() internal initializer {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (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 IERC165Upgradeable {
/**
* @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);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"AdminBadRole","type":"error"},{"inputs":[],"name":"DeBridgeGateBadRole","type":"error"},{"inputs":[],"name":"DuplicateSignatures","type":"error"},{"inputs":[],"name":"LowMinConfirmations","type":"error"},{"inputs":[],"name":"NotConfirmedByRequiredOracles","type":"error"},{"inputs":[],"name":"NotConfirmedThreshold","type":"error"},{"inputs":[],"name":"OracleAlreadyExist","type":"error"},{"inputs":[],"name":"OracleBadRole","type":"error"},{"inputs":[],"name":"OracleNotFound","type":"error"},{"inputs":[],"name":"SignatureInvalidLength","type":"error"},{"inputs":[],"name":"SignatureInvalidV","type":"error"},{"inputs":[],"name":"SubmissionNotConfirmed","type":"error"},{"inputs":[],"name":"WrongArgument","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"bool","name":"required","type":"bool"}],"name":"AddOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"submissionId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"deployId","type":"bytes32"}],"name":"DeployApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"deployId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"DeployConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"submissionId","type":"bytes32"}],"name":"SubmissionApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"bool","name":"required","type":"bool"},{"indexed":false,"internalType":"bool","name":"isValid","type":"bool"}],"name":"UpdateOracle","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_oracles","type":"address[]"},{"internalType":"bool[]","name":"_required","type":"bool[]"}],"name":"addOracles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"confirmationThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentBlock","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debridgeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"excessConfirmations","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getOracleInfo","outputs":[{"internalType":"bool","name":"exist","type":"bool"},{"internalType":"bool","name":"isValid","type":"bool"},{"internalType":"bool","name":"required","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_minConfirmations","type":"uint8"},{"internalType":"uint8","name":"_confirmationThreshold","type":"uint8"},{"internalType":"uint8","name":"_excessConfirmations","type":"uint8"},{"internalType":"address","name":"_debridgeAddress","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_submissionId","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minConfirmations","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"oracleAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requiredOraclesCount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_debridgeAddress","type":"address"}],"name":"setDebridgeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_excessConfirmations","type":"uint8"}],"name":"setExcessConfirmations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_minConfirmations","type":"uint8"}],"name":"setMinConfirmations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_confirmationThreshold","type":"uint8"}],"name":"setThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"submissionsInBlock","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_submissionId","type":"bytes32"},{"internalType":"bytes","name":"_signatures","type":"bytes"},{"internalType":"uint8","name":"_excessConfirmations","type":"uint8"}],"name":"submit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"bool","name":"_isValid","type":"bool"},{"internalType":"bool","name":"_required","type":"bool"}],"name":"updateOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50600054610100900460ff168061002a575060005460ff16155b6100915760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff161580156100b3576000805461ffff19166101011790555b80156100c5576000805461ff00191690555b50611dff806100d56000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c806391d14854116100de578063c4e7337711610097578063e12ed13c11610071578063e12ed13c146103de578063e5a98603146103f6578063e7c4393e14610409578063fceb17eb1461041657600080fd5b8063c4e7337714610386578063d547741f146103b8578063dc4bfb85146103cb57600080fd5b806391d14854146102de578063965d0a64146102f1578063a217fddf14610304578063b50492261461030c578063b9b556521461031f578063bfdb6b041461033157600080fd5b806332ea039a1161014b57806354fd4d501161012557806354fd4d501461028c578063698efb9514610293578063794a9c29146102a65780637c533fd3146102b957600080fd5b806332ea039a1461025357806336568abe146102665780634425bd9a1461027957600080fd5b806301ffc9a714610193578063140c0b1e146101bb5780631626ba7e146101d0578063248a9ca3146101e35780632f2ff15d146102145780632fa3ab6314610227575b600080fd5b6101a66101a13660046117a8565b610423565b60405190151581526020015b60405180910390f35b6101ce6101c93660046117e8565b61045a565b005b6101a66101de3660046118ba565b6104c8565b6102066101f1366004611901565b60009081526065602052604090206001015490565b6040519081526020016101b2565b6101ce610222366004611931565b61056d565b609a5461023d90610100900464ffffffffff1681565b60405164ffffffffff90911681526020016101b2565b6101ce6102613660046117e8565b610598565b6101ce610274366004611931565b610613565b6101ce610287366004611a03565b610696565b60ca610206565b6101ce6102a1366004611ab9565b610918565b6101ce6102b4366004611b0d565b610a19565b6097546102cc9062010000900460ff1681565b60405160ff90911681526020016101b2565b6101a66102ec366004611931565b610d9f565b6101ce6102ff366004611b50565b610dca565b610206600081565b6101ce61031a366004611b9e565b61120d565b6097546102cc90610100900460ff1681565b61036761033f366004611b9e565b60996020526000908152604090205460ff808216916101008104821691620100009091041683565b60408051931515845291151560208401521515908201526060016101b2565b609a546103a090600160581b90046001600160a01b031681565b6040516001600160a01b0390911681526020016101b2565b6101ce6103c6366004611931565b611276565b6103a06103d9366004611901565b61129c565b609a5461023d90600160301b900464ffffffffff1681565b6101ce6104043660046117e8565b6112c6565b6097546102cc9060ff1681565b609a546102cc9060ff1681565b60006001600160e01b03198216637965db0b60e01b148061045457506301ffc9a760e01b6001600160e01b03198316145b92915050565b610465600033610d9f565b61048257604051636f4720fd60e11b815260040160405180910390fd5b60975460ff90811690821610156104ac5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff9092166101000261ff0019909216919091179055565b6000806000806104d785611328565b925092509250600060016104ea88611367565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa158015610538573d6000803e3d6000fd5b505060408051601f1901516001600160a01b0316600090815260996020522054610100900460ff169550505050505092915050565b60008281526065602052604090206001015461058981336113ba565b610593838361141e565b505050565b6105a3600033610d9f565b6105c057604051636f4720fd60e11b815260040160405180910390fd5b6098546105cf90600290611be5565b6105da906001611bf9565b8160ff1610156105fd5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff191660ff92909216919091179055565b6001600160a01b03811633146106885760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61069282826114a4565b5050565b6106a1600033610d9f565b6106be57604051636f4720fd60e11b815260040160405180910390fd5b80518251146106e057604051634668624160e01b815260040160405180910390fd5b81516098546002916106f191611bf9565b6106fb9190611be5565b610706906001611bf9565b60975460ff16101561072b5760405163412f84c160e11b815260040160405180910390fd5b60005b82518110156105935760006099600085848151811061074f5761074f611c0c565b6020908102919091018101516001600160a01b03168252810191909152604001600020805490915060ff161561079857604051633ad24c0760e11b815260040160405180910390fd5b60988483815181106107ac576107ac611c0c565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b0390921691909117905582518390839081106107fb576107fb611c0c565b602002602001015115610840576001609760028282829054906101000a900460ff166108279190611c22565b92506101000a81548160ff021916908360ff1602179055505b805461ffff1916610101178155825183908390811061086157610861611c0c565b60209081029190910101518154901515620100000262ff00001990911617815583517fe755f450de2082b1e2a5be83219122e863839acc705c368b6e119432edfc360e908590849081106108b7576108b7611c0c565b60200260200101518484815181106108d1576108d1611c0c565b60200260200101516040516108fd9291906001600160a01b039290921682521515602082015260400190565b60405180910390a1508061091081611c3b565b91505061072e565b600054610100900460ff1680610931575060005460ff16155b6109945760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161067f565b600054610100900460ff161580156109b6576000805461ffff19166101011790555b6109c0858461150b565b609a80546001600160a01b038416600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffff0090911660ff8716171790558015610a12576000805461ff00191690555b5050505050565b610a24600033610d9f565b610a4157604051636f4720fd60e11b815260040160405180910390fd5b81158015610a4c5750805b15610a6a57604051634668624160e01b815260040160405180910390fd5b6001600160a01b0383166000908152609960205260409020805460ff16610aa457604051630b0a0e0d60e21b815260040160405180910390fd5b805462010000900460ff168015610ab9575081155b15610afa576001609760028282829054906101000a900460ff16610add9190611c54565b92506101000a81548160ff021916908360ff160217905550610b4c565b805462010000900460ff16158015610b0f5750815b15610b4c576001609760028282829054906101000a900460ff16610b339190611c22565b92506101000a81548160ff021916908360ff1602179055505b8054610100900460ff168015610b60575082155b15610c735760005b609854811015610c6d57846001600160a01b031660988281548110610b8f57610b8f611c0c565b6000918252602090912001546001600160a01b031603610c5b5760988054610bb990600190611c6d565b81548110610bc957610bc9611c0c565b600091825260209091200154609880546001600160a01b039092169183908110610bf557610bf5611c0c565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506098805480610c3457610c34611c80565b600082815260209020810160001990810180546001600160a01b0319169055019055610c6d565b80610c6581611c3b565b915050610b68565b50610d23565b8054610100900460ff16158015610c875750825b15610d2357609854600290610c9d906001611bf9565b610ca79190611be5565b610cb2906001611bf9565b60975460ff161015610cd75760405163412f84c160e11b815260040160405180910390fd5b609880546001810182556000919091527f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d8140180546001600160a01b0319166001600160a01b0386161790555b805462ffff00191661010084151590810262ff000019169190911762010000841515908102919091178355604080516001600160a01b038816815260208101929092528101919091527fd0a47d00eff59bee6da649bbe44f1e639db18f184bb4a80783cf8afd2a41e4609060600160405180910390a150505050565b60009182526065602090815260408084206001600160a01b0393909316845291905290205460ff1690565b609a54600160581b90046001600160a01b03163314610dfc576040516388a38fa160e01b815260040160405180910390fd5b60975460009060ff90811690831611610e1a5760975460ff16610e1c565b815b90506000806000610e2c86611564565b905060008167ffffffffffffffff811115610e4957610e49611803565b604051908082528060200260200182016040528015610e72578160200160208202803683370190505b50905060005b8281101561108e5760008080610e99610e92856041611c96565b8c9061158e565b92509250925060006001610eac8e611367565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa158015610efa573d6000803e3d6000fd5b505060408051601f1901516001600160a01b038116600090815260996020529190912054909250610100900460ff161590506110775760005b85811015610f9857816001600160a01b0316878281518110610f5757610f57611c0c565b60200260200101516001600160a01b031603610f86576040516317ab4f2360e11b815260040160405180910390fd5b80610f9081611c3b565b915050610f33565b5080868681518110610fac57610fac611c0c565b6001600160a01b0390921660209283029190910190910152610fcf600189611c22565b604080518f81526001600160a01b03841660208201529199507fd4964a7cd99f5c1fa8f2420fb5e1d3bd26eadf16e2658cf2e29a67dfda38601e910160405180910390a16001600160a01b03811660009081526099602052604090205462010000900460ff16156110485761104560018a611bf9565b98505b8960ff168860ff1610158015611069575060975462010000900460ff168910155b15611077575050505061108e565b50505050808061108690611c3b565b915050610e78565b5060975462010000900460ff1684146110ba576040516382635e4d60e01b815260040160405180910390fd5b60975460ff9081169084161061119357609a5464ffffffffff438116600160301b909204160361112c576001609a60018282829054906101000a900464ffffffffff166111079190611cad565b92506101000a81548164ffffffffff021916908364ffffffffff16021790555061115f565b609a805465ffffffffff001964ffffffffff4316600160301b02166affffffffffffffffffff0019909116176101001790555b6040518881527f2a6b4960c287d4d53a338f9c9a9f830f37e7b66e67a0a958f68be89a4eeb939d9060200160405180910390a15b609a5460ff811661010090910464ffffffffff1611156111dc5760975460ff610100909104811690841610156111dc576040516323d8dc8760e01b815260040160405180910390fd5b8460ff168360ff161015611203576040516374bb49d560e01b815260040160405180910390fd5b5050505050505050565b611218600033610d9f565b61123557604051636f4720fd60e11b815260040160405180910390fd5b609a80546001600160a01b03909216600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055565b60008281526065602052604090206001015461129281336113ba565b61059383836114a4565b609881815481106112ac57600080fd5b6000918252602090912001546001600160a01b0316905081565b6112d1600033610d9f565b6112ee57604051636f4720fd60e11b815260040160405180910390fd5b8060ff1660000361131257604051634668624160e01b815260040160405180910390fd5b609a805460ff191660ff92909216919091179055565b6000806000835160411461134f5760405163bb5ee95b60e01b815260040160405180910390fd5b61135a84600061158e565b9250925092509193909250565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b6113c48282610d9f565b610692576113dc816001600160a01b031660146115fb565b6113e78360206115fb565b6040516020016113f8929190611cf6565b60408051601f198184030181529082905262461bcd60e51b825261067f91600401611d6b565b6114288282610d9f565b6106925760008281526065602090815260408083206001600160a01b03851684529091529020805460ff191660011790556114603390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6114ae8282610d9f565b156106925760008281526065602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60ff8216158061152057508160ff168160ff16105b1561153e5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff8381166101000261ffff199092169085161717905561069260003361179e565b6000604182516115749190611d9e565b15611580576000610454565b604182516104549190611be5565b8181016020810151604082015160419092015190919060ff16601b8110156115be576115bb601b82611c22565b90505b8060ff16601b141580156115d657508060ff16601c14155b156115f457604051630633a0a560e21b815260040160405180910390fd5b9250925092565b6060600061160a836002611c96565b611615906002611bf9565b67ffffffffffffffff81111561162d5761162d611803565b6040519080825280601f01601f191660200182016040528015611657576020820181803683370190505b509050600360fc1b8160008151811061167257611672611c0c565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106116a1576116a1611c0c565b60200101906001600160f81b031916908160001a90535060006116c5846002611c96565b6116d0906001611bf9565b90505b6001811115611748576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061170457611704611c0c565b1a60f81b82828151811061171a5761171a611c0c565b60200101906001600160f81b031916908160001a90535060049490941c9361174181611db2565b90506116d3565b5083156117975760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161067f565b9392505050565b610692828261141e565b6000602082840312156117ba57600080fd5b81356001600160e01b03198116811461179757600080fd5b803560ff811681146117e357600080fd5b919050565b6000602082840312156117fa57600080fd5b611797826117d2565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561184257611842611803565b604052919050565b600082601f83011261185b57600080fd5b813567ffffffffffffffff81111561187557611875611803565b611888601f8201601f1916602001611819565b81815284602083860101111561189d57600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156118cd57600080fd5b82359150602083013567ffffffffffffffff8111156118eb57600080fd5b6118f78582860161184a565b9150509250929050565b60006020828403121561191357600080fd5b5035919050565b80356001600160a01b03811681146117e357600080fd5b6000806040838503121561194457600080fd5b823591506119546020840161191a565b90509250929050565b600067ffffffffffffffff82111561197757611977611803565b5060051b60200190565b803580151581146117e357600080fd5b600082601f8301126119a257600080fd5b813560206119b76119b28361195d565b611819565b82815260059290921b840181019181810190868411156119d657600080fd5b8286015b848110156119f8576119eb81611981565b83529183019183016119da565b509695505050505050565b60008060408385031215611a1657600080fd5b823567ffffffffffffffff80821115611a2e57600080fd5b818501915085601f830112611a4257600080fd5b81356020611a526119b28361195d565b82815260059290921b84018101918181019089841115611a7157600080fd5b948201945b83861015611a9657611a878661191a565b82529482019490820190611a76565b96505086013592505080821115611aac57600080fd5b506118f785828601611991565b60008060008060808587031215611acf57600080fd5b611ad8856117d2565b9350611ae6602086016117d2565b9250611af4604086016117d2565b9150611b026060860161191a565b905092959194509250565b600080600060608486031215611b2257600080fd5b611b2b8461191a565b9250611b3960208501611981565b9150611b4760408501611981565b90509250925092565b600080600060608486031215611b6557600080fd5b83359250602084013567ffffffffffffffff811115611b8357600080fd5b611b8f8682870161184a565b925050611b47604085016117d2565b600060208284031215611bb057600080fd5b6117978261191a565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082611bf457611bf4611bb9565b500490565b8082018082111561045457610454611bcf565b634e487b7160e01b600052603260045260246000fd5b60ff818116838216019081111561045457610454611bcf565b600060018201611c4d57611c4d611bcf565b5060010190565b60ff828116828216039081111561045457610454611bcf565b8181038181111561045457610454611bcf565b634e487b7160e01b600052603160045260246000fd5b808202811582820484141761045457610454611bcf565b64ffffffffff818116838216019080821115611ccb57611ccb611bcf565b5092915050565b60005b83811015611ced578181015183820152602001611cd5565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611d2e816017850160208801611cd2565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351611d5f816028840160208801611cd2565b01602801949350505050565b6020815260008251806020840152611d8a816040850160208701611cd2565b601f01601f19169190910160400192915050565b600082611dad57611dad611bb9565b500690565b600081611dc157611dc1611bcf565b50600019019056fea2646970667358221220fa23adb07ff882d9cb70637c31c98d796e314f33a2381155a9ad26cb5fc0ea0964736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061018e5760003560e01c806391d14854116100de578063c4e7337711610097578063e12ed13c11610071578063e12ed13c146103de578063e5a98603146103f6578063e7c4393e14610409578063fceb17eb1461041657600080fd5b8063c4e7337714610386578063d547741f146103b8578063dc4bfb85146103cb57600080fd5b806391d14854146102de578063965d0a64146102f1578063a217fddf14610304578063b50492261461030c578063b9b556521461031f578063bfdb6b041461033157600080fd5b806332ea039a1161014b57806354fd4d501161012557806354fd4d501461028c578063698efb9514610293578063794a9c29146102a65780637c533fd3146102b957600080fd5b806332ea039a1461025357806336568abe146102665780634425bd9a1461027957600080fd5b806301ffc9a714610193578063140c0b1e146101bb5780631626ba7e146101d0578063248a9ca3146101e35780632f2ff15d146102145780632fa3ab6314610227575b600080fd5b6101a66101a13660046117a8565b610423565b60405190151581526020015b60405180910390f35b6101ce6101c93660046117e8565b61045a565b005b6101a66101de3660046118ba565b6104c8565b6102066101f1366004611901565b60009081526065602052604090206001015490565b6040519081526020016101b2565b6101ce610222366004611931565b61056d565b609a5461023d90610100900464ffffffffff1681565b60405164ffffffffff90911681526020016101b2565b6101ce6102613660046117e8565b610598565b6101ce610274366004611931565b610613565b6101ce610287366004611a03565b610696565b60ca610206565b6101ce6102a1366004611ab9565b610918565b6101ce6102b4366004611b0d565b610a19565b6097546102cc9062010000900460ff1681565b60405160ff90911681526020016101b2565b6101a66102ec366004611931565b610d9f565b6101ce6102ff366004611b50565b610dca565b610206600081565b6101ce61031a366004611b9e565b61120d565b6097546102cc90610100900460ff1681565b61036761033f366004611b9e565b60996020526000908152604090205460ff808216916101008104821691620100009091041683565b60408051931515845291151560208401521515908201526060016101b2565b609a546103a090600160581b90046001600160a01b031681565b6040516001600160a01b0390911681526020016101b2565b6101ce6103c6366004611931565b611276565b6103a06103d9366004611901565b61129c565b609a5461023d90600160301b900464ffffffffff1681565b6101ce6104043660046117e8565b6112c6565b6097546102cc9060ff1681565b609a546102cc9060ff1681565b60006001600160e01b03198216637965db0b60e01b148061045457506301ffc9a760e01b6001600160e01b03198316145b92915050565b610465600033610d9f565b61048257604051636f4720fd60e11b815260040160405180910390fd5b60975460ff90811690821610156104ac5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff9092166101000261ff0019909216919091179055565b6000806000806104d785611328565b925092509250600060016104ea88611367565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa158015610538573d6000803e3d6000fd5b505060408051601f1901516001600160a01b0316600090815260996020522054610100900460ff169550505050505092915050565b60008281526065602052604090206001015461058981336113ba565b610593838361141e565b505050565b6105a3600033610d9f565b6105c057604051636f4720fd60e11b815260040160405180910390fd5b6098546105cf90600290611be5565b6105da906001611bf9565b8160ff1610156105fd5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff191660ff92909216919091179055565b6001600160a01b03811633146106885760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61069282826114a4565b5050565b6106a1600033610d9f565b6106be57604051636f4720fd60e11b815260040160405180910390fd5b80518251146106e057604051634668624160e01b815260040160405180910390fd5b81516098546002916106f191611bf9565b6106fb9190611be5565b610706906001611bf9565b60975460ff16101561072b5760405163412f84c160e11b815260040160405180910390fd5b60005b82518110156105935760006099600085848151811061074f5761074f611c0c565b6020908102919091018101516001600160a01b03168252810191909152604001600020805490915060ff161561079857604051633ad24c0760e11b815260040160405180910390fd5b60988483815181106107ac576107ac611c0c565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b0390921691909117905582518390839081106107fb576107fb611c0c565b602002602001015115610840576001609760028282829054906101000a900460ff166108279190611c22565b92506101000a81548160ff021916908360ff1602179055505b805461ffff1916610101178155825183908390811061086157610861611c0c565b60209081029190910101518154901515620100000262ff00001990911617815583517fe755f450de2082b1e2a5be83219122e863839acc705c368b6e119432edfc360e908590849081106108b7576108b7611c0c565b60200260200101518484815181106108d1576108d1611c0c565b60200260200101516040516108fd9291906001600160a01b039290921682521515602082015260400190565b60405180910390a1508061091081611c3b565b91505061072e565b600054610100900460ff1680610931575060005460ff16155b6109945760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161067f565b600054610100900460ff161580156109b6576000805461ffff19166101011790555b6109c0858461150b565b609a80546001600160a01b038416600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffff0090911660ff8716171790558015610a12576000805461ff00191690555b5050505050565b610a24600033610d9f565b610a4157604051636f4720fd60e11b815260040160405180910390fd5b81158015610a4c5750805b15610a6a57604051634668624160e01b815260040160405180910390fd5b6001600160a01b0383166000908152609960205260409020805460ff16610aa457604051630b0a0e0d60e21b815260040160405180910390fd5b805462010000900460ff168015610ab9575081155b15610afa576001609760028282829054906101000a900460ff16610add9190611c54565b92506101000a81548160ff021916908360ff160217905550610b4c565b805462010000900460ff16158015610b0f5750815b15610b4c576001609760028282829054906101000a900460ff16610b339190611c22565b92506101000a81548160ff021916908360ff1602179055505b8054610100900460ff168015610b60575082155b15610c735760005b609854811015610c6d57846001600160a01b031660988281548110610b8f57610b8f611c0c565b6000918252602090912001546001600160a01b031603610c5b5760988054610bb990600190611c6d565b81548110610bc957610bc9611c0c565b600091825260209091200154609880546001600160a01b039092169183908110610bf557610bf5611c0c565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506098805480610c3457610c34611c80565b600082815260209020810160001990810180546001600160a01b0319169055019055610c6d565b80610c6581611c3b565b915050610b68565b50610d23565b8054610100900460ff16158015610c875750825b15610d2357609854600290610c9d906001611bf9565b610ca79190611be5565b610cb2906001611bf9565b60975460ff161015610cd75760405163412f84c160e11b815260040160405180910390fd5b609880546001810182556000919091527f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d8140180546001600160a01b0319166001600160a01b0386161790555b805462ffff00191661010084151590810262ff000019169190911762010000841515908102919091178355604080516001600160a01b038816815260208101929092528101919091527fd0a47d00eff59bee6da649bbe44f1e639db18f184bb4a80783cf8afd2a41e4609060600160405180910390a150505050565b60009182526065602090815260408084206001600160a01b0393909316845291905290205460ff1690565b609a54600160581b90046001600160a01b03163314610dfc576040516388a38fa160e01b815260040160405180910390fd5b60975460009060ff90811690831611610e1a5760975460ff16610e1c565b815b90506000806000610e2c86611564565b905060008167ffffffffffffffff811115610e4957610e49611803565b604051908082528060200260200182016040528015610e72578160200160208202803683370190505b50905060005b8281101561108e5760008080610e99610e92856041611c96565b8c9061158e565b92509250925060006001610eac8e611367565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa158015610efa573d6000803e3d6000fd5b505060408051601f1901516001600160a01b038116600090815260996020529190912054909250610100900460ff161590506110775760005b85811015610f9857816001600160a01b0316878281518110610f5757610f57611c0c565b60200260200101516001600160a01b031603610f86576040516317ab4f2360e11b815260040160405180910390fd5b80610f9081611c3b565b915050610f33565b5080868681518110610fac57610fac611c0c565b6001600160a01b0390921660209283029190910190910152610fcf600189611c22565b604080518f81526001600160a01b03841660208201529199507fd4964a7cd99f5c1fa8f2420fb5e1d3bd26eadf16e2658cf2e29a67dfda38601e910160405180910390a16001600160a01b03811660009081526099602052604090205462010000900460ff16156110485761104560018a611bf9565b98505b8960ff168860ff1610158015611069575060975462010000900460ff168910155b15611077575050505061108e565b50505050808061108690611c3b565b915050610e78565b5060975462010000900460ff1684146110ba576040516382635e4d60e01b815260040160405180910390fd5b60975460ff9081169084161061119357609a5464ffffffffff438116600160301b909204160361112c576001609a60018282829054906101000a900464ffffffffff166111079190611cad565b92506101000a81548164ffffffffff021916908364ffffffffff16021790555061115f565b609a805465ffffffffff001964ffffffffff4316600160301b02166affffffffffffffffffff0019909116176101001790555b6040518881527f2a6b4960c287d4d53a338f9c9a9f830f37e7b66e67a0a958f68be89a4eeb939d9060200160405180910390a15b609a5460ff811661010090910464ffffffffff1611156111dc5760975460ff610100909104811690841610156111dc576040516323d8dc8760e01b815260040160405180910390fd5b8460ff168360ff161015611203576040516374bb49d560e01b815260040160405180910390fd5b5050505050505050565b611218600033610d9f565b61123557604051636f4720fd60e11b815260040160405180910390fd5b609a80546001600160a01b03909216600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055565b60008281526065602052604090206001015461129281336113ba565b61059383836114a4565b609881815481106112ac57600080fd5b6000918252602090912001546001600160a01b0316905081565b6112d1600033610d9f565b6112ee57604051636f4720fd60e11b815260040160405180910390fd5b8060ff1660000361131257604051634668624160e01b815260040160405180910390fd5b609a805460ff191660ff92909216919091179055565b6000806000835160411461134f5760405163bb5ee95b60e01b815260040160405180910390fd5b61135a84600061158e565b9250925092509193909250565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b6113c48282610d9f565b610692576113dc816001600160a01b031660146115fb565b6113e78360206115fb565b6040516020016113f8929190611cf6565b60408051601f198184030181529082905262461bcd60e51b825261067f91600401611d6b565b6114288282610d9f565b6106925760008281526065602090815260408083206001600160a01b03851684529091529020805460ff191660011790556114603390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6114ae8282610d9f565b156106925760008281526065602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60ff8216158061152057508160ff168160ff16105b1561153e5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff8381166101000261ffff199092169085161717905561069260003361179e565b6000604182516115749190611d9e565b15611580576000610454565b604182516104549190611be5565b8181016020810151604082015160419092015190919060ff16601b8110156115be576115bb601b82611c22565b90505b8060ff16601b141580156115d657508060ff16601c14155b156115f457604051630633a0a560e21b815260040160405180910390fd5b9250925092565b6060600061160a836002611c96565b611615906002611bf9565b67ffffffffffffffff81111561162d5761162d611803565b6040519080825280601f01601f191660200182016040528015611657576020820181803683370190505b509050600360fc1b8160008151811061167257611672611c0c565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106116a1576116a1611c0c565b60200101906001600160f81b031916908160001a90535060006116c5846002611c96565b6116d0906001611bf9565b90505b6001811115611748576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061170457611704611c0c565b1a60f81b82828151811061171a5761171a611c0c565b60200101906001600160f81b031916908160001a90535060049490941c9361174181611db2565b90506116d3565b5083156117975760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161067f565b9392505050565b610692828261141e565b6000602082840312156117ba57600080fd5b81356001600160e01b03198116811461179757600080fd5b803560ff811681146117e357600080fd5b919050565b6000602082840312156117fa57600080fd5b611797826117d2565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561184257611842611803565b604052919050565b600082601f83011261185b57600080fd5b813567ffffffffffffffff81111561187557611875611803565b611888601f8201601f1916602001611819565b81815284602083860101111561189d57600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156118cd57600080fd5b82359150602083013567ffffffffffffffff8111156118eb57600080fd5b6118f78582860161184a565b9150509250929050565b60006020828403121561191357600080fd5b5035919050565b80356001600160a01b03811681146117e357600080fd5b6000806040838503121561194457600080fd5b823591506119546020840161191a565b90509250929050565b600067ffffffffffffffff82111561197757611977611803565b5060051b60200190565b803580151581146117e357600080fd5b600082601f8301126119a257600080fd5b813560206119b76119b28361195d565b611819565b82815260059290921b840181019181810190868411156119d657600080fd5b8286015b848110156119f8576119eb81611981565b83529183019183016119da565b509695505050505050565b60008060408385031215611a1657600080fd5b823567ffffffffffffffff80821115611a2e57600080fd5b818501915085601f830112611a4257600080fd5b81356020611a526119b28361195d565b82815260059290921b84018101918181019089841115611a7157600080fd5b948201945b83861015611a9657611a878661191a565b82529482019490820190611a76565b96505086013592505080821115611aac57600080fd5b506118f785828601611991565b60008060008060808587031215611acf57600080fd5b611ad8856117d2565b9350611ae6602086016117d2565b9250611af4604086016117d2565b9150611b026060860161191a565b905092959194509250565b600080600060608486031215611b2257600080fd5b611b2b8461191a565b9250611b3960208501611981565b9150611b4760408501611981565b90509250925092565b600080600060608486031215611b6557600080fd5b83359250602084013567ffffffffffffffff811115611b8357600080fd5b611b8f8682870161184a565b925050611b47604085016117d2565b600060208284031215611bb057600080fd5b6117978261191a565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082611bf457611bf4611bb9565b500490565b8082018082111561045457610454611bcf565b634e487b7160e01b600052603260045260246000fd5b60ff818116838216019081111561045457610454611bcf565b600060018201611c4d57611c4d611bcf565b5060010190565b60ff828116828216039081111561045457610454611bcf565b8181038181111561045457610454611bcf565b634e487b7160e01b600052603160045260246000fd5b808202811582820484141761045457610454611bcf565b64ffffffffff818116838216019080821115611ccb57611ccb611bcf565b5092915050565b60005b83811015611ced578181015183820152602001611cd5565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611d2e816017850160208801611cd2565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351611d5f816028840160208801611cd2565b01602801949350505050565b6020815260008251806020840152611d8a816040850160208701611cd2565b601f01601f19169190910160400192915050565b600082611dad57611dad611bb9565b500690565b600081611dc157611dc1611bcf565b50600019019056fea2646970667358221220fa23adb07ff882d9cb70637c31c98d796e314f33a2381155a9ad26cb5fc0ea0964736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.