Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 111620564 | 857 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Authorizer
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.8.17;
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import '@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol';
import './AuthorizedHelpers.sol';
import './interfaces/IAuthorizer.sol';
/**
* @title Authorizer
* @dev Authorization mechanism based on permissions
*/
contract Authorizer is IAuthorizer, AuthorizedHelpers, Initializable, ReentrancyGuardUpgradeable {
// Constant used to denote that a permission is open to anyone
address public constant ANYONE = address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF);
// Constant used to denote that a permission is open to anywhere
address public constant ANYWHERE = address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF);
// Param logic op types
enum Op {
NONE,
EQ,
NEQ,
GT,
LT,
GTE,
LTE
}
/**
* @dev Permission information
* @param authorized Whether it is authorized or not
* @param params List of params defined for each permission
*/
struct Permission {
bool authorized;
Param[] params;
}
/**
* @dev Permissions list information
* @param count Number of permissions
* @param permissions List of permissions indexed by what
*/
struct PermissionsList {
uint256 count;
mapping (bytes4 => Permission) permissions;
}
// List of permissions indexed by who => where
mapping (address => mapping (address => PermissionsList)) private _permissionsLists;
/**
* @dev Creates a new authorizer contract. Note that initializers are disabled at creation time.
*/
constructor() {
_disableInitializers();
}
/**
* @dev Initialization function.
* @param owners List of addresses that will be allowed to authorize and unauthorize permissions
*/
function initialize(address[] memory owners) external virtual initializer {
__ReentrancyGuard_init();
for (uint256 i = 0; i < owners.length; i++) {
_authorize(owners[i], address(this), IAuthorizer.authorize.selector, new Param[](0));
_authorize(owners[i], address(this), IAuthorizer.unauthorize.selector, new Param[](0));
}
}
/**
* @dev Tells whether `who` has any permission on `where`
* @param who Address asking permission for
* @param where Target address asking permission for
*/
function hasPermissions(address who, address where) external view override returns (bool) {
return _permissionsLists[who][where].count > 0;
}
/**
* @dev Tells the number of permissions `who` has on `where`
* @param who Address asking permission for
* @param where Target address asking permission for
*/
function getPermissionsLength(address who, address where) external view override returns (uint256) {
return _permissionsLists[who][where].count;
}
/**
* @dev Tells whether `who` has permission to call `what` on `where`. Note `how` is not evaluated here,
* which means `who` might be authorized on or not depending on the call at the moment of the execution
* @param who Address asking permission for
* @param where Target address asking permission for
* @param what Function selector asking permission for
*/
function hasPermission(address who, address where, bytes4 what) external view override returns (bool) {
return _permissionsLists[who][where].permissions[what].authorized;
}
/**
* @dev Tells whether `who` is allowed to call `what` on `where` with `how`
* @param who Address asking permission for
* @param where Target address asking permission for
* @param what Function selector asking permission for
* @param how Params asking permission for
*/
function isAuthorized(address who, address where, bytes4 what, uint256[] memory how)
public
view
override
returns (bool)
{
if (_isAuthorized(who, where, what, how)) return true; // direct permission
if (_isAuthorized(ANYONE, where, what, how)) return true; // anyone is allowed
if (_isAuthorized(who, ANYWHERE, what, how)) return true; // direct permission on anywhere
if (_isAuthorized(ANYONE, ANYWHERE, what, how)) return true; // anyone allowed anywhere
return false;
}
/**
* @dev Tells the params set for a given permission
* @param who Address asking permission params of
* @param where Target address asking permission params of
* @param what Function selector asking permission params of
*/
function getPermissionParams(address who, address where, bytes4 what)
external
view
override
returns (Param[] memory)
{
return _permissionsLists[who][where].permissions[what].params;
}
/**
* @dev Executes a list of permission changes. Sender must be authorized.
* @param changes List of permission changes to be executed
*/
function changePermissions(PermissionChange[] memory changes) external override {
for (uint256 i = 0; i < changes.length; i++) {
PermissionChange memory change = changes[i];
for (uint256 j = 0; j < change.grants.length; j++) {
GrantPermission memory grant = change.grants[j];
authorize(grant.who, change.where, grant.what, grant.params);
}
for (uint256 j = 0; j < change.revokes.length; j++) {
RevokePermission memory revoke = change.revokes[j];
unauthorize(revoke.who, change.where, revoke.what);
}
}
}
/**
* @dev Authorizes `who` to call `what` on `where` restricted by `params`. Sender must be authorized.
* @param who Address to be authorized
* @param where Target address to be granted for
* @param what Function selector to be granted
* @param params Optional params to restrict a permission attempt
*/
function authorize(address who, address where, bytes4 what, Param[] memory params) public override nonReentrant {
uint256[] memory how = authParams(who, where, what);
_authenticate(msg.sender, IAuthorizer.authorize.selector, how);
_authorize(who, where, what, params);
}
/**
* @dev Unauthorizes `who` to call `what` on `where`. Sender must be authorized.
* @param who Address to be authorized
* @param where Target address to be revoked for
* @param what Function selector to be revoked
*/
function unauthorize(address who, address where, bytes4 what) public override nonReentrant {
uint256[] memory how = authParams(who, where, what);
_authenticate(msg.sender, IAuthorizer.unauthorize.selector, how);
_unauthorize(who, where, what);
}
/**
* @dev Validates whether `who` is authorized to call `what` with `how`
* @param who Address asking permission for
* @param what Function selector asking permission for
* @param how Params asking permission for
*/
function _authenticate(address who, bytes4 what, uint256[] memory how) internal view {
bool allowed = isAuthorized(who, address(this), what, how);
if (!allowed) revert AuthorizerSenderNotAllowed(who, address(this), what, how);
}
/**
* @dev Tells whether `who` is allowed to call `what` on `where` with `how`
* @param who Address asking permission for
* @param where Target address asking permission for
* @param what Function selector asking permission for
* @param how Params asking permission for
*/
function _isAuthorized(address who, address where, bytes4 what, uint256[] memory how) internal view returns (bool) {
Permission storage permission = _permissionsLists[who][where].permissions[what];
return permission.authorized && _evalParams(permission.params, how);
}
/**
* @dev Authorizes `who` to call `what` on `where` restricted by `params`
* @param who Address to be authorized
* @param where Target address to be granted for
* @param what Function selector to be granted
* @param params Optional params to restrict a permission attempt
*/
function _authorize(address who, address where, bytes4 what, Param[] memory params) internal {
PermissionsList storage list = _permissionsLists[who][where];
Permission storage permission = list.permissions[what];
if (!permission.authorized) list.count++;
permission.authorized = true;
delete permission.params;
for (uint256 i = 0; i < params.length; i++) permission.params.push(params[i]);
emit Authorized(who, where, what, params);
}
/**
* @dev Unauthorizes `who` to call `what` on `where`
* @param who Address to be authorized
* @param where Target address to be revoked for
* @param what Function selector to be revoked
*/
function _unauthorize(address who, address where, bytes4 what) internal {
PermissionsList storage list = _permissionsLists[who][where];
Permission storage permission = list.permissions[what];
if (permission.authorized) list.count--;
delete list.permissions[what];
emit Unauthorized(who, where, what);
}
/**
* @dev Evaluates a list of params defined for a permission against a list of values given by a call
* @param params List of expected params
* @param how List of actual given values
* @return True if all the given values hold against the list of params
*/
function _evalParams(Param[] memory params, uint256[] memory how) private pure returns (bool) {
for (uint256 i = 0; i < params.length; i++) {
Param memory param = params[i];
if ((i < how.length && !_evalParam(param, how[i])) || (i >= how.length && Op(param.op) != Op.NONE)) {
return false;
}
}
return true;
}
/**
* @dev Evaluates a single param defined for a permission against a single value
* @param param Expected params
* @param how Actual given value
* @return True if the given value hold against the expected param
*/
function _evalParam(Param memory param, uint256 how) private pure returns (bool) {
if (Op(param.op) == Op.NONE) return true;
if (Op(param.op) == Op.EQ) return how == param.value;
if (Op(param.op) == Op.NEQ) return how != param.value;
if (Op(param.op) == Op.GT) return how > param.value;
if (Op(param.op) == Op.LT) return how < param.value;
if (Op(param.op) == Op.GTE) return how >= param.value;
if (Op(param.op) == Op.LTE) return how <= param.value;
revert AuthorizerInvalidParamOp(param.op);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @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 proxied contracts do not make use of 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.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* 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 prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.8.17;
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import './AuthorizedHelpers.sol';
import './interfaces/IAuthorized.sol';
import './interfaces/IAuthorizer.sol';
/**
* @title Authorized
* @dev Implementation using an authorizer as its access-control mechanism. It offers `auth` and `authP` modifiers to
* tag its own functions in order to control who can access them against the authorizer referenced.
*/
contract Authorized is IAuthorized, Initializable, AuthorizedHelpers {
// Authorizer reference
address public override authorizer;
/**
* @dev Modifier that should be used to tag protected functions
*/
modifier auth() {
_authenticate(msg.sender, msg.sig);
_;
}
/**
* @dev Modifier that should be used to tag protected functions with params
*/
modifier authP(uint256[] memory params) {
_authenticate(msg.sender, msg.sig, params);
_;
}
/**
* @dev Creates a new authorized contract. Note that initializers are disabled at creation time.
*/
constructor() {
_disableInitializers();
}
/**
* @dev Initializes the authorized contract. It does call upper contracts initializers.
* @param _authorizer Address of the authorizer to be set
*/
function __Authorized_init(address _authorizer) internal onlyInitializing {
__Authorized_init_unchained(_authorizer);
}
/**
* @dev Initializes the authorized contract. It does not call upper contracts initializers.
* @param _authorizer Address of the authorizer to be set
*/
function __Authorized_init_unchained(address _authorizer) internal onlyInitializing {
authorizer = _authorizer;
}
/**
* @dev Reverts if `who` is not allowed to call `what`
* @param who Address to be authenticated
* @param what Function selector to be authenticated
*/
function _authenticate(address who, bytes4 what) internal view {
_authenticate(who, what, new uint256[](0));
}
/**
* @dev Reverts if `who` is not allowed to call `what` with `how`
* @param who Address to be authenticated
* @param what Function selector to be authenticated
* @param how Params to be authenticated
*/
function _authenticate(address who, bytes4 what, uint256[] memory how) internal view {
if (!_isAuthorized(who, what, how)) revert AuthSenderNotAllowed(who, what, how);
}
/**
* @dev Tells whether `who` has any permission on this contract
* @param who Address asking permissions for
*/
function _hasPermissions(address who) internal view returns (bool) {
return IAuthorizer(authorizer).hasPermissions(who, address(this));
}
/**
* @dev Tells whether `who` is allowed to call `what`
* @param who Address asking permission for
* @param what Function selector asking permission for
*/
function _isAuthorized(address who, bytes4 what) internal view returns (bool) {
return _isAuthorized(who, what, new uint256[](0));
}
/**
* @dev Tells whether `who` is allowed to call `what` with `how`
* @param who Address asking permission for
* @param what Function selector asking permission for
* @param how Params asking permission for
*/
function _isAuthorized(address who, bytes4 what, uint256[] memory how) internal view returns (bool) {
return IAuthorizer(authorizer).isAuthorized(who, address(this), what, how);
}
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.8.17;
/**
* @title AuthorizedHelpers
* @dev Syntax sugar methods to operate with authorizer params easily
*/
contract AuthorizedHelpers {
function authParams(address p1) internal pure returns (uint256[] memory r) {
return authParams(uint256(uint160(p1)));
}
function authParams(bytes32 p1) internal pure returns (uint256[] memory r) {
return authParams(uint256(p1));
}
function authParams(uint256 p1) internal pure returns (uint256[] memory r) {
r = new uint256[](1);
r[0] = p1;
}
function authParams(address p1, bool p2) internal pure returns (uint256[] memory r) {
r = new uint256[](2);
r[0] = uint256(uint160(p1));
r[1] = p2 ? 1 : 0;
}
function authParams(address p1, uint256 p2) internal pure returns (uint256[] memory r) {
r = new uint256[](2);
r[0] = uint256(uint160(p1));
r[1] = p2;
}
function authParams(address p1, address p2) internal pure returns (uint256[] memory r) {
r = new uint256[](2);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
}
function authParams(bytes32 p1, bytes32 p2) internal pure returns (uint256[] memory r) {
r = new uint256[](2);
r[0] = uint256(p1);
r[1] = uint256(p2);
}
function authParams(address p1, address p2, uint256 p3) internal pure returns (uint256[] memory r) {
r = new uint256[](3);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
r[2] = p3;
}
function authParams(address p1, address p2, address p3) internal pure returns (uint256[] memory r) {
r = new uint256[](3);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
r[2] = uint256(uint160(p3));
}
function authParams(address p1, address p2, bytes4 p3) internal pure returns (uint256[] memory r) {
r = new uint256[](3);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
r[2] = uint256(uint32(p3));
}
function authParams(address p1, uint256 p2, uint256 p3) internal pure returns (uint256[] memory r) {
r = new uint256[](3);
r[0] = uint256(uint160(p1));
r[1] = p2;
r[2] = p3;
}
function authParams(uint256 p1, uint256 p2, uint256 p3, uint256 p4) internal pure returns (uint256[] memory r) {
r = new uint256[](4);
r[0] = p1;
r[1] = p2;
r[2] = p3;
r[3] = p4;
}
function authParams(address p1, address p2, uint256 p3, uint256 p4) internal pure returns (uint256[] memory r) {
r = new uint256[](4);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
r[2] = p3;
r[3] = p4;
}
function authParams(address p1, uint256 p2, uint256 p3, uint256 p4) internal pure returns (uint256[] memory r) {
r = new uint256[](4);
r[0] = uint256(uint160(p1));
r[1] = p2;
r[2] = p3;
r[3] = p4;
}
function authParams(bytes32 p1, address p2, uint256 p3, bool p4) internal pure returns (uint256[] memory r) {
r = new uint256[](4);
r[0] = uint256(p1);
r[1] = uint256(uint160(p2));
r[2] = p3;
r[3] = p4 ? 1 : 0;
}
function authParams(address p1, uint256 p2, uint256 p3, uint256 p4, uint256 p5)
internal
pure
returns (uint256[] memory r)
{
r = new uint256[](5);
r[0] = uint256(uint160(p1));
r[1] = p2;
r[2] = p3;
r[3] = p4;
r[4] = p5;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.8.0;
/**
* @dev Authorized interface
*/
interface IAuthorized {
/**
* @dev Sender `who` is not allowed to call `what` with `how`
*/
error AuthSenderNotAllowed(address who, bytes4 what, uint256[] how);
/**
* @dev Tells the address of the authorizer reference
*/
function authorizer() external view returns (address);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.8.0;
/**
* @dev Authorizer interface
*/
interface IAuthorizer {
/**
* @dev Permission change
* @param where Address of the contract to change a permission for
* @param changes List of permission changes to be executed
*/
struct PermissionChange {
address where;
GrantPermission[] grants;
RevokePermission[] revokes;
}
/**
* @dev Grant permission data
* @param who Address to be authorized
* @param what Function selector to be authorized
* @param params List of params to restrict the given permission
*/
struct GrantPermission {
address who;
bytes4 what;
Param[] params;
}
/**
* @dev Revoke permission data
* @param who Address to be unauthorized
* @param what Function selector to be unauthorized
*/
struct RevokePermission {
address who;
bytes4 what;
}
/**
* @dev Params used to validate permissions params against
* @param op ID of the operation to compute in order to validate a permission param
* @param value Comparison value
*/
struct Param {
uint8 op;
uint248 value;
}
/**
* @dev Sender is not authorized to call `what` on `where` with `how`
*/
error AuthorizerSenderNotAllowed(address who, address where, bytes4 what, uint256[] how);
/**
* @dev The operation param is invalid
*/
error AuthorizerInvalidParamOp(uint8 op);
/**
* @dev Emitted every time `who`'s permission to perform `what` on `where` is granted with `params`
*/
event Authorized(address indexed who, address indexed where, bytes4 indexed what, Param[] params);
/**
* @dev Emitted every time `who`'s permission to perform `what` on `where` is revoked
*/
event Unauthorized(address indexed who, address indexed where, bytes4 indexed what);
/**
* @dev Tells whether `who` has any permission on `where`
* @param who Address asking permission for
* @param where Target address asking permission for
*/
function hasPermissions(address who, address where) external view returns (bool);
/**
* @dev Tells the number of permissions `who` has on `where`
* @param who Address asking permission for
* @param where Target address asking permission for
*/
function getPermissionsLength(address who, address where) external view returns (uint256);
/**
* @dev Tells whether `who` has permission to call `what` on `where`. Note `how` is not evaluated here,
* which means `who` might be authorized on or not depending on the call at the moment of the execution
* @param who Address asking permission for
* @param where Target address asking permission for
* @param what Function selector asking permission for
*/
function hasPermission(address who, address where, bytes4 what) external view returns (bool);
/**
* @dev Tells whether `who` is allowed to call `what` on `where` with `how`
* @param who Address asking permission for
* @param where Target address asking permission for
* @param what Function selector asking permission for
* @param how Params asking permission for
*/
function isAuthorized(address who, address where, bytes4 what, uint256[] memory how) external view returns (bool);
/**
* @dev Tells the params set for a given permission
* @param who Address asking permission params of
* @param where Target address asking permission params of
* @param what Function selector asking permission params of
*/
function getPermissionParams(address who, address where, bytes4 what) external view returns (Param[] memory);
/**
* @dev Executes a list of permission changes
* @param changes List of permission changes to be executed
*/
function changePermissions(PermissionChange[] memory changes) external;
/**
* @dev Authorizes `who` to call `what` on `where` restricted by `params`
* @param who Address to be authorized
* @param where Target address to be granted for
* @param what Function selector to be granted
* @param params Optional params to restrict a permission attempt
*/
function authorize(address who, address where, bytes4 what, Param[] memory params) external;
/**
* @dev Unauthorizes `who` to call `what` on `where`. Sender must be authorized.
* @param who Address to be authorized
* @param where Target address to be revoked for
* @param what Function selector to be revoked
*/
function unauthorize(address who, address where, bytes4 what) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import '../AuthorizedHelpers.sol';
contract AuthorizedHelpersMock is AuthorizedHelpers {
function getAuthParams(address p1) external pure returns (uint256[] memory r) {
return authParams(p1);
}
function getAuthParams(bytes32 p1) external pure returns (uint256[] memory r) {
return authParams(p1);
}
function getAuthParams(uint256 p1) external pure returns (uint256[] memory r) {
return authParams(p1);
}
function getAuthParams(address p1, bool p2) external pure returns (uint256[] memory r) {
return authParams(p1, p2);
}
function getAuthParams(address p1, uint256 p2) external pure returns (uint256[] memory r) {
return authParams(p1, p2);
}
function getAuthParams(address p1, address p2) external pure returns (uint256[] memory r) {
return authParams(p1, p2);
}
function getAuthParams(bytes32 p1, bytes32 p2) external pure returns (uint256[] memory r) {
return authParams(p1, p2);
}
function getAuthParams(address p1, address p2, uint256 p3) external pure returns (uint256[] memory r) {
return authParams(p1, p2, p3);
}
function getAuthParams(address p1, address p2, address p3) external pure returns (uint256[] memory r) {
return authParams(p1, p2, p3);
}
function getAuthParams(address p1, address p2, bytes4 p3) external pure returns (uint256[] memory r) {
return authParams(p1, p2, p3);
}
function getAuthParams(address p1, uint256 p2, uint256 p3) external pure returns (uint256[] memory r) {
return authParams(p1, p2, p3);
}
function getAuthParams(address p1, address p2, uint256 p3, uint256 p4) external pure returns (uint256[] memory r) {
return authParams(p1, p2, p3, p4);
}
function getAuthParams(address p1, uint256 p2, uint256 p3, uint256 p4) external pure returns (uint256[] memory r) {
return authParams(p1, p2, p3, p4);
}
function getAuthParams(bytes32 p1, address p2, uint256 p3, bool p4) external pure returns (uint256[] memory r) {
return authParams(p1, p2, p3, p4);
}
function getAuthParams(address p1, uint256 p2, uint256 p3, uint256 p4, uint256 p5)
external
pure
returns (uint256[] memory r)
{
return authParams(p1, p2, p3, p4, p5);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import '../Authorized.sol';
contract AuthorizedMock is Authorized {
event LogUint256(uint256 x);
event LogBytes32(bytes32 x);
event LogAddress(address x);
function initialize(address _authorizer) external virtual initializer {
__Authorized_init(_authorizer);
}
function setUint256(uint256 x) external authP(authParams(x)) {
emit LogUint256(x);
}
function setBytes32(bytes32 x) external authP(authParams(x)) {
emit LogBytes32(x);
}
function setAddress(address x) external authP(authParams(x)) {
emit LogAddress(x);
}
}{
"optimizer": {
"enabled": true,
"runs": 10000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"op","type":"uint8"}],"name":"AuthorizerInvalidParamOp","type":"error"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"where","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"},{"internalType":"uint256[]","name":"how","type":"uint256[]"}],"name":"AuthorizerSenderNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"who","type":"address"},{"indexed":true,"internalType":"address","name":"where","type":"address"},{"indexed":true,"internalType":"bytes4","name":"what","type":"bytes4"},{"components":[{"internalType":"uint8","name":"op","type":"uint8"},{"internalType":"uint248","name":"value","type":"uint248"}],"indexed":false,"internalType":"struct IAuthorizer.Param[]","name":"params","type":"tuple[]"}],"name":"Authorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"who","type":"address"},{"indexed":true,"internalType":"address","name":"where","type":"address"},{"indexed":true,"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"Unauthorized","type":"event"},{"inputs":[],"name":"ANYONE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANYWHERE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"where","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"},{"components":[{"internalType":"uint8","name":"op","type":"uint8"},{"internalType":"uint248","name":"value","type":"uint248"}],"internalType":"struct IAuthorizer.Param[]","name":"params","type":"tuple[]"}],"name":"authorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"where","type":"address"},{"components":[{"internalType":"address","name":"who","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"},{"components":[{"internalType":"uint8","name":"op","type":"uint8"},{"internalType":"uint248","name":"value","type":"uint248"}],"internalType":"struct IAuthorizer.Param[]","name":"params","type":"tuple[]"}],"internalType":"struct IAuthorizer.GrantPermission[]","name":"grants","type":"tuple[]"},{"components":[{"internalType":"address","name":"who","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"}],"internalType":"struct IAuthorizer.RevokePermission[]","name":"revokes","type":"tuple[]"}],"internalType":"struct IAuthorizer.PermissionChange[]","name":"changes","type":"tuple[]"}],"name":"changePermissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"where","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"getPermissionParams","outputs":[{"components":[{"internalType":"uint8","name":"op","type":"uint8"},{"internalType":"uint248","name":"value","type":"uint248"}],"internalType":"struct IAuthorizer.Param[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"where","type":"address"}],"name":"getPermissionsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"where","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"hasPermission","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"where","type":"address"}],"name":"hasPermissions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"where","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"},{"internalType":"uint256[]","name":"how","type":"uint256[]"}],"name":"isAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"where","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"unauthorize","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5061001961001e565b6100dd565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146100db576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611d01806100ec6000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063840510cc11610081578063ca7c51d01161005b578063ca7c51d014610217578063e8a67dad1461022a578063fd1ccc9b1461027257600080fd5b8063840510cc146101a4578063a224cee7146101e4578063b091986d146101f757600080fd5b8063261a48af116100b2578063261a48af1461017c5780632852289514610191578063405d30af146101a457600080fd5b80630eb39344146100ce57806315771845146100f4575b600080fd5b6100e16100dc3660046113a6565b610285565b6040519081526020015b60405180910390f35b61016c610102366004611409565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260336020908152604080832093861683529281528282207fffffffff00000000000000000000000000000000000000000000000000000000851683526001019052205460ff169392505050565b60405190151581526020016100eb565b61018f61018a366004611409565b6102bf565b005b61016c61019f36600461153a565b61031b565b6101bf73ffffffffffffffffffffffffffffffffffffffff81565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100eb565b61018f6101f2366004611602565b6103c9565b61020a610205366004611409565b61069c565b6040516100eb919061169a565b61018f610225366004611862565b610789565b61016c6102383660046113a6565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152603360209081526040808320939094168252919091522054151590565b61018f610280366004611ac9565b610886565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152603360209081526040808320938516835292905220545b92915050565b6102c76108e4565b60006102d4848484610957565b9050610301337f261a48af0000000000000000000000000000000000000000000000000000000083610a15565b61030c848484610a64565b5061031660018055565b505050565b600061032985858585610bd6565b15610336575060016103c1565b61035673ffffffffffffffffffffffffffffffffffffffff858585610bd6565b15610363575060016103c1565b6103838573ffffffffffffffffffffffffffffffffffffffff8585610bd6565b15610390575060016103c1565b6103b073ffffffffffffffffffffffffffffffffffffffff808585610bd6565b156103bd575060016103c1565b5060005b949350505050565b600054610100900460ff16158080156103e95750600054600160ff909116105b806104035750303b158015610403575060005460ff166001145b610494576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156104f257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6104fa610cdd565b60005b82518110156106345761059583828151811061051b5761051b611b38565b6020908102919091010151307ffd1ccc9b00000000000000000000000000000000000000000000000000000000600060405190808252806020026020018201604052801561058f57816020015b60408051808201909152600080825260208201528152602001906001900390816105685790505b50610d7e565b6106228382815181106105aa576105aa611b38565b6020908102919091010151307f261a48af00000000000000000000000000000000000000000000000000000000600060405190808252806020026020018201604052801561058f5781602001604080518082019091526000808252602082015281526020019060019003908161056857905050610d7e565b8061062c81611b96565b9150506104fd565b50801561069857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260336020908152604080832093861683529281528282207fffffffff00000000000000000000000000000000000000000000000000000000851683526001908101825283832001805484518184028101840190955280855260609493919290919084015b8282101561077c576000848152602090819020604080518082019091529084015460ff8116825261010090047effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168183015282526001909201910161071d565b5050505090509392505050565b60005b81518110156106985760008282815181106107a9576107a9611b38565b6020026020010151905060005b816020015151811015610814576000826020015182815181106107db576107db611b38565b602002602001015190506108018160000151846000015183602001518460400151610886565b508061080c81611b96565b9150506107b6565b5060005b8160400151518110156108715760008260400151828151811061083d5761083d611b38565b6020026020010151905061085e8160000151846000015183602001516102bf565b508061086981611b96565b915050610818565b5050808061087e90611b96565b91505061078c565b61088e6108e4565b600061089b858585610957565b90506108c8337ffd1ccc9b0000000000000000000000000000000000000000000000000000000083610a15565b6108d485858585610d7e565b506108de60018055565b50505050565b600260015403610950576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161048b565b6002600155565b604080516003808252608082019092526060916020820183803683370190505090508373ffffffffffffffffffffffffffffffffffffffff16816000815181106109a3576109a3611b38565b6020026020010181815250508273ffffffffffffffffffffffffffffffffffffffff16816001815181106109d9576109d9611b38565b6020026020010181815250508160e01c63ffffffff1681600281518110610a0257610a02611b38565b6020026020010181815250509392505050565b6000610a238430858561031b565b9050806108de57833084846040517f61174e8800000000000000000000000000000000000000000000000000000000815260040161048b9493929190611bce565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260336020908152604080832093861683529281528282207fffffffff000000000000000000000000000000000000000000000000000000008516835260018101909152919020805460ff1615610ae5578154826000610adf83611c67565b91905055505b7fffffffff000000000000000000000000000000000000000000000000000000008316600090815260018084016020526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681559190610b4d90830182611343565b5050827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fa8095e01dcc1c206b8b64f0bcaf4fee219b0ee0bd623ea32f9876e19600cdb6360405160405180910390a45050505050565b60018055565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260336020908152604080832093871683529281528282207fffffffff00000000000000000000000000000000000000000000000000000000861683526001019052908120805460ff168015610cd35750610cd381600101805480602002602001604051908101604052809291908181526020016000905b82821015610cc9576000848152602090819020604080518082019091529084015460ff8116825261010090047effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681830152825260019092019101610c6a565b5050505084610f4a565b9695505050505050565b600054610100900460ff16610d74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161048b565b610d7c611010565b565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260336020908152604080832093871683529281528282207fffffffff000000000000000000000000000000000000000000000000000000008616835260018101909152919020805460ff16610dfe578154826000610df883611b96565b91905055505b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081178255610e369082016000611343565b60005b8351811015610ebc5781600101848281518110610e5857610e58611b38565b6020908102919091018101518254600181018455600093845292829020815191909201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff166101000260ff9091161791015580610eb481611b96565b915050610e39565b50837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fa4e3ad0d161589a3d7d368c479c5c4bd9d753ea8f4865b26801b7e9823235ff586604051610f3a919061169a565b60405180910390a4505050505050565b6000805b8351811015611006576000848281518110610f6b57610f6b611b38565b60200260200101519050835182108015610fa55750610fa381858481518110610f9657610f96611b38565b60200260200101516110a7565b155b80610fe3575083518210158015610fe357506000815160ff166006811115610fcf57610fcf611c9c565b6006811115610fe057610fe0611c9c565b14155b15610ff3576000925050506102b9565b5080610ffe81611b96565b915050610f4e565b5060019392505050565b600054610100900460ff16610bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161048b565b600080835160ff1660068111156110c0576110c0611c9c565b60068111156110d1576110d1611c9c565b036110de575060016102b9565b6001835160ff1660068111156110f6576110f6611c9c565b600681111561110757611107611c9c565b0361113a575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681146102b9565b6002835160ff16600681111561115257611152611c9c565b600681111561116357611163611c9c565b03611197575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168114156102b9565b6003835160ff1660068111156111af576111af611c9c565b60068111156111c0576111c0611c9c565b036111f3575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681116102b9565b6004835160ff16600681111561120b5761120b611c9c565b600681111561121c5761121c611c9c565b0361124f575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681106102b9565b6005835160ff16600681111561126757611267611c9c565b600681111561127857611278611c9c565b036112ac575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168110156102b9565b6006835160ff1660068111156112c4576112c4611c9c565b60068111156112d5576112d5611c9c565b03611309575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168111156102b9565b82516040517f69f2cbf500000000000000000000000000000000000000000000000000000000815260ff909116600482015260240161048b565b50805460008255906000526020600020908101906113619190611364565b50565b5b808211156113795760008155600101611365565b5090565b803573ffffffffffffffffffffffffffffffffffffffff811681146113a157600080fd5b919050565b600080604083850312156113b957600080fd5b6113c28361137d565b91506113d06020840161137d565b90509250929050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146113a157600080fd5b60008060006060848603121561141e57600080fd5b6114278461137d565b92506114356020850161137d565b9150611443604085016113d9565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561149e5761149e61144c565b60405290565b6040516060810167ffffffffffffffff8111828210171561149e5761149e61144c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561150e5761150e61144c565b604052919050565b600067ffffffffffffffff8211156115305761153061144c565b5060051b60200190565b6000806000806080858703121561155057600080fd5b6115598561137d565b9350602061156881870161137d565b9350611576604087016113d9565b9250606086013567ffffffffffffffff81111561159257600080fd5b8601601f810188136115a357600080fd5b80356115b66115b182611516565b6114c7565b81815260059190911b8201830190838101908a8311156115d557600080fd5b928401925b828410156115f3578335825292840192908401906115da565b979a9699509497505050505050565b6000602080838503121561161557600080fd5b823567ffffffffffffffff81111561162c57600080fd5b8301601f8101851361163d57600080fd5b803561164b6115b182611516565b81815260059190911b8201830190838101908783111561166a57600080fd5b928401925b8284101561168f576116808461137d565b8252928401929084019061166f565b979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015611700578151805160ff1685528601517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168685015292840192908501906001016116b7565b5091979650505050505050565b600082601f83011261171e57600080fd5b8135602061172e6115b183611516565b82815260069290921b8401810191818101908684111561174d57600080fd5b8286015b848110156117ca576040818903121561176a5760008081fd5b61177261147b565b813560ff811681146117845760008081fd5b8152818501357effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146117b85760008081fd5b81860152835291830191604001611751565b509695505050505050565b600082601f8301126117e657600080fd5b813560206117f66115b183611516565b82815260069290921b8401810191818101908684111561181557600080fd5b8286015b848110156117ca57604081890312156118325760008081fd5b61183a61147b565b6118438261137d565b81526118508583016113d9565b81860152835291830191604001611819565b60006020828403121561187457600080fd5b67ffffffffffffffff8235111561188a57600080fd5b8135820183601f82011261189d57600080fd5b6118aa6115b18235611516565b81358082526020808301929160051b8401018610156118c857600080fd5b602083015b6020843560051b850101811015611abf5767ffffffffffffffff813511156118f457600080fd5b8035840160607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a0301121561192a57600080fd5b6119326114a4565b61193e6020830161137d565b815267ffffffffffffffff6040830135111561195957600080fd5b6040820135820189603f82011261196f57600080fd5b61197f6115b16020830135611516565b602082810135808352908201919060051b83016040018c10156119a157600080fd5b604083015b6040602085013560051b850101811015611a775767ffffffffffffffff813511156119d057600080fd5b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0823586018f03011215611a0557600080fd5b611a0d6114a4565b611a1c6040833587010161137d565b8152611a2d606083358701016113d9565b602082015267ffffffffffffffff60808335870101351115611a4e57600080fd5b611a648e8335870160808101350160400161170d565b60408201528352602092830192016119a6565b506020840152505067ffffffffffffffff60608301351115611a9857600080fd5b611aab89602060608501358501016117d5565b6040820152845250602092830192016118cd565b5095945050505050565b60008060008060808587031215611adf57600080fd5b611ae88561137d565b9350611af66020860161137d565b9250611b04604086016113d9565b9150606085013567ffffffffffffffff811115611b2057600080fd5b611b2c8782880161170d565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611bc757611bc7611b67565b5060010190565b60006080820173ffffffffffffffffffffffffffffffffffffffff80881684526020818816818601527fffffffff000000000000000000000000000000000000000000000000000000008716604086015260806060860152829150855180845260a086019250818701935060005b81811015611c5857845184529382019392820192600101611c3c565b50919998505050505050505050565b600081611c7657611c76611b67565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea264697066735822122010f73222ea0d815cb6e46c1aaef2b993a8da022a3742cc1de1bffc7ef5b3390964736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100c95760003560e01c8063840510cc11610081578063ca7c51d01161005b578063ca7c51d014610217578063e8a67dad1461022a578063fd1ccc9b1461027257600080fd5b8063840510cc146101a4578063a224cee7146101e4578063b091986d146101f757600080fd5b8063261a48af116100b2578063261a48af1461017c5780632852289514610191578063405d30af146101a457600080fd5b80630eb39344146100ce57806315771845146100f4575b600080fd5b6100e16100dc3660046113a6565b610285565b6040519081526020015b60405180910390f35b61016c610102366004611409565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260336020908152604080832093861683529281528282207fffffffff00000000000000000000000000000000000000000000000000000000851683526001019052205460ff169392505050565b60405190151581526020016100eb565b61018f61018a366004611409565b6102bf565b005b61016c61019f36600461153a565b61031b565b6101bf73ffffffffffffffffffffffffffffffffffffffff81565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100eb565b61018f6101f2366004611602565b6103c9565b61020a610205366004611409565b61069c565b6040516100eb919061169a565b61018f610225366004611862565b610789565b61016c6102383660046113a6565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152603360209081526040808320939094168252919091522054151590565b61018f610280366004611ac9565b610886565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152603360209081526040808320938516835292905220545b92915050565b6102c76108e4565b60006102d4848484610957565b9050610301337f261a48af0000000000000000000000000000000000000000000000000000000083610a15565b61030c848484610a64565b5061031660018055565b505050565b600061032985858585610bd6565b15610336575060016103c1565b61035673ffffffffffffffffffffffffffffffffffffffff858585610bd6565b15610363575060016103c1565b6103838573ffffffffffffffffffffffffffffffffffffffff8585610bd6565b15610390575060016103c1565b6103b073ffffffffffffffffffffffffffffffffffffffff808585610bd6565b156103bd575060016103c1565b5060005b949350505050565b600054610100900460ff16158080156103e95750600054600160ff909116105b806104035750303b158015610403575060005460ff166001145b610494576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156104f257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6104fa610cdd565b60005b82518110156106345761059583828151811061051b5761051b611b38565b6020908102919091010151307ffd1ccc9b00000000000000000000000000000000000000000000000000000000600060405190808252806020026020018201604052801561058f57816020015b60408051808201909152600080825260208201528152602001906001900390816105685790505b50610d7e565b6106228382815181106105aa576105aa611b38565b6020908102919091010151307f261a48af00000000000000000000000000000000000000000000000000000000600060405190808252806020026020018201604052801561058f5781602001604080518082019091526000808252602082015281526020019060019003908161056857905050610d7e565b8061062c81611b96565b9150506104fd565b50801561069857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260336020908152604080832093861683529281528282207fffffffff00000000000000000000000000000000000000000000000000000000851683526001908101825283832001805484518184028101840190955280855260609493919290919084015b8282101561077c576000848152602090819020604080518082019091529084015460ff8116825261010090047effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168183015282526001909201910161071d565b5050505090509392505050565b60005b81518110156106985760008282815181106107a9576107a9611b38565b6020026020010151905060005b816020015151811015610814576000826020015182815181106107db576107db611b38565b602002602001015190506108018160000151846000015183602001518460400151610886565b508061080c81611b96565b9150506107b6565b5060005b8160400151518110156108715760008260400151828151811061083d5761083d611b38565b6020026020010151905061085e8160000151846000015183602001516102bf565b508061086981611b96565b915050610818565b5050808061087e90611b96565b91505061078c565b61088e6108e4565b600061089b858585610957565b90506108c8337ffd1ccc9b0000000000000000000000000000000000000000000000000000000083610a15565b6108d485858585610d7e565b506108de60018055565b50505050565b600260015403610950576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161048b565b6002600155565b604080516003808252608082019092526060916020820183803683370190505090508373ffffffffffffffffffffffffffffffffffffffff16816000815181106109a3576109a3611b38565b6020026020010181815250508273ffffffffffffffffffffffffffffffffffffffff16816001815181106109d9576109d9611b38565b6020026020010181815250508160e01c63ffffffff1681600281518110610a0257610a02611b38565b6020026020010181815250509392505050565b6000610a238430858561031b565b9050806108de57833084846040517f61174e8800000000000000000000000000000000000000000000000000000000815260040161048b9493929190611bce565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260336020908152604080832093861683529281528282207fffffffff000000000000000000000000000000000000000000000000000000008516835260018101909152919020805460ff1615610ae5578154826000610adf83611c67565b91905055505b7fffffffff000000000000000000000000000000000000000000000000000000008316600090815260018084016020526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681559190610b4d90830182611343565b5050827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fa8095e01dcc1c206b8b64f0bcaf4fee219b0ee0bd623ea32f9876e19600cdb6360405160405180910390a45050505050565b60018055565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260336020908152604080832093871683529281528282207fffffffff00000000000000000000000000000000000000000000000000000000861683526001019052908120805460ff168015610cd35750610cd381600101805480602002602001604051908101604052809291908181526020016000905b82821015610cc9576000848152602090819020604080518082019091529084015460ff8116825261010090047effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681830152825260019092019101610c6a565b5050505084610f4a565b9695505050505050565b600054610100900460ff16610d74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161048b565b610d7c611010565b565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260336020908152604080832093871683529281528282207fffffffff000000000000000000000000000000000000000000000000000000008616835260018101909152919020805460ff16610dfe578154826000610df883611b96565b91905055505b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081178255610e369082016000611343565b60005b8351811015610ebc5781600101848281518110610e5857610e58611b38565b6020908102919091018101518254600181018455600093845292829020815191909201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff166101000260ff9091161791015580610eb481611b96565b915050610e39565b50837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fa4e3ad0d161589a3d7d368c479c5c4bd9d753ea8f4865b26801b7e9823235ff586604051610f3a919061169a565b60405180910390a4505050505050565b6000805b8351811015611006576000848281518110610f6b57610f6b611b38565b60200260200101519050835182108015610fa55750610fa381858481518110610f9657610f96611b38565b60200260200101516110a7565b155b80610fe3575083518210158015610fe357506000815160ff166006811115610fcf57610fcf611c9c565b6006811115610fe057610fe0611c9c565b14155b15610ff3576000925050506102b9565b5080610ffe81611b96565b915050610f4e565b5060019392505050565b600054610100900460ff16610bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161048b565b600080835160ff1660068111156110c0576110c0611c9c565b60068111156110d1576110d1611c9c565b036110de575060016102b9565b6001835160ff1660068111156110f6576110f6611c9c565b600681111561110757611107611c9c565b0361113a575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681146102b9565b6002835160ff16600681111561115257611152611c9c565b600681111561116357611163611c9c565b03611197575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168114156102b9565b6003835160ff1660068111156111af576111af611c9c565b60068111156111c0576111c0611c9c565b036111f3575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681116102b9565b6004835160ff16600681111561120b5761120b611c9c565b600681111561121c5761121c611c9c565b0361124f575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681106102b9565b6005835160ff16600681111561126757611267611c9c565b600681111561127857611278611c9c565b036112ac575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168110156102b9565b6006835160ff1660068111156112c4576112c4611c9c565b60068111156112d5576112d5611c9c565b03611309575060208201517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168111156102b9565b82516040517f69f2cbf500000000000000000000000000000000000000000000000000000000815260ff909116600482015260240161048b565b50805460008255906000526020600020908101906113619190611364565b50565b5b808211156113795760008155600101611365565b5090565b803573ffffffffffffffffffffffffffffffffffffffff811681146113a157600080fd5b919050565b600080604083850312156113b957600080fd5b6113c28361137d565b91506113d06020840161137d565b90509250929050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146113a157600080fd5b60008060006060848603121561141e57600080fd5b6114278461137d565b92506114356020850161137d565b9150611443604085016113d9565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561149e5761149e61144c565b60405290565b6040516060810167ffffffffffffffff8111828210171561149e5761149e61144c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561150e5761150e61144c565b604052919050565b600067ffffffffffffffff8211156115305761153061144c565b5060051b60200190565b6000806000806080858703121561155057600080fd5b6115598561137d565b9350602061156881870161137d565b9350611576604087016113d9565b9250606086013567ffffffffffffffff81111561159257600080fd5b8601601f810188136115a357600080fd5b80356115b66115b182611516565b6114c7565b81815260059190911b8201830190838101908a8311156115d557600080fd5b928401925b828410156115f3578335825292840192908401906115da565b979a9699509497505050505050565b6000602080838503121561161557600080fd5b823567ffffffffffffffff81111561162c57600080fd5b8301601f8101851361163d57600080fd5b803561164b6115b182611516565b81815260059190911b8201830190838101908783111561166a57600080fd5b928401925b8284101561168f576116808461137d565b8252928401929084019061166f565b979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015611700578151805160ff1685528601517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff168685015292840192908501906001016116b7565b5091979650505050505050565b600082601f83011261171e57600080fd5b8135602061172e6115b183611516565b82815260069290921b8401810191818101908684111561174d57600080fd5b8286015b848110156117ca576040818903121561176a5760008081fd5b61177261147b565b813560ff811681146117845760008081fd5b8152818501357effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146117b85760008081fd5b81860152835291830191604001611751565b509695505050505050565b600082601f8301126117e657600080fd5b813560206117f66115b183611516565b82815260069290921b8401810191818101908684111561181557600080fd5b8286015b848110156117ca57604081890312156118325760008081fd5b61183a61147b565b6118438261137d565b81526118508583016113d9565b81860152835291830191604001611819565b60006020828403121561187457600080fd5b67ffffffffffffffff8235111561188a57600080fd5b8135820183601f82011261189d57600080fd5b6118aa6115b18235611516565b81358082526020808301929160051b8401018610156118c857600080fd5b602083015b6020843560051b850101811015611abf5767ffffffffffffffff813511156118f457600080fd5b8035840160607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a0301121561192a57600080fd5b6119326114a4565b61193e6020830161137d565b815267ffffffffffffffff6040830135111561195957600080fd5b6040820135820189603f82011261196f57600080fd5b61197f6115b16020830135611516565b602082810135808352908201919060051b83016040018c10156119a157600080fd5b604083015b6040602085013560051b850101811015611a775767ffffffffffffffff813511156119d057600080fd5b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0823586018f03011215611a0557600080fd5b611a0d6114a4565b611a1c6040833587010161137d565b8152611a2d606083358701016113d9565b602082015267ffffffffffffffff60808335870101351115611a4e57600080fd5b611a648e8335870160808101350160400161170d565b60408201528352602092830192016119a6565b506020840152505067ffffffffffffffff60608301351115611a9857600080fd5b611aab89602060608501358501016117d5565b6040820152845250602092830192016118cd565b5095945050505050565b60008060008060808587031215611adf57600080fd5b611ae88561137d565b9350611af66020860161137d565b9250611b04604086016113d9565b9150606085013567ffffffffffffffff811115611b2057600080fd5b611b2c8782880161170d565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611bc757611bc7611b67565b5060010190565b60006080820173ffffffffffffffffffffffffffffffffffffffff80881684526020818816818601527fffffffff000000000000000000000000000000000000000000000000000000008716604086015260806060860152829150855180845260a086019250818701935060005b81811015611c5857845184529382019392820192600101611c3c565b50919998505050505050505050565b600081611c7657611c76611b67565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea264697066735822122010f73222ea0d815cb6e46c1aaef2b993a8da022a3742cc1de1bffc7ef5b3390964736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 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.