Source Code
Overview
XDAI Balance
XDAI Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 32809116 | 688 days ago | 0 XDAI | ||||
| 32809116 | 688 days ago | 0 XDAI | ||||
| 32809116 | 688 days ago | 0 XDAI | ||||
| 32809116 | 688 days ago | 0 XDAI | ||||
| 32809070 | 688 days ago | 0 XDAI | ||||
| 32809070 | 688 days ago | 0 XDAI | ||||
| 32809070 | 688 days ago | 0 XDAI | ||||
| 32809063 | 688 days ago | 0 XDAI | ||||
| 32809063 | 688 days ago | 0 XDAI | ||||
| 32809063 | 688 days ago | 0 XDAI | ||||
| 32809063 | 688 days ago | 0 XDAI | ||||
| 32809063 | 688 days ago | 0 XDAI | ||||
| 32809063 | 688 days ago | 0 XDAI | ||||
| 32809051 | 688 days ago | 0 XDAI | ||||
| 32809051 | 688 days ago | 0 XDAI | ||||
| 32809051 | 688 days ago | 0 XDAI | ||||
| 32809043 | 688 days ago | 0 XDAI | ||||
| 32809043 | 688 days ago | 0 XDAI | ||||
| 32809043 | 688 days ago | 0 XDAI | ||||
| 32809043 | 688 days ago | 0 XDAI | ||||
| 32809028 | 688 days ago | 0 XDAI | ||||
| 32809028 | 688 days ago | 0 XDAI | ||||
| 32809028 | 688 days ago | 0 XDAI | ||||
| 32809028 | 688 days ago | 0 XDAI | ||||
| 32809028 | 688 days ago | 0 XDAI |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
SmartController
Compiler Version
v0.8.11+commit.d7f03943
Contract Source Code (Solidity Multiple files format)
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./SmartTokenLib.sol";
import "./MintableController.sol";
import "./IValidator.sol";
/**
* @title SmartController
* @dev This contract adds "smart" functionality which is required from a regulatory perspective.
*/
contract SmartController is MintableController {
using SmartTokenLib for SmartTokenLib.SmartStorage;
SmartTokenLib.SmartStorage internal smartToken;
bytes3 public ticker;
uint256 public constant INITIAL_SUPPLY = 0;
/**
* @dev Contract constructor.
* @param storage_ Address of the token storage for the controller.
* @param validator Address of validator.
* @param ticker_ 3 letter currency ticker.
* @param frontend_ Address of the authorized frontend.
*/
constructor(
address storage_,
address validator,
bytes3 ticker_,
address frontend_
) MintableController(storage_, INITIAL_SUPPLY, frontend_) {
require(
validator != address(0x0),
"validator cannot be the null address"
);
smartToken.setValidator(validator);
ticker = ticker_;
}
/**
* @dev Sets a new validator.
* @param validator Address of validator.
*/
function setValidator(address validator) external onlyOwner {
smartToken.setValidator(validator);
}
/**
* @dev Recovers tokens from an address and reissues them to another address.
* In case a user loses its private key the tokens can be recovered by burning
* the tokens from that address and reissuing to a new address.
* To recover tokens the contract owner needs to provide a signature
* proving that the token owner has authorized the owner to do so.
* @param caller Address of the caller passed through the frontend.
* @param from Address to burn tokens from.
* @param to Address to mint tokens to.
* @param h Hash which the token owner signed.
* @param v Signature component.
* @param r Signature component.
* @param s Sigature component.
* @return Amount recovered.
*/
function recover_withCaller(
address caller,
address from,
address to,
bytes32 h,
uint8 v,
bytes32 r,
bytes32 s
) external onlyFrontend onlySystemAccount(caller) returns (uint) {
_avoidBlackholes(to);
return SmartTokenLib.recover(token, from, to, h, v, r, s);
}
/**
* @dev Transfers tokens [ERC20].
* The caller, to address and amount are validated before executing method.
* Prior to transfering tokens the validator needs to approve.
* @notice Overrides method in a parent.
* @param caller Address of the caller passed through the frontend.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
*/
function transfer_withCaller(
address caller,
address to,
uint256 amount
) public override returns (bool) {
require(
smartToken.validate(caller, to, amount),
"transfer request not valid"
);
return super.transfer_withCaller(caller, to, amount);
}
/**
* @dev Transfers tokens from a specific address [ERC20].
* The address owner has to approve the spender beforehand.
* The from address, to address and amount are validated before executing method.
* @notice Overrides method in a parent.
* Prior to transfering tokens the validator needs to approve.
* @param caller Address of the caller passed through the frontend.
* @param from Address to debet the tokens from.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
*/
function transferFrom_withCaller(
address caller,
address from,
address to,
uint256 amount
) public override returns (bool) {
require(
smartToken.validate(from, to, amount),
"transferFrom request not valid"
);
return super.transferFrom_withCaller(caller, from, to, amount);
}
/**
* @dev Transfers tokens and subsequently calls a method on the recipient [ERC677].
* If the recipient is a non-contract address this method behaves just like transfer.
* The caller, to address and amount are validated before executing method.
* @notice Overrides method in a parent.
* @param caller Address of the caller passed through the frontend.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
* @param data Additional data passed to the recipient's tokenFallback method.
*/
function transferAndCall_withCaller(
address caller,
address to,
uint256 amount,
bytes calldata data
) public override returns (bool) {
require(
smartToken.validate(caller, to, amount),
"transferAndCall request not valid"
);
return super.transferAndCall_withCaller(caller, to, amount, data);
}
/**
* @dev Gets the current validator.
* @return Address of validator.
*/
function getValidator() external view returns (address) {
return smartToken.getValidator();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "./Context.sol";
import "./Strings.sol";
import "./ERC165.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 AccessControl is Context, IAccessControl, ERC165 {
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);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @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 virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.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 virtual 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.
*
* May emit a {RoleGranted} event.
*/
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.
*
* May emit a {RoleRevoked} event.
*/
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`.
*
* May emit a {RoleRevoked} event.
*/
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.
*
* May emit a {RoleGranted} event.
*
* [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.
*
* May emit a {RoleGranted} event.
*/
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.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return 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: MIT
pragma solidity 0.8.11;
import "./Ownable.sol";
import "./ERC20Basic.sol";
import "./SafeERC20.sol";
/**
* @title Contracts that should be able to recover tokens
* @author SylTi
* @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner.
* This will prevent any accidental loss of tokens.
*/
contract CanReclaimToken is Ownable {
using SafeERC20 for ERC20Basic;
/**
* @dev Reclaim all ERC20Basic compatible tokens
* @param _token ERC20Basic The address of the token contract
*/
function reclaimToken(ERC20Basic _token) external onlyOwner {
uint256 balance = _token.balanceOf(address(this));
_token.safeTransfer(owner, balance);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./Ownable.sol";
/**
* @title Claimable
* @dev Extension for the Ownable contract, where the ownership needs to be claimed.
* This allows the new owner to accept the transfer.
*/
abstract contract Claimable is Ownable {
address public pendingOwner;
/**
* @dev emitted when the pendingOwner address is changed
* @param previousPendingOwner previous pendingOwner address
* @param newPendingOwner new pendingOwner address
*/
event OwnershipTransferPending(
address indexed previousPendingOwner,
address indexed newPendingOwner
);
/**
* @dev Modifier throws if called by any account other than the pendingOwner.
*/
modifier onlyPendingOwner() {
require(msg.sender == pendingOwner);
_;
}
/**
* @dev Allows the current owner to set the pendingOwner address.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(
address newOwner
) public virtual override onlyOwner {
emit OwnershipTransferPending(pendingOwner, newOwner);
pendingOwner = newOwner;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer.
*/
function claimOwnership() public onlyPendingOwner {
emit OwnershipTransferred(owner, pendingOwner);
owner = pendingOwner;
pendingOwner = address(0);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./SystemRole.sol";
/**
* @title ClaimableSystemRole
* @dev Extension for the SystemRole contract, where the ownership needs to be claimed.
* This allows the new owner to accept the transfer.
*/
abstract contract ClaimableSystemRole is SystemRole {
address public pendingOwner;
/**
* @dev emitted when the pendingOwner address is changed
* @param previousPendingOwner previous pendingOwner address
* @param newPendingOwner new pendingOwner address
*/
event OwnershipTransferPending(
address indexed previousPendingOwner,
address indexed newPendingOwner
);
/**
* @dev Modifier throws if called by any account other than the pendingOwner.
*/
modifier onlyPendingOwner() {
require(msg.sender == pendingOwner);
_;
}
/**
* @dev Allows the current owner to set the pendingOwner address.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(
address newOwner
) public virtual override onlyOwner {
emit OwnershipTransferPending(pendingOwner, newOwner);
pendingOwner = newOwner;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer.
*/
function claimOwnership() public onlyPendingOwner {
emit OwnershipTransferred(owner, pendingOwner);
owner = pendingOwner;
_setupRole(DEFAULT_ADMIN_ROLE, owner);
pendingOwner = address(0);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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 Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "./Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.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 ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* See https://github.com/ethereum/EIPs/issues/179
*/
abstract contract ERC20Basic {
function totalSupply() public view virtual returns (uint256);
function balanceOf(address _who) public view virtual returns (uint256);
function transfer(
address _to,
uint256 _value
) public virtual returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./TokenStorage.sol";
/**
* @title ERC20Lib
* @dev Standard ERC20 token functionality.
* https://github.com/ethereum/EIPs/issues/20
*/
library ERC20Lib {
/**
* @dev Transfers tokens [ERC20].
* @param db Token storage to operate on.
* @param caller Address of the caller passed through the frontend.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
*/
function transfer(
TokenStorage db,
address caller,
address to,
uint256 amount
) external returns (bool success) {
db.subBalance(caller, amount);
db.addBalance(to, amount);
return true;
}
/**
* @dev Transfers tokens from a specific address [ERC20].
* The address owner has to approve the spender beforehand.
* @param db Token storage to operate on.
* @param caller Address of the caller passed through the frontend.
* @param from Address to debet the tokens from.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
*/
function transferFrom(
TokenStorage db,
address caller,
address from,
address to,
uint256 amount
) external returns (bool success) {
uint256 allowance_ = db.getAllowed(from, caller);
db.subBalance(from, amount);
db.addBalance(to, amount);
db.setAllowed(from, caller, allowance_ - amount);
return true;
}
/**
* @dev Approves a spender [ERC20].
* Note that using the approve/transferFrom presents a possible
* security vulnerability described in:
* https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#heading=h.quou09mcbpzw
* Use transferAndCall to mitigate.
* @param db Token storage to operate on.
* @param caller Address of the caller passed through the frontend.
* @param spender The address of the future spender.
* @param amount The allowance of the spender.
*/
function approve(
TokenStorage db,
address caller,
address spender,
uint256 amount
) public returns (bool success) {
db.setAllowed(caller, spender, amount);
return true;
}
/**
* @dev Returns the number tokens associated with an address.
* @param db Token storage to operate on.
* @param who Address to lookup.
* @return balance Balance of address.
*/
function balanceOf(
TokenStorage db,
address who
) external view returns (uint256 balance) {
return db.getBalance(who);
}
/**
* @dev Returns the allowance for a spender
* @param db Token storage to operate on.
* @param owner The address of the owner of the tokens.
* @param spender The address of the spender.
* @return remaining Number of tokens the spender is allowed to spend.
*/
function allowance(
TokenStorage db,
address owner,
address spender
) external view returns (uint256 remaining) {
return db.getAllowed(owner, spender);
}
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./Address.sol";
import "./IERC677Recipient.sol";
import "./TokenStorage.sol";
import "./ERC20Lib.sol";
/**
* @title ERC677
* @dev ERC677 token functionality.
* https://github.com/ethereum/EIPs/issues/677
*/
library ERC677Lib {
using ERC20Lib for TokenStorage;
using Address for address;
/**
* @dev Transfers tokens and subsequently calls a method on the recipient [ERC677].
* If the recipient is a non-contract address this method behaves just like transfer.
* @notice db.transfer either returns true or reverts.
* @param db Token storage to operate on.
* @param caller Address of the caller passed through the frontend.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
* @param data Additional data passed to the recipient's tokenFallback method.
*/
function transferAndCall(
TokenStorage db,
address caller,
address to,
uint256 amount,
bytes calldata data
) external returns (bool) {
require(db.transfer(caller, to, amount), "unable to transfer");
if (to.isContract()) {
IERC677Recipient recipient = IERC677Recipient(to);
require(
recipient.onTokenTransfer(caller, amount, data),
"token handler returns false"
);
}
return true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./Ownable.sol";
/**
* @title Contracts that should not own Contracts
* @author Remco Bloemen <remco@2π.com>
* @dev Should contracts (anything Ownable) end up being owned by this contract, it allows the owner
* of this contract to reclaim ownership of the contracts.
*/
contract HasNoContracts is Ownable {
/**
* @dev Reclaim ownership of Ownable contracts
* @param _contractAddr The address of the Ownable to be reclaimed.
*/
function reclaimContract(address _contractAddr) external onlyOwner {
Ownable contractInst = Ownable(_contractAddr);
contractInst.transferOwnership(owner);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./Ownable.sol";
/**
* @title Contracts that should not own Ether
* @author Remco Bloemen <remco@2π.com>
* @dev This tries to block incoming ether to prevent accidental loss of Ether. Should Ether end up
* in the contract, it will allow the owner to reclaim this Ether.
* @notice Ether can still be sent to this contract by:
* calling functions labeled `payable`
* `selfdestruct(contract_address)`
* mining directly to the contract address
*/
contract HasNoEther is Ownable {
/**
* @dev Constructor that rejects incoming Ether
* The `payable` flag is added so we can access `msg.value` without compiler warning. If we
* leave out payable, then Solidity will allow inheriting contracts to implement a payable
* constructor. By doing it this way we prevent a payable constructor from working. Alternatively
* we could use assembly to access msg.value.
*/
constructor() payable {
require(msg.value == 0);
}
/**
* @dev Disallows direct send by setting a default function without the `payable` flag.
*/
fallback() external {}
/**
* @dev Transfer all Ether held by the contract to the owner.
*/
function reclaimEther() external onlyOwner {
payable(owner).transfer(address(this).balance);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./CanReclaimToken.sol";
/**
* @title Contracts that should not own Tokens
* @author Remco Bloemen <remco@2π.com>
* @dev This blocks incoming ERC223 tokens to prevent accidental loss of tokens.
* Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
* owner to reclaim the tokens.
*/
contract HasNoTokens is CanReclaimToken {
/**
* @dev Reject all ERC223 compatible tokens
* @param _from address The address that is transferring the tokens
* @param _value uint256 the amount of the specified token
* @param _data Bytes The data passed from the caller.
*/
function tokenFallback(
address _from,
uint256 _value,
bytes calldata _data
) external pure {
_from;
_value;
_data;
revert();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @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.1 (interfaces/IERC1271.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*
* _Available since v4.1._
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see `ERC20Detailed`.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `Transfer` event.
*/
function transfer(
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through `transferFrom`. This is
* zero by default.
*
* This value changes when `approve` or `transferFrom` are called.
*/
function allowance(
address owner,
address spender
) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* > Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an `Approval` event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `Transfer` event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to `approve`. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
/**
* @title IERC677Recipient
* @dev Contracts implementing this interface can participate in [ERC677].
*/
interface IERC677Recipient {
/**
* @dev Receives notification from [ERC677] transferAndCall.
* @param from Sender address.
* @param amount Number of tokens.
* @param data Additional data.
*/
function onTokenTransfer(
address from,
uint256 amount,
bytes calldata data
) external returns (bool);
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
/**
* @title IValidator
* @dev Contracts implementing this interface validate token transfers.
*/
interface IValidator {
/**
* @dev Emitted when a validator makes a decision.
* @param from Sender address.
* @param to Recipient address.
* @param amount Number of tokens.
* @param valid True if transfer approved, false if rejected.
*/
event Decision(
address indexed from,
address indexed to,
uint256 amount,
bool valid
);
/**
* @dev Validates token transfer.
* If the sender is on the blacklist the transfer is denied.
* @param from Sender address.
* @param to Recipient address.
* @param amount Number of tokens.
*/
function validate(
address from,
address to,
uint256 amount
) external returns (bool valid);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./StandardController.sol";
import "./MintableTokenLib.sol";
/**
* @title MintableController
* @dev This contracts implements functionality allowing for minting and burning of tokens.
*/
contract MintableController is StandardController {
using MintableTokenLib for TokenStorage;
mapping(address => uint256) internal mintAllowances;
uint256 internal maxMintAllowance;
/**
* @dev Contract constructor.
* @param storage_ Address of the token storage for the controller.
* @param initialSupply The amount of tokens to mint upon creation.
* @param frontend_ Address of the authorized frontend.
*/
constructor(
address storage_,
uint256 initialSupply,
address frontend_
) StandardController(storage_, initialSupply, frontend_) {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
/**
* @dev Emitted when allowance is set.
* @param account The address of the account.
* @param amount The amount of allowance.
*/
event MintAllowance(address indexed account, uint256 amount);
/**
* @dev Emitted when max allowance is set.
* @param amount The amount of allowance.
*/
event MaxMintAllowance(uint256 amount);
/**
* @dev modifier to restrict access to system accounts with enough allowance
* @param account The address of the account.
* @param amount The amount of allowance.
*/
modifier onlyAllowedSystemAccount(address account, uint256 amount) {
require(
hasRole(SYSTEM_ROLE, account),
"MintableController: caller is not a system account"
);
require(
mintAllowances[account] >= amount,
"MintableController: caller is not allowed to perform this action"
);
_;
}
/**
* @dev Mints new tokens.
* @param caller Address of the caller passed through the frontend.
* @param to Address to credit the tokens.
* @param amount Number of tokens to mint.
*/
function mintTo_withCaller(
address caller,
address to,
uint256 amount
)
public
onlyFrontend
onlyAllowedSystemAccount(caller, amount)
returns (bool)
{
_avoidBlackholes(to);
mintAllowances[caller] = mintAllowances[caller] - amount;
require(token.mint(to, amount), "MintableController: mint failed");
return true;
}
/**
* @dev Burns tokens from token owner.
* This removes the burned tokens from circulation.
* @param caller Address of the caller passed through the frontend.
* @param from Address of the token owner.
* @param amount Number of tokens to burn.
* @param h Hash which the token owner signed.
* @param v Signature component.
* @param r Signature component.
* @param s Sigature component.
*/
function burnFrom_withCaller(
address caller,
address from,
uint256 amount,
bytes32 h,
uint8 v,
bytes32 r,
bytes32 s
) public onlyFrontend onlySystemAccount(caller) returns (bool) {
require(
token.burn(from, amount, h, v, r, s),
"MintableController: burn failed"
);
return true;
}
/**
* @dev Burns tokens from token owner.
* This removes the burned tokens from circulation.
* @param from Address of the token owner.
* @param amount Number of tokens to burn.
*/
function burnFrom(
address from,
uint256 amount
) public onlyFrontend onlySystemAccount(msg.sender) returns (bool) {
require(token.burn(from, amount), "MintableController: burn failed");
return true;
}
/**
* @dev set maximum allowance for system accounts.
* @param amount The amount of allowance.
*/
function setMaxMintAllowance(uint256 amount) public virtual onlyOwner {
emit MaxMintAllowance(amount);
maxMintAllowance = amount;
}
/**
* @dev get maximum allowance for system accounts.
* @return The amount of allowance.
*/
function getMaxMintAllowance() public view virtual returns (uint256) {
return maxMintAllowance;
}
/**
* @dev set allowance for an account.
* @param account The address of the account.
* @param amount The amount of allowance.
*/
function setMintAllowance(
address account,
uint256 amount
) public virtual onlyAdminAccounts {
require(
amount <= maxMintAllowance,
"MintableController: allowance exceeds maximum setted by owner"
);
mintAllowances[account] = amount;
emit MintAllowance(account, amount);
}
/**
* @dev get allowance for an account.
* @param account The address of the account.
* @return The amount of allowance.
*/
function getMintAllowance(
address account
) public view virtual returns (uint256) {
return mintAllowances[account];
}
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./SignatureChecker.sol";
import "./ERC20Lib.sol";
import "./TokenStorage.sol";
/**
* @title Mintable token
* @dev Simple ERC20 Token example, with mintable token creation
* @dev Issue: * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/120
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
*/
library MintableTokenLib {
using SignatureChecker for address;
/**
* @dev Mints new tokens.
* @param db Token storage to operate on.
* @param to The address that will recieve the minted tokens.
* @param amount The amount of tokens to mint.
*/
function mint(
TokenStorage db,
address to,
uint256 amount
) external returns (bool) {
db.addBalance(to, amount);
return true;
}
/**
* @dev Burns tokens.
* @param db Token storage to operate on.
* @param from The address holding tokens.
* @param amount The amount of tokens to burn.
*/
function burn(
TokenStorage db,
address from,
uint256 amount
) public returns (bool) {
db.subBalance(from, amount);
return true;
}
/**
* @dev Burns tokens from a specific address.
* To burn the tokens the caller needs to provide a signature
* proving that the caller is authorized by the token owner to do so.
* @param db Token storage to operate on.
* @param from The address holding tokens.
* @param amount The amount of tokens to burn.
* @param h Hash which the token owner signed.
* @param v Signature component.
* @param r Signature component.
* @param s Sigature component.
*/
function burn(
TokenStorage db,
address from,
uint256 amount,
bytes32 h,
uint8 v,
bytes32 r,
bytes32 s
) external returns (bool) {
bytes memory signature;
if (r != bytes32(0) || s != bytes32(0)) {
signature = bytes(abi.encodePacked(r, s, v));
}
require(
from.isValidSignatureNow(h, signature),
"signature/hash does not match"
);
return burn(db, from, amount);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./HasNoEther.sol";
import "./HasNoTokens.sol";
import "./HasNoContracts.sol";
/**
* @title Base contract for contracts that should not own things.
* @author Remco Bloemen <remco@2π.com>
* @dev Solves a class of errors where a contract accidentally becomes owner of Ether, Tokens or
* Owned contracts. See respective base contracts for details.
*/
contract NoOwner is HasNoEther, HasNoTokens, HasNoContracts {
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public virtual onlyOwner {
_transferOwnership(_newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function _transferOwnership(address _newOwner) internal {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./ERC20Basic.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure.
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
function safeTransfer(
ERC20Basic _token,
address _to,
uint256 _value
) internal {
require(_token.transfer(_to, _value));
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/SignatureChecker.sol)
pragma solidity ^0.8.0;
import "./ECDSA.sol";
import "./Address.sol";
import "./IERC1271.sol";
/**
* @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
* signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
* Argent and Gnosis Safe.
*
* _Available since v4.1._
*/
library SignatureChecker {
/**
* @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
* signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function isValidSignatureNow(
address signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
(address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
if (error == ECDSA.RecoverError.NoError && recovered == signer) {
return true;
}
(bool success, bytes memory result) = signer.staticcall(
abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
);
return (success &&
result.length == 32 &&
abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
}
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./ERC20Lib.sol";
import "./MintableTokenLib.sol";
import "./IValidator.sol";
import "./SignatureChecker.sol";
/**
* @title SmartTokenLib
* @dev This library provides functionality which is required from a regulatory perspective.
*/
library SmartTokenLib {
using ERC20Lib for TokenStorage;
using MintableTokenLib for TokenStorage;
using SignatureChecker for address;
struct SmartStorage {
IValidator validator;
}
/**
* @dev Emitted when the contract owner recovers tokens.
* @param from Sender address.
* @param to Recipient address.
* @param amount Number of tokens.
*/
event Recovered(address indexed from, address indexed to, uint256 amount);
/**
* @dev Emitted when updating the validator.
* @param old Address of the old validator.
* @param current Address of the new validator.
*/
event Validator(address indexed old, address indexed current);
/**
* @dev Sets a new validator.
* @param self Smart storage to operate on.
* @param validator Address of validator.
*/
function setValidator(
SmartStorage storage self,
address validator
) external {
emit Validator(address(self.validator), validator);
self.validator = IValidator(validator);
}
/**
* @dev Approves or rejects a transfer request.
* The request is forwarded to a validator which implements
* the actual business logic.
* @param self Smart storage to operate on.
* @param from Sender address.
* @param to Recipient address.
* @param amount Number of tokens.
*/
function validate(
SmartStorage storage self,
address from,
address to,
uint256 amount
) external returns (bool valid) {
return self.validator.validate(from, to, amount);
}
/**
* @dev Recovers tokens from an address and reissues them to another address.
* In case a user loses its private key the tokens can be recovered by burning
* the tokens from that address and reissuing to a new address.
* To recover tokens the contract owner needs to provide a signature
* proving that the token owner has authorized the owner to do so.
* @param from Address to burn tokens from.
* @param to Address to mint tokens to.
* @param h Hash which the token owner signed.
* @param v Signature component.
* @param r Signature component.
* @param s Sigature component.
* @return Amount recovered.
*/
function recover(
TokenStorage token,
address from,
address to,
bytes32 h,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256) {
bytes memory signature;
if (r != bytes32(0) || s != bytes32(0)) {
signature = bytes(abi.encodePacked(r, s, v));
}
require(
from.isValidSignatureNow(h, signature),
"signature/hash does not recover from address"
);
uint256 amount = token.balanceOf(from);
require(token.burn(from, amount), "burn failed");
require(token.mint(to, amount), "mint failed");
emit Recovered(from, to, amount);
return amount;
}
/**
* @dev Gets the current validator.
* @param self Smart storage to operate on.
* @return Address of validator.
*/
function getValidator(
SmartStorage storage self
) external view returns (address) {
return address(self.validator);
}
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./TokenStorage.sol";
import "./IERC20.sol";
import "./ERC20Lib.sol";
import "./ERC677Lib.sol";
import "./ClaimableSystemRole.sol";
/**
* @title StandardController
* @dev This is the base contract which delegates token methods [ERC20 and ERC677]
* to their respective library implementations.
* The controller is primarily intended to be interacted with via a token frontend.
*/
contract StandardController is ClaimableSystemRole {
using ERC20Lib for TokenStorage;
using ERC677Lib for TokenStorage;
TokenStorage internal token;
address internal frontend;
mapping(address => bool) internal bridgeFrontends;
uint8 public decimals = 18;
/**
* @dev Emitted when updating the frontend.
* @param old Address of the old frontend.
* @param current Address of the new frontend.
*/
event Frontend(address indexed old, address indexed current);
/**
* @dev Emitted when updating the Bridge frontend.
* @param frontend Address of the new Bridge frontend.
* @param title String of the frontend name.
*/
event BridgeFrontend(address indexed frontend, string indexed title);
/**
* @dev Emitted when removing a Bridge frontend.
* @param frontend Address of the Bridge frontend.
*/
event BridgeFrontendRemoved(address indexed frontend);
/**
* @dev Emitted when updating the storage.
* @param old Address of the old storage.
* @param current Address of the new storage.
*/
event Storage(address indexed old, address indexed current);
/**
* @dev Modifier which prevents the function from being called by unauthorized parties.
* The caller must be the frontend otherwise the call is reverted.
*/
modifier onlyFrontend() {
require(isFrontend(msg.sender));
_;
}
/**
* @dev Contract constructor.
* @param storage_ Address of the token storage for the controller.
* @param initialSupply The amount of tokens to mint upon creation.
* @param frontend_ Address of the authorized frontend.
*/
constructor(address storage_, uint256 initialSupply, address frontend_) {
require(
storage_ == address(0x0) || initialSupply == 0,
"either a token storage must be initialized or no initial supply"
);
if (storage_ == address(0x0)) {
token = new TokenStorage();
token.addBalance(msg.sender, initialSupply);
} else {
token = TokenStorage(storage_);
}
frontend = frontend_;
}
/**
* @dev Prevents tokens to be sent to well known blackholes by throwing on known blackholes.
* @param to The address of the intended recipient.
*/
function _avoidBlackholes(address to) internal view {
require(to != address(0x0), "must not send to 0x0");
require(to != address(this), "must not send to controller");
require(to != address(token), "must not send to token storage");
require(to != frontend, "must not send to frontend");
require(isFrontend(to) == false, "must not send to bridgeFrontends");
}
/**
* @dev Returns the current frontend.
* @return Address of the frontend.
*/
function getFrontend() external view returns (address) {
return frontend;
}
/**
* @dev Returns the current storage.
* @return Address of the storage.
*/
function getStorage() external view returns (address) {
return address(token);
}
/**
* @dev Sets a new frontend.
* @param frontend_ Address of the new frontend.
*/
function setFrontend(address frontend_) public onlyOwner {
emit Frontend(frontend, frontend_);
frontend = frontend_;
}
/**
* @dev Set a new bridge frontend.
* @param frontend_ Address of the new bridge frontend.
* @param title Keccack256 hash of the frontend title.
*/
function setBridgeFrontend(
address frontend_,
string calldata title
) public onlyOwner {
bridgeFrontends[frontend_] = true;
emit BridgeFrontend(frontend_, title);
}
/**
* @dev Removes a bridge frontend.
* @param frontend_ Address of the bridge frontend to remove.
*/
function removeBridgeFrontend(address frontend_) public onlyOwner {
bridgeFrontends[frontend_] = false;
emit BridgeFrontendRemoved(frontend_);
}
/**
* @dev Checks wether an address is a frontend.
* @param frontend_ Address of the frontend candidate.
*/
function isFrontend(address frontend_) public view returns (bool) {
return (frontend_ == frontend) || bridgeFrontends[frontend_];
}
/**
* @dev Sets a new storage.
* @param storage_ Address of the new storage.
*/
function setStorage(address storage_) external onlyOwner {
emit Storage(address(token), storage_);
token = TokenStorage(storage_);
}
/**
* @dev Transfers the ownership of the storage.
* @param newOwner Address of the new storage owner.
*/
function transferStorageOwnership(address newOwner) public onlyOwner {
token.transferOwnership(newOwner);
}
/**
* @dev Claims the ownership of the storage.
*/
function claimStorageOwnership() public onlyOwner {
token.claimOwnership();
}
/**
* @dev Transfers tokens [ERC20].
* @param caller Address of the caller passed through the frontend.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
*/
function transfer_withCaller(
address caller,
address to,
uint256 amount
) public virtual onlyFrontend returns (bool ok) {
_avoidBlackholes(to);
return token.transfer(caller, to, amount);
}
/**
* @dev Transfers tokens from a specific address [ERC20].
* The address owner has to approve the spender beforehand.
* @param caller Address of the caller passed through the frontend.
* @param from Address to debet the tokens from.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
*/
function transferFrom_withCaller(
address caller,
address from,
address to,
uint256 amount
) public virtual onlyFrontend returns (bool ok) {
_avoidBlackholes(to);
return token.transferFrom(caller, from, to, amount);
}
/**
* @dev Approves a spender [ERC20].
* Note that using the approve/transferFrom presents a possible
* security vulnerability described in:
* https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#heading=h.quou09mcbpzw
* Use transferAndCall to mitigate.
* @param caller Address of the caller passed through the frontend.
* @param spender The address of the future spender.
* @param amount The allowance of the spender.
*/
function approve_withCaller(
address caller,
address spender,
uint256 amount
) public onlyFrontend returns (bool ok) {
return token.approve(caller, spender, amount);
}
/**
* @dev Transfers tokens and subsequently calls a method on the recipient [ERC677].
* If the recipient is a non-contract address this method behaves just like transfer.
* @param caller Address of the caller passed through the frontend.
* @param to Recipient address.
* @param amount Number of tokens to transfer.
* @param data Additional data passed to the recipient's tokenFallback method.
*/
function transferAndCall_withCaller(
address caller,
address to,
uint256 amount,
bytes calldata data
) public virtual onlyFrontend returns (bool ok) {
_avoidBlackholes(to);
return token.transferAndCall(caller, to, amount, data);
}
/**
* @dev Returns the total supply.
* @return Number of tokens.
*/
function totalSupply() external view returns (uint) {
return token.getSupply();
}
/**
* @dev Returns the number tokens associated with an address.
* @param who Address to lookup.
* @return Balance of address.
*/
function balanceOf(address who) external view returns (uint) {
return token.getBalance(who);
}
/**
* @dev Returns the allowance for a spender
* @param owner The address of the owner of the tokens.
* @param spender The address of the spender.
* @return Number of tokens the spender is allowed to spend.
*/
function allowance(
address owner,
address spender
) external view returns (uint) {
return token.allowance(owner, spender);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./Math.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @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] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./AccessControl.sol";
import "./Ownable.sol";
/**
* @title SystemRole
* @dev SystemRole accounts have been approved to perform operational actions (e.g. mint and burn).
* @dev AdminRole accounts have been approved to perform administrative actions (e.g. setting allowances).
* @notice The contract is an abstract contract.
*/
abstract contract SystemRole is AccessControl, Ownable {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant SYSTEM_ROLE = keccak256("SYSTEM_ROLE");
/**
* @dev Emitted when system account is added.
* @param account The address of the account.
*/
event SystemAccountAdded(address indexed account);
/**
* @dev Emitted when system account is removed.
* @param account The address of the account.
*/
event SystemAccountRemoved(address indexed account);
/**
* @dev Emitted when admin account is added.
* @param account The address of the account.
*/
event AdminAccountAdded(address indexed account);
/**
* @dev Emitted when admin account is removed.
* @param account The address of the account.
*/
event AdminAccountRemoved(address indexed account);
/**
* @dev modifier to restrict access to system accounts.
*/
modifier onlySystemAccounts() {
require(
hasRole(SYSTEM_ROLE, msg.sender),
"SystemRole: caller is not a system account"
);
_;
}
/**
* @dev modifier to restrict access to system accounts.
* @param account The address of the account.
*/
modifier onlySystemAccount(address account) {
require(
hasRole(SYSTEM_ROLE, account),
"SystemRole: caller is not a system account"
);
_;
}
/**
* @dev modifier to restrict access to admin accounts.
*/
modifier onlyAdminAccounts() {
require(
hasRole(ADMIN_ROLE, msg.sender),
"SystemRole: caller is not an admin account"
);
_;
}
/**
* @dev modifier to restrict access to admin accounts.
* @param account The address of the account.
*/
modifier onlyAdminAccount(address account) {
require(
hasRole(ADMIN_ROLE, account),
"SystemRole: caller is not an admin account"
);
_;
}
/**
* @dev Checks wether an address is a system account.
* @param account The address of the account.
* @return true if system account.
*/
function isSystemAccount(address account) public view returns (bool) {
return hasRole(SYSTEM_ROLE, account);
}
/**
* @dev add system account.
* @param account The address of the account.
*/
function addSystemAccount(address account) public virtual onlyOwner {
grantRole(SYSTEM_ROLE, account);
emit SystemAccountAdded(account);
}
/**
* @dev remove system account.
* @param account The address of the account.
*/
function removeSystemAccount(address account) public virtual onlyOwner {
revokeRole(SYSTEM_ROLE, account);
emit SystemAccountRemoved(account);
}
/**
* @dev add admin account.
* @param account The address of the account.
*/
function addAdminAccount(address account) public virtual onlyOwner {
grantRole(ADMIN_ROLE, account);
emit AdminAccountAdded(account);
}
/**
* @dev remove admin account.
* @param account The address of the account.
*/
function removeAdminAccount(address account) public virtual onlyOwner {
revokeRole(ADMIN_ROLE, account);
emit AdminAccountRemoved(account);
}
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
import "./Claimable.sol";
import "./CanReclaimToken.sol";
import "./NoOwner.sol";
import "./TokenStorageLib.sol";
/**
* @title TokenStorage
* @dev External storage for tokens.
* The storage is implemented in a separate contract to maintain state
* between token upgrades.
*/
contract TokenStorage is Claimable, CanReclaimToken, NoOwner {
using TokenStorageLib for TokenStorageLib.TokenStorage;
TokenStorageLib.TokenStorage internal tokenStorage;
/**
* @dev Increases balance of an address.
* @param to Address to increase.
* @param amount Number of units to add.
*/
function addBalance(address to, uint256 amount) external onlyOwner {
tokenStorage.addBalance(to, amount);
}
/**
* @dev Decreases balance of an address.
* @param from Address to decrease.
* @param amount Number of units to subtract.
*/
function subBalance(address from, uint256 amount) external onlyOwner {
tokenStorage.subBalance(from, amount);
}
/**
* @dev Sets the allowance for a spender.
* @param owner Address of the owner of the tokens to spend.
* @param spender Address of the spender.
* @param amount Quantity of allowance.
*/
function setAllowed(
address owner,
address spender,
uint256 amount
) external onlyOwner {
tokenStorage.setAllowed(owner, spender, amount);
}
/**
* @dev Returns the supply of tokens.
* @return Total supply.
*/
function getSupply() external view returns (uint256) {
return tokenStorage.getSupply();
}
/**
* @dev Returns the balance of an address.
* @param who Address to lookup.
* @return Number of units.
*/
function getBalance(address who) external view returns (uint256) {
return tokenStorage.getBalance(who);
}
/**
* @dev Returns the allowance for a spender.
* @param owner Address of the owner of the tokens to spend.
* @param spender Address of the spender.
* @return Number of units.
*/
function getAllowed(
address owner,
address spender
) external view returns (uint256) {
return tokenStorage.getAllowed(owner, spender);
}
/**
* @dev Explicit override of transferOwnership from Claimable and Ownable
* @param newOwner Address to transfer ownership to.
*/
function transferOwnership(
address newOwner
) public override(Claimable, Ownable) {
Claimable.transferOwnership(newOwner);
}
}
/* SPDX-License-Identifier: apache-2.0 */
/**
* Copyright 2022 Monerium ehf.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity 0.8.11;
/*
* @title TokenStorageLib
* @dev Implementation of an[external storage for tokens.
*/
library TokenStorageLib {
struct TokenStorage {
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
uint256 totalSupply;
}
/**
* @dev Increases balance of an address.
* @param self Token storage to operate on.
* @param to Address to increase.
* @param amount Number of units to add.
*/
function addBalance(
TokenStorage storage self,
address to,
uint256 amount
) external {
self.totalSupply = self.totalSupply + amount;
self.balances[to] = self.balances[to] + amount;
}
/**
* @dev Decreases balance of an address.
* @param self Token storage to operate on.
* @param from Address to decrease.
* @param amount Number of units to subtract.
*/
function subBalance(
TokenStorage storage self,
address from,
uint256 amount
) external {
self.totalSupply = self.totalSupply - amount;
self.balances[from] = self.balances[from] - amount;
}
/**
* @dev Sets the allowance for a spender.
* @param self Token storage to operate on.
* @param owner Address of the owner of the tokens to spend.
* @param spender Address of the spender.
* @param amount Qunatity of allowance.
*/
function setAllowed(
TokenStorage storage self,
address owner,
address spender,
uint256 amount
) external {
self.allowed[owner][spender] = amount;
}
/**
* @dev Returns the supply of tokens.
* @param self Token storage to operate on.
* @return Total supply.
*/
function getSupply(TokenStorage storage self) external view returns (uint) {
return self.totalSupply;
}
/**
* @dev Returns the balance of an address.
* @param self Token storage to operate on.
* @param who Address to lookup.
* @return Number of units.
*/
function getBalance(
TokenStorage storage self,
address who
) external view returns (uint) {
return self.balances[who];
}
/**
* @dev Returns the allowance for a spender.
* @param self Token storage to operate on.
* @param owner Address of the owner of the tokens to spend.
* @param spender Address of the spender.
* @return Number of units.
*/
function getAllowed(
TokenStorage storage self,
address owner,
address spender
) external view returns (uint) {
return self.allowed[owner][spender];
}
}
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"storage_","type":"address"},{"internalType":"address","name":"validator","type":"address"},{"internalType":"bytes3","name":"ticker_","type":"bytes3"},{"internalType":"address","name":"frontend_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AdminAccountAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AdminAccountRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"frontend","type":"address"},{"indexed":true,"internalType":"string","name":"title","type":"string"}],"name":"BridgeFrontend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"frontend","type":"address"}],"name":"BridgeFrontendRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"current","type":"address"}],"name":"Frontend","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MaxMintAllowance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MintAllowance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousPendingOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"OwnershipTransferPending","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"current","type":"address"}],"name":"Storage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"SystemAccountAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"SystemAccountRemoved","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SYSTEM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAdminAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addSystemAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve_withCaller","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"h","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"burnFrom_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimStorageOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrontend","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxMintAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getMintAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidator","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"address","name":"frontend_","type":"address"}],"name":"isFrontend","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isSystemAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintTo_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32","name":"h","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"recover_withCaller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeAdminAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"frontend_","type":"address"}],"name":"removeBridgeFrontend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeSystemAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","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":"frontend_","type":"address"},{"internalType":"string","name":"title","type":"string"}],"name":"setBridgeFrontend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"frontend_","type":"address"}],"name":"setFrontend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMaxMintAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMintAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"storage_","type":"address"}],"name":"setStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"}],"name":"setValidator","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":[],"name":"ticker","outputs":[{"internalType":"bytes3","name":"","type":"bytes3"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"transferAndCall_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferStorageOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040526006805460ff191660121790553480156200001e57600080fd5b5060405162003bed38038062003bed8339810160408190526200004191620003c1565b600180546001600160a01b03191633179055836000828282826001600160a01b03831615806200006f575081155b620000e75760405162461bcd60e51b815260206004820152603f60248201527f656974686572206120746f6b656e2073746f72616765206d757374206265206960448201527f6e697469616c697a6564206f72206e6f20696e697469616c20737570706c790060648201526084015b60405180910390fd5b6001600160a01b0383166200019e57604051620001049062000396565b604051809103906000f08015801562000121573d6000803e3d6000fd5b50600380546001600160a01b0319166001600160a01b039290921691821790556040516310f29c1d60e11b8152336004820152602481018490526321e5383a90604401600060405180830381600087803b1580156200017f57600080fd5b505af115801562000194573d6000803e3d6000fd5b50505050620001ba565b600380546001600160a01b0319166001600160a01b0385161790555b600480546001600160a01b0319166001600160a01b039290921691909117905550620001ea9050600033620002e6565b5050506001600160a01b038316620002515760405162461bcd60e51b8152602060048201526024808201527f76616c696461746f722063616e6e6f7420626520746865206e756c6c206164646044820152637265737360e01b6064820152608401620000de565b60405163ad41534960e01b8152600960048201526001600160a01b038416602482015273ceb6728300915d56ac58fc99b4becc01a630ed8a9063ad4153499060440160006040518083038186803b158015620002ac57600080fd5b505af4158015620002c1573d6000803e3d6000fd5b5050600a805462ffffff191660e89590951c94909417909355506200042d9350505050565b620002f28282620002f6565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620002f2576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620003523390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b610b1780620030d683390190565b80516001600160a01b0381168114620003bc57600080fd5b919050565b60008060008060808587031215620003d857600080fd5b620003e385620003a4565b9350620003f360208601620003a4565b60408601519093506001600160e81b0319811681146200041257600080fd5b91506200042260608601620003a4565b905092959194509250565b612c99806200043d6000396000f3fe608060405234801561001057600080fd5b50600436106103145760003560e01c806375b238fc116101a7578063a84c56d0116100ee578063e974fee911610097578063f27c5f6e11610071578063f27c5f6e146106e6578063f2fde38b146106f9578063fd2319c41461070c57600080fd5b8063e974fee9146106ad578063ebbc3d46146106c0578063ee0b5445146106d357600080fd5b8063dd62ed3e116100c8578063dd62ed3e14610674578063e174fd9414610687578063e30c39781461069a57600080fd5b8063a84c56d014610646578063b516af7014610659578063d547741f1461066157600080fd5b80638fb81d98116101505780639e7f43ca1161012a5780639e7f43ca1461062b5780639ea33e191461063e578063a217fddf146103e257600080fd5b80638fb81d98146105ce5780639137c1a7146105e157806391d14854146105f457600080fd5b8063802d441f11610181578063802d441f1461056a5780638ba47bdd1461057d5780638da5cb5b146105bb57600080fd5b806375b238fc1461051d578063774d54091461054457806379cc67901461055757600080fd5b8063326ecb051161026b5780634eb007541161021457806369569a51116101ee57806369569a51146104d057806370a08231146104e357806375071d2a146104f657600080fd5b80634eb00754146104975780634fe57e7a146104aa57806367a89a72146104bd57600080fd5b80633cd1570f116102455780633cd1570f146104535780634a36703b146104665780634e71e0c81461048f57600080fd5b8063326ecb051461041c5780633408f73a1461042f57806336568abe1461044057600080fd5b8063248a9ca3116102cd5780632ff2e9dc116102a75780632ff2e9dc146103e2578063313ce567146103ea578063322ec0fb1461040957600080fd5b8063248a9ca31461039957806325ec2eb0146103bc5780632f2ff15d146103cf57600080fd5b80631195e07e116102fe5780631195e07e146103665780631327d3d81461036e57806318160ddd1461038357600080fd5b80623074ff1461031957806301ffc9a714610343575b600080fd5b6004546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b61035661035136600461267e565b61071f565b604051901515815260200161033a565b6103266107b8565b61038161037c3660046126d5565b61084d565b005b61038b6108f2565b60405190815260200161033a565b61038b6103a73660046126f2565b60009081526020819052604090206001015490565b6103566103ca3660046126d5565b610979565b6103816103dd36600461270b565b6109b2565b61038b600081565b6006546103f79060ff1681565b60405160ff909116815260200161033a565b61035661041736600461273b565b6109dc565b61035661042a3660046126d5565b610c78565b6003546001600160a01b0316610326565b61038161044e36600461270b565b610cb8565b61038b610461366004612792565b610d44565b61038b6104743660046126d5565b6001600160a01b031660009081526007602052604090205490565b610381610ed1565b6103566104a5366004612809565b610f66565b6103816104b83660046126d5565b611137565b6103816104cb3660046126d5565b6111af565b6103816104de3660046126d5565b611227565b61038b6104f13660046126d5565b61129a565b61038b7f5719df9ef2c4678b547f89e4f5ae410dbf400fc51cf3ded434c55f6adea2c43f81565b61038b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b61035661055236600461273b565b611322565b61035661056536600461285b565b6113ef565b6103816105783660046126d5565b611592565b600a5461058a9060e81b81565b6040517fffffff0000000000000000000000000000000000000000000000000000000000909116815260200161033a565b600154610326906001600160a01b031681565b6103816105dc3660046128d0565b6115f2565b6103816105ef3660046126d5565b61167c565b61035661060236600461270b565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b610356610639366004612925565b6116ef565b60085461038b565b6103816106543660046126d5565b61180d565b610381611885565b61038161066f36600461270b565b611906565b61038b610682366004612998565b61192b565b61035661069536600461273b565b6119de565b600254610326906001600160a01b031681565b6103566106bb3660046129c6565b611aca565b6103816106ce3660046126d5565b611bc0565b6103816106e13660046126d5565b611c38565b6103816106f436600461285b565b611cc3565b6103816107073660046126d5565b611e38565b61038161071a3660046126f2565b611eab565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107b257507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6040517f6271970c0000000000000000000000000000000000000000000000000000000081526009600482015260009073ceb6728300915d56ac58fc99b4becc01a630ed8a90636271970c90602401602060405180830381865af4158015610824573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108489190612a17565b905090565b6001546001600160a01b0316331461086457600080fd5b6040517fad415349000000000000000000000000000000000000000000000000000000008152600960048201526001600160a01b038216602482015273ceb6728300915d56ac58fc99b4becc01a630ed8a9063ad4153499060440160006040518083038186803b1580156108d757600080fd5b505af41580156108eb573d6000803e3d6000fd5b5050505050565b600354604080517f6c9c2faf00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691636c9c2faf9160048083019260209291908290030181865afa158015610955573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108489190612a34565b6004546000906001600160a01b03838116911614806107b25750506001600160a01b031660009081526005602052604090205460ff1690565b6000828152602081905260409020600101546109cd81611efa565b6109d78383611f07565b505050565b60006109e733610979565b6109f057600080fd5b6001600160a01b03841660009081527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe60205260409020548490839060ff16610aa65760405162461bcd60e51b815260206004820152603260248201527f4d696e7461626c65436f6e74726f6c6c65723a2063616c6c6572206973206e6f60448201527f7420612073797374656d206163636f756e74000000000000000000000000000060648201526084015b60405180910390fd5b6001600160a01b038216600090815260076020526040902054811115610b36576040805162461bcd60e51b81526020600482015260248101919091527f4d696e7461626c65436f6e74726f6c6c65723a2063616c6c6572206973206e6f60448201527f7420616c6c6f77656420746f20706572666f726d207468697320616374696f6e6064820152608401610a9d565b610b3f85611fa5565b6001600160a01b038616600090815260076020526040902054610b63908590612a63565b6001600160a01b03878116600090815260076020526040908190209290925560035491517fb0c29c7400000000000000000000000000000000000000000000000000000000815291811660048301528616602482015260448101859052731007a6c78354f0c0033d1f96bb7b6b76402af3de9063b0c29c7490606401602060405180830381865af4158015610bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c209190612a7a565b610c6c5760405162461bcd60e51b815260206004820152601f60248201527f4d696e7461626c65436f6e74726f6c6c65723a206d696e74206661696c6564006044820152606401610a9d565b50600195945050505050565b6001600160a01b03811660009081527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe602052604081205460ff166107b2565b6001600160a01b0381163314610d365760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610a9d565b610d408282612166565b5050565b6000610d4f33610979565b610d5857600080fd5b6001600160a01b03881660009081527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe6020526040902054889060ff16610df45760405162461bcd60e51b815260206004820152602a60248201527f53797374656d526f6c653a2063616c6c6572206973206e6f7420612073797374604482015269195b481858d8dbdd5b9d60b21b6064820152608401610a9d565b610dfd87611fa5565b6003546040517f8f7227340000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152898216602482015290881660448201526064810187905260ff8616608482015260a4810185905260c4810184905273ceb6728300915d56ac58fc99b4becc01a630ed8a90638f7227349060e401602060405180830381865af4158015610ea0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ec49190612a34565b9998505050505050505050565b6002546001600160a01b03163314610ee857600080fd5b6002546001546040516001600160a01b0392831692909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600254600180546001600160a01b0319166001600160a01b039092169182179055610f54906000906121e5565b600280546001600160a01b0319169055565b6000610f7133610979565b610f7a57600080fd5b6001600160a01b03881660009081527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe6020526040902054889060ff166110165760405162461bcd60e51b815260206004820152602a60248201527f53797374656d526f6c653a2063616c6c6572206973206e6f7420612073797374604482015269195b481858d8dbdd5b9d60b21b6064820152608401610a9d565b6003546040517f799639d40000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529089166024820152604481018890526064810187905260ff8616608482015260a4810185905260c48101849052731007a6c78354f0c0033d1f96bb7b6b76402af3de9063799639d49060e401602060405180830381865af41580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190612a7a565b6111285760405162461bcd60e51b815260206004820152601f60248201527f4d696e7461626c65436f6e74726f6c6c65723a206275726e206661696c6564006044820152606401610a9d565b50600198975050505050505050565b6001546001600160a01b0316331461114e57600080fd5b6111787fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775826109b2565b6040516001600160a01b038216907f5c7eb798b922f0164aa9c5340006161c64436190a49eebc58b4e6e0715700ae690600090a250565b6001546001600160a01b031633146111c657600080fd5b6111f07fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177582611906565b6040516001600160a01b038216907fc3198db98a2c50068f0a99b9297e60b2dbf0eafcde57e366e70a29f887c44e1090600090a250565b6001546001600160a01b0316331461123e57600080fd5b6004546040516001600160a01b038084169216907fcb01f884fc4203d4c1643cb0e126faeb397682c122ca8c0433776d42cdc0060a90600090a3600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546040517ff8b2cb4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063f8b2cb4f90602401602060405180830381865afa1580156112fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b29190612a34565b600061132d33610979565b61133657600080fd5b6003546040517f365feff10000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528582166024820152908416604482015260648101839052731d94e102e1c7a2cab9ba6d6d344d34d023628bd39063365feff1906084015b602060405180830381865af41580156113c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e79190612a7a565b949350505050565b60006113fa33610979565b61140357600080fd5b3360008181527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe602052604090205460ff166114945760405162461bcd60e51b815260206004820152602a60248201527f53797374656d526f6c653a2063616c6c6572206973206e6f7420612073797374604482015269195b481858d8dbdd5b9d60b21b6064820152608401610a9d565b6003546040517fa6c9ac280000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152908516602482015260448101849052731007a6c78354f0c0033d1f96bb7b6b76402af3de9063a6c9ac2890606401602060405180830381865af4158015611518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153c9190612a7a565b6115885760405162461bcd60e51b815260206004820152601f60248201527f4d696e7461626c65436f6e74726f6c6c65723a206275726e206661696c6564006044820152606401610a9d565b5060019392505050565b6001546001600160a01b031633146115a957600080fd5b6001600160a01b038116600081815260056020526040808220805460ff19169055517f10cf5a523a14a54e61c21610dc10c01e40e2ebc37baa3effd74032f7d3865e6d9190a250565b6001546001600160a01b0316331461160957600080fd5b6001600160a01b03831660009081526005602052604090819020805460ff191660011790555161163c9083908390612a9c565b604051908190038120906001600160a01b038516907fec75908259de4d038ff5f2b6b99e3725bc21871f4d2a44adeff9bb814afbc9f790600090a3505050565b6001546001600160a01b0316331461169357600080fd5b6003546040516001600160a01b038084169216907fdaaa9d417a3107fd3d9db02eba3eeafbae2b8af16ee08c534f5bc449054c1c4c90600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b6040516332c5a6eb60e01b8152600960048201526001600160a01b038087166024830152851660448201526064810184905260009073ceb6728300915d56ac58fc99b4becc01a630ed8a906332c5a6eb90608401602060405180830381865af4158015611760573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117849190612a7a565b6117f65760405162461bcd60e51b815260206004820152602160248201527f7472616e73666572416e6443616c6c2072657175657374206e6f742076616c6960448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610a9d565b61180386868686866121ef565b9695505050505050565b6001546001600160a01b0316331461182457600080fd5b61184e7f5719df9ef2c4678b547f89e4f5ae410dbf400fc51cf3ded434c55f6adea2c43f826109b2565b6040516001600160a01b038216907fdfb5b1167ef9eadf5cac67570f1a2971a6f6175303b9d4166a65a11d0a294e3490600090a250565b6001546001600160a01b0316331461189c57600080fd5b600360009054906101000a90046001600160a01b03166001600160a01b0316634e71e0c86040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156118ec57600080fd5b505af1158015611900573d6000803e3d6000fd5b50505050565b60008281526020819052604090206001015461192181611efa565b6109d78383612166565b6003546040517f1045d7ce0000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015283821660248201529082166044820152600090731d94e102e1c7a2cab9ba6d6d344d34d023628bd390631045d7ce90606401602060405180830381865af41580156119b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d79190612a34565b9392505050565b6040516332c5a6eb60e01b8152600960048201526001600160a01b038085166024830152831660448201526064810182905260009073ceb6728300915d56ac58fc99b4becc01a630ed8a906332c5a6eb90608401602060405180830381865af4158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a739190612a7a565b611abf5760405162461bcd60e51b815260206004820152601a60248201527f7472616e736665722072657175657374206e6f742076616c69640000000000006044820152606401610a9d565b6113e78484846122b2565b6040516332c5a6eb60e01b8152600960048201526001600160a01b038085166024830152831660448201526064810182905260009073ceb6728300915d56ac58fc99b4becc01a630ed8a906332c5a6eb90608401602060405180830381865af4158015611b3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5f9190612a7a565b611bab5760405162461bcd60e51b815260206004820152601e60248201527f7472616e7366657246726f6d2072657175657374206e6f742076616c696400006044820152606401610a9d565b611bb785858585612343565b95945050505050565b6001546001600160a01b03163314611bd757600080fd5b611c017f5719df9ef2c4678b547f89e4f5ae410dbf400fc51cf3ded434c55f6adea2c43f82611906565b6040516001600160a01b038216907f21bfb3de07221bc6197a8c23f7a059308b7a741f259cf4ef3b519cde0fde7ac390600090a250565b6001546001600160a01b03163314611c4f57600080fd5b6003546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063f2fde38b90602401600060405180830381600087803b158015611caf57600080fd5b505af11580156108eb573d6000803e3d6000fd5b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff16611d675760405162461bcd60e51b815260206004820152602a60248201527f53797374656d526f6c653a2063616c6c6572206973206e6f7420616e2061646d60448201527f696e206163636f756e74000000000000000000000000000000000000000000006064820152608401610a9d565b600854811115611ddf5760405162461bcd60e51b815260206004820152603d60248201527f4d696e7461626c65436f6e74726f6c6c65723a20616c6c6f77616e636520657860448201527f6365656473206d6178696d756d20736574746564206279206f776e65720000006064820152608401610a9d565b6001600160a01b03821660008181526007602052604090819020839055517f8fe74a1bbab5a9534a04463cd7b9423b985ed316426821cace8ed4aeac5a4d1490611e2c9084815260200190565b60405180910390a25050565b6001546001600160a01b03163314611e4f57600080fd5b6002546040516001600160a01b038084169216907f8573d4aae9f7fb051c6b88d7440011a1c12376acda6603a45f45bad36a8db4ce90600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b03163314611ec257600080fd5b6040518181527f34affbf2a21d1f1d12e5e49bdca58fb75dba6879f5430f2fbf5c1d07476018d29060200160405180910390a1600855565b611f048133612418565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610d40576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611f613390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6001600160a01b038116611ffb5760405162461bcd60e51b815260206004820152601460248201527f6d757374206e6f742073656e6420746f203078300000000000000000000000006044820152606401610a9d565b6001600160a01b0381163014156120545760405162461bcd60e51b815260206004820152601b60248201527f6d757374206e6f742073656e6420746f20636f6e74726f6c6c657200000000006044820152606401610a9d565b6003546001600160a01b03828116911614156120b25760405162461bcd60e51b815260206004820152601e60248201527f6d757374206e6f742073656e6420746f20746f6b656e2073746f7261676500006044820152606401610a9d565b6004546001600160a01b03828116911614156121105760405162461bcd60e51b815260206004820152601960248201527f6d757374206e6f742073656e6420746f2066726f6e74656e64000000000000006044820152606401610a9d565b61211981610979565b15611f045760405162461bcd60e51b815260206004820181905260248201527f6d757374206e6f742073656e6420746f2062726964676546726f6e74656e64736044820152606401610a9d565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610d40576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b610d408282611f07565b60006121fa33610979565b61220357600080fd5b61220c85611fa5565b6003546040517f1eb8bccb00000000000000000000000000000000000000000000000000000000815273e74b37a54e8ae26d8c6c50830804f689888ef9a091631eb8bccb91612271916001600160a01b0316908a908a908a908a908a90600401612aac565b602060405180830381865af415801561228e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118039190612a7a565b60006122bd33610979565b6122c657600080fd5b6122cf83611fa5565b6003546040517f44ded8ba0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528582166024820152908416604482015260648101839052731d94e102e1c7a2cab9ba6d6d344d34d023628bd3906344ded8ba906084016113a6565b600061234e33610979565b61235757600080fd5b61236083611fa5565b6003546040517ff3a0ddf90000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015286821660248201528582166044820152908416606482015260848101839052731d94e102e1c7a2cab9ba6d6d344d34d023628bd39063f3a0ddf99060a401602060405180830381865af41580156123f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb79190612a7a565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610d40576124498161248b565b61245483602061249d565b604051602001612465929190612b35565b60408051601f198184030181529082905262461bcd60e51b8252610a9d91600401612bb6565b60606107b26001600160a01b03831660145b606060006124ac836002612be9565b6124b7906002612c08565b67ffffffffffffffff8111156124cf576124cf612c20565b6040519080825280601f01601f1916602001820160405280156124f9576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061253057612530612c36565b60200101906001600160f81b031916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061257b5761257b612c36565b60200101906001600160f81b031916908160001a905350600061259f846002612be9565b6125aa906001612c08565b90505b600181111561262f577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106125eb576125eb612c36565b1a60f81b82828151811061260157612601612c36565b60200101906001600160f81b031916908160001a90535060049490941c9361262881612c4c565b90506125ad565b5083156119d75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a9d565b60006020828403121561269057600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146119d757600080fd5b6001600160a01b0381168114611f0457600080fd5b6000602082840312156126e757600080fd5b81356119d7816126c0565b60006020828403121561270457600080fd5b5035919050565b6000806040838503121561271e57600080fd5b823591506020830135612730816126c0565b809150509250929050565b60008060006060848603121561275057600080fd5b833561275b816126c0565b9250602084013561276b816126c0565b929592945050506040919091013590565b803560ff8116811461278d57600080fd5b919050565b600080600080600080600060e0888a0312156127ad57600080fd5b87356127b8816126c0565b965060208801356127c8816126c0565b955060408801356127d8816126c0565b9450606088013593506127ed6080890161277c565b925060a0880135915060c0880135905092959891949750929550565b600080600080600080600060e0888a03121561282457600080fd5b873561282f816126c0565b9650602088013561283f816126c0565b955060408801359450606088013593506127ed6080890161277c565b6000806040838503121561286e57600080fd5b8235612879816126c0565b946020939093013593505050565b60008083601f84011261289957600080fd5b50813567ffffffffffffffff8111156128b157600080fd5b6020830191508360208285010111156128c957600080fd5b9250929050565b6000806000604084860312156128e557600080fd5b83356128f0816126c0565b9250602084013567ffffffffffffffff81111561290c57600080fd5b61291886828701612887565b9497909650939450505050565b60008060008060006080868803121561293d57600080fd5b8535612948816126c0565b94506020860135612958816126c0565b935060408601359250606086013567ffffffffffffffff81111561297b57600080fd5b61298788828901612887565b969995985093965092949392505050565b600080604083850312156129ab57600080fd5b82356129b6816126c0565b91506020830135612730816126c0565b600080600080608085870312156129dc57600080fd5b84356129e7816126c0565b935060208501356129f7816126c0565b92506040850135612a07816126c0565b9396929550929360600135925050565b600060208284031215612a2957600080fd5b81516119d7816126c0565b600060208284031215612a4657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612a7557612a75612a4d565b500390565b600060208284031215612a8c57600080fd5b815180151581146119d757600080fd5b8183823760009101908152919050565b60006001600160a01b038089168352808816602084015280871660408401525084606083015260a060808301528260a0830152828460c0840137600060c0848401015260c0601f19601f8501168301019050979650505050505050565b60005b83811015612b24578181015183820152602001612b0c565b838111156119005750506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612b6d816017850160208801612b09565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351612baa816028840160208801612b09565b01602801949350505050565b6020815260008251806020840152612bd5816040850160208701612b09565b601f01601f19169190910160400192915050565b6000816000190483118215151615612c0357612c03612a4d565b500290565b60008219821115612c1b57612c1b612a4d565b500190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081612c5b57612c5b612a4d565b50600019019056fea2646970667358221220440686b156ac6a64c9b87b2366b5617a8d4b3945365accdb6737e8a5ec19647664736f6c634300080b0033608060405234801561001057600080fd5b50600080546001600160a01b03191633179055341561002e57600080fd5b610ada8061003d6000396000f3fe608060405234801561001057600080fd5b50600436106100e15760003560e01c80639f727c2711610086578063cf8eeb7e11610063578063cf8eeb7e146101ab578063e30c3978146101be578063f2fde38b146101d1578063f8b2cb4f146101e457005b80639f727c271461017d578063c0ee0b8a14610185578063c7c7e9ea1461019857005b806333dd1b8a116100bf57806333dd1b8a1461011c5780634e71e0c81461012f5780636c9c2faf146101375780638da5cb5b1461015257005b806317ffc320146100e357806321e5383a146100f65780632aed7f3f14610109575b005b6100e16100f136600461091d565b6101f7565b6100e161010436600461093a565b6102b3565b6100e161011736600461091d565b610361565b6100e161012a366004610966565b6103ed565b6100e16104a3565b61013f61052b565b6040519081526020015b60405180910390f35b600054610165906001600160a01b031681565b6040516001600160a01b039091168152602001610149565b6100e16105c0565b6100e16101933660046109a7565b600080fd5b61013f6101a6366004610a30565b610614565b6100e16101b936600461093a565b6106c2565b600154610165906001600160a01b031681565b6100e16101df36600461091d565b610740565b61013f6101f236600461091d565b610749565b6000546001600160a01b0316331461020e57600080fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa15801561026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102929190610a69565b6000549091506102af906001600160a01b038481169116836107ee565b5050565b6000546001600160a01b031633146102ca57600080fd5b6040517f7aeb0ed5000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b0383166024820152604481018290527366c121c0d400e57ef1ec453b72f7ecfa7c77e1dc90637aeb0ed5906064015b60006040518083038186803b15801561034557600080fd5b505af4158015610359573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461037857600080fd5b6000546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152829182169063f2fde38b90602401600060405180830381600087803b1580156103d957600080fd5b505af1158015610359573d6000803e3d6000fd5b6000546001600160a01b0316331461040457600080fd5b6040517f5599b4b7000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b03808516602483015283166044820152606481018290527366c121c0d400e57ef1ec453b72f7ecfa7c77e1dc90635599b4b79060840160006040518083038186803b15801561048657600080fd5b505af415801561049a573d6000803e3d6000fd5b50505050505050565b6001546001600160a01b031633146104ba57600080fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600180546000805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03841617909155169055565b6040517f072f9a50000000000000000000000000000000000000000000000000000000008152600260048201526000907366c121c0d400e57ef1ec453b72f7ecfa7c77e1dc9063072f9a5090602401602060405180830381865af4158015610597573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105bb9190610a69565b905090565b6000546001600160a01b031633146105d757600080fd5b600080546040516001600160a01b03909116914780156108fc02929091818181858888f19350505050158015610611573d6000803e3d6000fd5b50565b6040517f9daeae1e000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b038084166024830152821660448201526000907366c121c0d400e57ef1ec453b72f7ecfa7c77e1dc90639daeae1e90606401602060405180830381865af4158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190610a69565b9392505050565b6000546001600160a01b031633146106d957600080fd5b6040517fd9c7339e000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b0383166024820152604481018290527366c121c0d400e57ef1ec453b72f7ecfa7c77e1dc9063d9c7339e9060640161032d565b61061181610888565b6040517fb0aacf24000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b03821660248201526000907366c121c0d400e57ef1ec453b72f7ecfa7c77e1dc9063b0aacf2490604401602060405180830381865af41580156107c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e89190610a69565b92915050565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610856573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087a9190610a82565b61088357600080fd5b505050565b6000546001600160a01b0316331461089f57600080fd5b6001546040516001600160a01b038084169216907f8573d4aae9f7fb051c6b88d7440011a1c12376acda6603a45f45bad36a8db4ce90600090a36001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001600160a01b038116811461061157600080fd5b60006020828403121561092f57600080fd5b81356106bb81610908565b6000806040838503121561094d57600080fd5b823561095881610908565b946020939093013593505050565b60008060006060848603121561097b57600080fd5b833561098681610908565b9250602084013561099681610908565b929592945050506040919091013590565b600080600080606085870312156109bd57600080fd5b84356109c881610908565b935060208501359250604085013567ffffffffffffffff808211156109ec57600080fd5b818701915087601f830112610a0057600080fd5b813581811115610a0f57600080fd5b886020828501011115610a2157600080fd5b95989497505060200194505050565b60008060408385031215610a4357600080fd5b8235610a4e81610908565b91506020830135610a5e81610908565b809150509250929050565b600060208284031215610a7b57600080fd5b5051919050565b600060208284031215610a9457600080fd5b815180151581146106bb57600080fdfea2646970667358221220e51bdfea16490038892f8feb2068851f6ae531d935e40110b020c2e80aafd7c664736f6c634300080b0033000000000000000000000000455bc1d1528108b51bbbd7a9542ba6cc10e6a33c0000000000000000000000003fe4db892b4572a24b4431ef5742a88ef68ff5414555520000000000000000000000000000000000000000000000000000000000000000000000000000000000cb444e90d8198415266c6a2724b7900fb12fc56e
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103145760003560e01c806375b238fc116101a7578063a84c56d0116100ee578063e974fee911610097578063f27c5f6e11610071578063f27c5f6e146106e6578063f2fde38b146106f9578063fd2319c41461070c57600080fd5b8063e974fee9146106ad578063ebbc3d46146106c0578063ee0b5445146106d357600080fd5b8063dd62ed3e116100c8578063dd62ed3e14610674578063e174fd9414610687578063e30c39781461069a57600080fd5b8063a84c56d014610646578063b516af7014610659578063d547741f1461066157600080fd5b80638fb81d98116101505780639e7f43ca1161012a5780639e7f43ca1461062b5780639ea33e191461063e578063a217fddf146103e257600080fd5b80638fb81d98146105ce5780639137c1a7146105e157806391d14854146105f457600080fd5b8063802d441f11610181578063802d441f1461056a5780638ba47bdd1461057d5780638da5cb5b146105bb57600080fd5b806375b238fc1461051d578063774d54091461054457806379cc67901461055757600080fd5b8063326ecb051161026b5780634eb007541161021457806369569a51116101ee57806369569a51146104d057806370a08231146104e357806375071d2a146104f657600080fd5b80634eb00754146104975780634fe57e7a146104aa57806367a89a72146104bd57600080fd5b80633cd1570f116102455780633cd1570f146104535780634a36703b146104665780634e71e0c81461048f57600080fd5b8063326ecb051461041c5780633408f73a1461042f57806336568abe1461044057600080fd5b8063248a9ca3116102cd5780632ff2e9dc116102a75780632ff2e9dc146103e2578063313ce567146103ea578063322ec0fb1461040957600080fd5b8063248a9ca31461039957806325ec2eb0146103bc5780632f2ff15d146103cf57600080fd5b80631195e07e116102fe5780631195e07e146103665780631327d3d81461036e57806318160ddd1461038357600080fd5b80623074ff1461031957806301ffc9a714610343575b600080fd5b6004546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b61035661035136600461267e565b61071f565b604051901515815260200161033a565b6103266107b8565b61038161037c3660046126d5565b61084d565b005b61038b6108f2565b60405190815260200161033a565b61038b6103a73660046126f2565b60009081526020819052604090206001015490565b6103566103ca3660046126d5565b610979565b6103816103dd36600461270b565b6109b2565b61038b600081565b6006546103f79060ff1681565b60405160ff909116815260200161033a565b61035661041736600461273b565b6109dc565b61035661042a3660046126d5565b610c78565b6003546001600160a01b0316610326565b61038161044e36600461270b565b610cb8565b61038b610461366004612792565b610d44565b61038b6104743660046126d5565b6001600160a01b031660009081526007602052604090205490565b610381610ed1565b6103566104a5366004612809565b610f66565b6103816104b83660046126d5565b611137565b6103816104cb3660046126d5565b6111af565b6103816104de3660046126d5565b611227565b61038b6104f13660046126d5565b61129a565b61038b7f5719df9ef2c4678b547f89e4f5ae410dbf400fc51cf3ded434c55f6adea2c43f81565b61038b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b61035661055236600461273b565b611322565b61035661056536600461285b565b6113ef565b6103816105783660046126d5565b611592565b600a5461058a9060e81b81565b6040517fffffff0000000000000000000000000000000000000000000000000000000000909116815260200161033a565b600154610326906001600160a01b031681565b6103816105dc3660046128d0565b6115f2565b6103816105ef3660046126d5565b61167c565b61035661060236600461270b565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b610356610639366004612925565b6116ef565b60085461038b565b6103816106543660046126d5565b61180d565b610381611885565b61038161066f36600461270b565b611906565b61038b610682366004612998565b61192b565b61035661069536600461273b565b6119de565b600254610326906001600160a01b031681565b6103566106bb3660046129c6565b611aca565b6103816106ce3660046126d5565b611bc0565b6103816106e13660046126d5565b611c38565b6103816106f436600461285b565b611cc3565b6103816107073660046126d5565b611e38565b61038161071a3660046126f2565b611eab565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107b257507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6040517f6271970c0000000000000000000000000000000000000000000000000000000081526009600482015260009073ceb6728300915d56ac58fc99b4becc01a630ed8a90636271970c90602401602060405180830381865af4158015610824573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108489190612a17565b905090565b6001546001600160a01b0316331461086457600080fd5b6040517fad415349000000000000000000000000000000000000000000000000000000008152600960048201526001600160a01b038216602482015273ceb6728300915d56ac58fc99b4becc01a630ed8a9063ad4153499060440160006040518083038186803b1580156108d757600080fd5b505af41580156108eb573d6000803e3d6000fd5b5050505050565b600354604080517f6c9c2faf00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691636c9c2faf9160048083019260209291908290030181865afa158015610955573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108489190612a34565b6004546000906001600160a01b03838116911614806107b25750506001600160a01b031660009081526005602052604090205460ff1690565b6000828152602081905260409020600101546109cd81611efa565b6109d78383611f07565b505050565b60006109e733610979565b6109f057600080fd5b6001600160a01b03841660009081527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe60205260409020548490839060ff16610aa65760405162461bcd60e51b815260206004820152603260248201527f4d696e7461626c65436f6e74726f6c6c65723a2063616c6c6572206973206e6f60448201527f7420612073797374656d206163636f756e74000000000000000000000000000060648201526084015b60405180910390fd5b6001600160a01b038216600090815260076020526040902054811115610b36576040805162461bcd60e51b81526020600482015260248101919091527f4d696e7461626c65436f6e74726f6c6c65723a2063616c6c6572206973206e6f60448201527f7420616c6c6f77656420746f20706572666f726d207468697320616374696f6e6064820152608401610a9d565b610b3f85611fa5565b6001600160a01b038616600090815260076020526040902054610b63908590612a63565b6001600160a01b03878116600090815260076020526040908190209290925560035491517fb0c29c7400000000000000000000000000000000000000000000000000000000815291811660048301528616602482015260448101859052731007a6c78354f0c0033d1f96bb7b6b76402af3de9063b0c29c7490606401602060405180830381865af4158015610bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c209190612a7a565b610c6c5760405162461bcd60e51b815260206004820152601f60248201527f4d696e7461626c65436f6e74726f6c6c65723a206d696e74206661696c6564006044820152606401610a9d565b50600195945050505050565b6001600160a01b03811660009081527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe602052604081205460ff166107b2565b6001600160a01b0381163314610d365760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610a9d565b610d408282612166565b5050565b6000610d4f33610979565b610d5857600080fd5b6001600160a01b03881660009081527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe6020526040902054889060ff16610df45760405162461bcd60e51b815260206004820152602a60248201527f53797374656d526f6c653a2063616c6c6572206973206e6f7420612073797374604482015269195b481858d8dbdd5b9d60b21b6064820152608401610a9d565b610dfd87611fa5565b6003546040517f8f7227340000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152898216602482015290881660448201526064810187905260ff8616608482015260a4810185905260c4810184905273ceb6728300915d56ac58fc99b4becc01a630ed8a90638f7227349060e401602060405180830381865af4158015610ea0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ec49190612a34565b9998505050505050505050565b6002546001600160a01b03163314610ee857600080fd5b6002546001546040516001600160a01b0392831692909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600254600180546001600160a01b0319166001600160a01b039092169182179055610f54906000906121e5565b600280546001600160a01b0319169055565b6000610f7133610979565b610f7a57600080fd5b6001600160a01b03881660009081527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe6020526040902054889060ff166110165760405162461bcd60e51b815260206004820152602a60248201527f53797374656d526f6c653a2063616c6c6572206973206e6f7420612073797374604482015269195b481858d8dbdd5b9d60b21b6064820152608401610a9d565b6003546040517f799639d40000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529089166024820152604481018890526064810187905260ff8616608482015260a4810185905260c48101849052731007a6c78354f0c0033d1f96bb7b6b76402af3de9063799639d49060e401602060405180830381865af41580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dc9190612a7a565b6111285760405162461bcd60e51b815260206004820152601f60248201527f4d696e7461626c65436f6e74726f6c6c65723a206275726e206661696c6564006044820152606401610a9d565b50600198975050505050505050565b6001546001600160a01b0316331461114e57600080fd5b6111787fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775826109b2565b6040516001600160a01b038216907f5c7eb798b922f0164aa9c5340006161c64436190a49eebc58b4e6e0715700ae690600090a250565b6001546001600160a01b031633146111c657600080fd5b6111f07fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177582611906565b6040516001600160a01b038216907fc3198db98a2c50068f0a99b9297e60b2dbf0eafcde57e366e70a29f887c44e1090600090a250565b6001546001600160a01b0316331461123e57600080fd5b6004546040516001600160a01b038084169216907fcb01f884fc4203d4c1643cb0e126faeb397682c122ca8c0433776d42cdc0060a90600090a3600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546040517ff8b2cb4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063f8b2cb4f90602401602060405180830381865afa1580156112fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b29190612a34565b600061132d33610979565b61133657600080fd5b6003546040517f365feff10000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528582166024820152908416604482015260648101839052731d94e102e1c7a2cab9ba6d6d344d34d023628bd39063365feff1906084015b602060405180830381865af41580156113c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e79190612a7a565b949350505050565b60006113fa33610979565b61140357600080fd5b3360008181527f1feb9b335997de56b08b04054f0301e3df87667f2dfed59b0299f6d9a067ecbe602052604090205460ff166114945760405162461bcd60e51b815260206004820152602a60248201527f53797374656d526f6c653a2063616c6c6572206973206e6f7420612073797374604482015269195b481858d8dbdd5b9d60b21b6064820152608401610a9d565b6003546040517fa6c9ac280000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152908516602482015260448101849052731007a6c78354f0c0033d1f96bb7b6b76402af3de9063a6c9ac2890606401602060405180830381865af4158015611518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153c9190612a7a565b6115885760405162461bcd60e51b815260206004820152601f60248201527f4d696e7461626c65436f6e74726f6c6c65723a206275726e206661696c6564006044820152606401610a9d565b5060019392505050565b6001546001600160a01b031633146115a957600080fd5b6001600160a01b038116600081815260056020526040808220805460ff19169055517f10cf5a523a14a54e61c21610dc10c01e40e2ebc37baa3effd74032f7d3865e6d9190a250565b6001546001600160a01b0316331461160957600080fd5b6001600160a01b03831660009081526005602052604090819020805460ff191660011790555161163c9083908390612a9c565b604051908190038120906001600160a01b038516907fec75908259de4d038ff5f2b6b99e3725bc21871f4d2a44adeff9bb814afbc9f790600090a3505050565b6001546001600160a01b0316331461169357600080fd5b6003546040516001600160a01b038084169216907fdaaa9d417a3107fd3d9db02eba3eeafbae2b8af16ee08c534f5bc449054c1c4c90600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b6040516332c5a6eb60e01b8152600960048201526001600160a01b038087166024830152851660448201526064810184905260009073ceb6728300915d56ac58fc99b4becc01a630ed8a906332c5a6eb90608401602060405180830381865af4158015611760573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117849190612a7a565b6117f65760405162461bcd60e51b815260206004820152602160248201527f7472616e73666572416e6443616c6c2072657175657374206e6f742076616c6960448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610a9d565b61180386868686866121ef565b9695505050505050565b6001546001600160a01b0316331461182457600080fd5b61184e7f5719df9ef2c4678b547f89e4f5ae410dbf400fc51cf3ded434c55f6adea2c43f826109b2565b6040516001600160a01b038216907fdfb5b1167ef9eadf5cac67570f1a2971a6f6175303b9d4166a65a11d0a294e3490600090a250565b6001546001600160a01b0316331461189c57600080fd5b600360009054906101000a90046001600160a01b03166001600160a01b0316634e71e0c86040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156118ec57600080fd5b505af1158015611900573d6000803e3d6000fd5b50505050565b60008281526020819052604090206001015461192181611efa565b6109d78383612166565b6003546040517f1045d7ce0000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015283821660248201529082166044820152600090731d94e102e1c7a2cab9ba6d6d344d34d023628bd390631045d7ce90606401602060405180830381865af41580156119b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d79190612a34565b9392505050565b6040516332c5a6eb60e01b8152600960048201526001600160a01b038085166024830152831660448201526064810182905260009073ceb6728300915d56ac58fc99b4becc01a630ed8a906332c5a6eb90608401602060405180830381865af4158015611a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a739190612a7a565b611abf5760405162461bcd60e51b815260206004820152601a60248201527f7472616e736665722072657175657374206e6f742076616c69640000000000006044820152606401610a9d565b6113e78484846122b2565b6040516332c5a6eb60e01b8152600960048201526001600160a01b038085166024830152831660448201526064810182905260009073ceb6728300915d56ac58fc99b4becc01a630ed8a906332c5a6eb90608401602060405180830381865af4158015611b3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5f9190612a7a565b611bab5760405162461bcd60e51b815260206004820152601e60248201527f7472616e7366657246726f6d2072657175657374206e6f742076616c696400006044820152606401610a9d565b611bb785858585612343565b95945050505050565b6001546001600160a01b03163314611bd757600080fd5b611c017f5719df9ef2c4678b547f89e4f5ae410dbf400fc51cf3ded434c55f6adea2c43f82611906565b6040516001600160a01b038216907f21bfb3de07221bc6197a8c23f7a059308b7a741f259cf4ef3b519cde0fde7ac390600090a250565b6001546001600160a01b03163314611c4f57600080fd5b6003546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063f2fde38b90602401600060405180830381600087803b158015611caf57600080fd5b505af11580156108eb573d6000803e3d6000fd5b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff16611d675760405162461bcd60e51b815260206004820152602a60248201527f53797374656d526f6c653a2063616c6c6572206973206e6f7420616e2061646d60448201527f696e206163636f756e74000000000000000000000000000000000000000000006064820152608401610a9d565b600854811115611ddf5760405162461bcd60e51b815260206004820152603d60248201527f4d696e7461626c65436f6e74726f6c6c65723a20616c6c6f77616e636520657860448201527f6365656473206d6178696d756d20736574746564206279206f776e65720000006064820152608401610a9d565b6001600160a01b03821660008181526007602052604090819020839055517f8fe74a1bbab5a9534a04463cd7b9423b985ed316426821cace8ed4aeac5a4d1490611e2c9084815260200190565b60405180910390a25050565b6001546001600160a01b03163314611e4f57600080fd5b6002546040516001600160a01b038084169216907f8573d4aae9f7fb051c6b88d7440011a1c12376acda6603a45f45bad36a8db4ce90600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b03163314611ec257600080fd5b6040518181527f34affbf2a21d1f1d12e5e49bdca58fb75dba6879f5430f2fbf5c1d07476018d29060200160405180910390a1600855565b611f048133612418565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610d40576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611f613390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6001600160a01b038116611ffb5760405162461bcd60e51b815260206004820152601460248201527f6d757374206e6f742073656e6420746f203078300000000000000000000000006044820152606401610a9d565b6001600160a01b0381163014156120545760405162461bcd60e51b815260206004820152601b60248201527f6d757374206e6f742073656e6420746f20636f6e74726f6c6c657200000000006044820152606401610a9d565b6003546001600160a01b03828116911614156120b25760405162461bcd60e51b815260206004820152601e60248201527f6d757374206e6f742073656e6420746f20746f6b656e2073746f7261676500006044820152606401610a9d565b6004546001600160a01b03828116911614156121105760405162461bcd60e51b815260206004820152601960248201527f6d757374206e6f742073656e6420746f2066726f6e74656e64000000000000006044820152606401610a9d565b61211981610979565b15611f045760405162461bcd60e51b815260206004820181905260248201527f6d757374206e6f742073656e6420746f2062726964676546726f6e74656e64736044820152606401610a9d565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610d40576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b610d408282611f07565b60006121fa33610979565b61220357600080fd5b61220c85611fa5565b6003546040517f1eb8bccb00000000000000000000000000000000000000000000000000000000815273e74b37a54e8ae26d8c6c50830804f689888ef9a091631eb8bccb91612271916001600160a01b0316908a908a908a908a908a90600401612aac565b602060405180830381865af415801561228e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118039190612a7a565b60006122bd33610979565b6122c657600080fd5b6122cf83611fa5565b6003546040517f44ded8ba0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528582166024820152908416604482015260648101839052731d94e102e1c7a2cab9ba6d6d344d34d023628bd3906344ded8ba906084016113a6565b600061234e33610979565b61235757600080fd5b61236083611fa5565b6003546040517ff3a0ddf90000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015286821660248201528582166044820152908416606482015260848101839052731d94e102e1c7a2cab9ba6d6d344d34d023628bd39063f3a0ddf99060a401602060405180830381865af41580156123f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb79190612a7a565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610d40576124498161248b565b61245483602061249d565b604051602001612465929190612b35565b60408051601f198184030181529082905262461bcd60e51b8252610a9d91600401612bb6565b60606107b26001600160a01b03831660145b606060006124ac836002612be9565b6124b7906002612c08565b67ffffffffffffffff8111156124cf576124cf612c20565b6040519080825280601f01601f1916602001820160405280156124f9576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061253057612530612c36565b60200101906001600160f81b031916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061257b5761257b612c36565b60200101906001600160f81b031916908160001a905350600061259f846002612be9565b6125aa906001612c08565b90505b600181111561262f577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106125eb576125eb612c36565b1a60f81b82828151811061260157612601612c36565b60200101906001600160f81b031916908160001a90535060049490941c9361262881612c4c565b90506125ad565b5083156119d75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a9d565b60006020828403121561269057600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146119d757600080fd5b6001600160a01b0381168114611f0457600080fd5b6000602082840312156126e757600080fd5b81356119d7816126c0565b60006020828403121561270457600080fd5b5035919050565b6000806040838503121561271e57600080fd5b823591506020830135612730816126c0565b809150509250929050565b60008060006060848603121561275057600080fd5b833561275b816126c0565b9250602084013561276b816126c0565b929592945050506040919091013590565b803560ff8116811461278d57600080fd5b919050565b600080600080600080600060e0888a0312156127ad57600080fd5b87356127b8816126c0565b965060208801356127c8816126c0565b955060408801356127d8816126c0565b9450606088013593506127ed6080890161277c565b925060a0880135915060c0880135905092959891949750929550565b600080600080600080600060e0888a03121561282457600080fd5b873561282f816126c0565b9650602088013561283f816126c0565b955060408801359450606088013593506127ed6080890161277c565b6000806040838503121561286e57600080fd5b8235612879816126c0565b946020939093013593505050565b60008083601f84011261289957600080fd5b50813567ffffffffffffffff8111156128b157600080fd5b6020830191508360208285010111156128c957600080fd5b9250929050565b6000806000604084860312156128e557600080fd5b83356128f0816126c0565b9250602084013567ffffffffffffffff81111561290c57600080fd5b61291886828701612887565b9497909650939450505050565b60008060008060006080868803121561293d57600080fd5b8535612948816126c0565b94506020860135612958816126c0565b935060408601359250606086013567ffffffffffffffff81111561297b57600080fd5b61298788828901612887565b969995985093965092949392505050565b600080604083850312156129ab57600080fd5b82356129b6816126c0565b91506020830135612730816126c0565b600080600080608085870312156129dc57600080fd5b84356129e7816126c0565b935060208501356129f7816126c0565b92506040850135612a07816126c0565b9396929550929360600135925050565b600060208284031215612a2957600080fd5b81516119d7816126c0565b600060208284031215612a4657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612a7557612a75612a4d565b500390565b600060208284031215612a8c57600080fd5b815180151581146119d757600080fd5b8183823760009101908152919050565b60006001600160a01b038089168352808816602084015280871660408401525084606083015260a060808301528260a0830152828460c0840137600060c0848401015260c0601f19601f8501168301019050979650505050505050565b60005b83811015612b24578181015183820152602001612b0c565b838111156119005750506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612b6d816017850160208801612b09565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351612baa816028840160208801612b09565b01602801949350505050565b6020815260008251806020840152612bd5816040850160208701612b09565b601f01601f19169190910160400192915050565b6000816000190483118215151615612c0357612c03612a4d565b500290565b60008219821115612c1b57612c1b612a4d565b500190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081612c5b57612c5b612a4d565b50600019019056fea2646970667358221220440686b156ac6a64c9b87b2366b5617a8d4b3945365accdb6737e8a5ec19647664736f6c634300080b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000455bc1d1528108b51bbbd7a9542ba6cc10e6a33c0000000000000000000000003fe4db892b4572a24b4431ef5742a88ef68ff5414555520000000000000000000000000000000000000000000000000000000000000000000000000000000000cb444e90d8198415266c6a2724b7900fb12fc56e
-----Decoded View---------------
Arg [0] : storage_ (address): 0x455bC1d1528108b51bBbd7A9542Ba6cC10e6A33C
Arg [1] : validator (address): 0x3fe4dB892b4572A24B4431ef5742A88EF68FF541
Arg [2] : ticker_ (bytes3): 0x455552
Arg [3] : frontend_ (address): 0xcB444e90D8198415266c6a2724b7900fb12FC56E
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000455bc1d1528108b51bbbd7a9542ba6cc10e6a33c
Arg [1] : 0000000000000000000000003fe4db892b4572a24b4431ef5742a88ef68ff541
Arg [2] : 4555520000000000000000000000000000000000000000000000000000000000
Arg [3] : 000000000000000000000000cb444e90d8198415266c6a2724b7900fb12fc56e
Library Used
TokenStorageLib : 0x66c121c0d400e57ef1ec453b72f7ecfa7c77e1dcERC20Lib : 0x1d94e102e1c7a2cab9ba6d6d344d34d023628bd3ERC677Lib : 0xe74b37a54e8ae26d8c6c50830804f689888ef9a0MintableTokenLib : 0x1007a6c78354f0c0033d1f96bb7b6b76402af3deSmartTokenLib : 0xceb6728300915d56ac58fc99b4becc01a630ed8a
Deployed Bytecode Sourcemap
891:5009:27:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3921:87:29;3993:8;;-1:-1:-1;;;;;3993:8:29;3921:87;;;-1:-1:-1;;;;;178:55:34;;;160:74;;148:2;133:18;3921:87:29;;;;;;;;2571:202:0;;;;;;:::i;:::-;;:::i;:::-;;;747:14:34;;740:22;722:41;;710:2;695:18;2571:202:0;582:187:34;5793:105:27;;;:::i;1880:111::-;;;;;;:::i;:::-;;:::i;:::-;;8693:93:29;;;:::i;:::-;;;1331:25:34;;;1319:2;1304:18;8693:93:29;1185:177:34;4343:129:0;;;;;;:::i;:::-;4417:7;4443:12;;;;;;;;;;:22;;;;4343:129;5257:143:29;;;;;;:::i;:::-;;:::i;4768:145:0:-;;;;;;:::i;:::-;;:::i;1080:42:27:-;;1121:1;1080:42;;1310:26:29;;;;;;;;;;;;2226:4:34;2214:17;;;2196:36;;2184:2;2169:18;1310:26:29;2054:184:34;2701:413:21;;;;;;:::i;:::-;;:::i;3217:122:31:-;;;;;;:::i;:::-;;:::i;4110:92:29:-;4189:5;;-1:-1:-1;;;;;4189:5:29;4110:92;;5877:214:0;;;;;;:::i;:::-;;:::i;2748:341:27:-;;;;;;:::i;:::-;;:::i;5576:142:21:-;;;;;;:::i;:::-;-1:-1:-1;;;;;5688:23:21;5662:7;5688:23;;;:14;:23;;;;;;;5576:142;1313:225:4;;;:::i;3562:392:21:-;;;;;;:::i;:::-;;:::i;3975:155:31:-;;;;;;:::i;:::-;;:::i;4236:161::-;;;;;;:::i;:::-;;:::i;4310:138:29:-;;;;;;:::i;:::-;;:::i;8946:106::-;;;;;;:::i;:::-;;:::i;1133:62:31:-;;1171:24;1133:62;;1067:60;;1104:23;1067:60;;7665:207:29;;;;;;:::i;:::-;;:::i;4169:241:21:-;;;;;;:::i;:::-;;:::i;4960:164:29:-;;;;;;:::i;:::-;;:::i;1054:20:27:-;;;;;;;;;;;;4910:66:34;4898:79;;;4880:98;;4868:2;4853:18;1054:20:27;4736:248:34;270:20:24;;;;;-1:-1:-1;;;;;270:20:24;;;4628:205:29;;;;;;:::i;:::-;;:::i;5505:152::-;;;;;;:::i;:::-;;:::i;2860:145:0:-;;;;;;:::i;:::-;2946:4;2969:12;;;;;;;;;;;-1:-1:-1;;;;;2969:29:0;;;;;;;;;;;;;;;2860:145;5313:381:27;;;;;;:::i;:::-;;:::i;4801:109:21:-;4887:16;;4801:109;;3443:158:31;;;;;;:::i;:::-;;:::i;5978:89:29:-;;;:::i;5193:147:0:-;;;;;;:::i;:::-;;:::i;9297:157:29:-;;;;;;:::i;:::-;;:::i;3500:325:27:-;;;;;;:::i;:::-;;:::i;322:27:4:-;;;;;-1:-1:-1;;;;;322:27:4;;;4383:363:27;;;;;;:::i;:::-;;:::i;3708:164:31:-;;;;;;:::i;:::-;;:::i;5788:119:29:-;;;;;;:::i;:::-;;:::i;5070:352:21:-;;;;;;:::i;:::-;;:::i;1025:196:4:-;;;;;;:::i;:::-;;:::i;4533:151:21:-;;;;;;:::i;:::-;;:::i;2571:202:0:-;2656:4;2679:47;;;2694:32;2679:47;;:87;;-1:-1:-1;952:25:7;937:40;;;;2730:36:0;2672:94;2571:202;-1:-1:-1;;2571:202:0:o;5793:105:27:-;5866:25;;;;;:10;:25;;;1331::34;5840:7:27;;5866:23;;;;1304:18:34;;5866:25:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5859:32;;5793:105;:::o;1880:111::-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;1950:34:27::1;::::0;;;;:10:::1;:34;::::0;::::1;8524:25:34::0;-1:-1:-1;;;;;8585:55:34;;8565:18;;;8558:83;1950:23:27::1;::::0;::::1;::::0;8497:18:34;;1950:34:27::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;1880:111:::0;:::o;8693:93:29:-;8762:5;;:17;;;;;;;;8739:4;;-1:-1:-1;;;;;8762:5:29;;:15;;:17;;;;;;;;;;;;;;:5;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;5257:143::-;5354:8;;5317:4;;-1:-1:-1;;;;;5341:21:29;;;5354:8;;5341:21;;5340:53;;-1:-1:-1;;;;;;;5367:26:29;;;;;:15;:26;;;;;;;;;5257:143::o;4768:145:0:-;4417:7;4443:12;;;;;;;;;;:22;;;2470:16;2481:4;2470:10;:16::i;:::-;4881:25:::1;4892:4;4898:7;4881:10;:25::i;:::-;4768:145:::0;;;:::o;2701:413:21:-;2904:4;2456:22:29;2467:10;2456;:22::i;:::-;2448:31;;;;;;-1:-1:-1;;;;;2969:29:0;;2946:4;2969:29;;;:12;;:29;:12;:29;;;2871:6:21;;2879;;2969:29:0;;2185:126:21::1;;;::::0;-1:-1:-1;;;2185:126:21;;9043:2:34;2185:126:21::1;::::0;::::1;9025:21:34::0;9082:2;9062:18;;;9055:30;9121:34;9101:18;;;9094:62;9192:20;9172:18;;;9165:48;9230:19;;2185:126:21::1;;;;;;;;;-1:-1:-1::0;;;;;2342:23:21;::::1;;::::0;;;:14:::1;:23;::::0;;;;;:33;-1:-1:-1;2342:33:21::1;2321:144;;;::::0;;-1:-1:-1;;;2321:144:21;;9462:2:34;2321:144:21::1;::::0;::::1;9444:21:34::0;9481:18;;;9474:30;;;;9540:34;9520:18;;;9513:62;9611:34;9591:18;;;9584:62;9663:19;;2321:144:21::1;9260:428:34::0;2321:144:21::1;2924:20:::2;2941:2;2924:16;:20::i;:::-;-1:-1:-1::0;;;;;2979:22:21;::::2;;::::0;;;:14:::2;:22;::::0;;;;;:31:::2;::::0;3004:6;;2979:31:::2;:::i;:::-;-1:-1:-1::0;;;;;2954:22:21;;::::2;;::::0;;;:14:::2;:22;::::0;;;;;;:56;;;;3028:5:::2;::::0;:22;;;;;:5;;::::2;:22;::::0;::::2;10304:34:34::0;10374:15;;10354:18;;;10347:43;10406:18;;;10399:34;;;3028:10:21::2;::::0;::::2;::::0;10216:18:34;;3028:22:21::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3020:66;;;::::0;-1:-1:-1;;;3020:66:21;;10928:2:34;3020:66:21::2;::::0;::::2;10910:21:34::0;10967:2;10947:18;;;10940:30;11006:33;10986:18;;;10979:61;11057:18;;3020:66:21::2;10726:355:34::0;3020:66:21::2;-1:-1:-1::0;3103:4:21::2;::::0;2701:413;-1:-1:-1;;;;;2701:413:21:o;3217:122:31:-;-1:-1:-1;;;;;2969:29:0;;3280:4:31;2969:29:0;;;:12;;:29;:12;:29;;;;;3303::31;2860:145:0;5877:214;-1:-1:-1;;;;;5972:23:0;;719:10:5;5972:23:0;5964:83;;;;-1:-1:-1;;;5964:83:0;;11288:2:34;5964:83:0;;;11270:21:34;11327:2;11307:18;;;11300:30;11366:34;11346:18;;;11339:62;11437:17;11417:18;;;11410:45;11472:19;;5964:83:0;11086:411:34;5964:83:0;6058:26;6070:4;6076:7;6058:11;:26::i;:::-;5877:214;;:::o;2748:341:27:-;2979:4;2456:22:29;2467:10;2456;:22::i;:::-;2448:31;;;;;;-1:-1:-1;;;;;2969:29:0;;2946:4;2969:29;;;:12;;:29;:12;:29;;;2962:6:27;;2969:29:0;;2335:118:31::1;;;::::0;-1:-1:-1;;;2335:118:31;;11704:2:34;2335:118:31::1;::::0;::::1;11686:21:34::0;11743:2;11723:18;;;11716:30;11782:34;11762:18;;;11755:62;-1:-1:-1;;;11833:18:34;;;11826:40;11883:19;;2335:118:31::1;11502:406:34::0;2335:118:31::1;2995:20:27::2;3012:2;2995:16;:20::i;:::-;3054:5;::::0;3032:50:::2;::::0;;;;-1:-1:-1;;;;;3054:5:27;;::::2;3032:50;::::0;::::2;12314:34:34::0;12384:15;;;12364:18;;;12357:43;12436:15;;;12416:18;;;12409:43;12468:18;;;12461:34;;;12544:4;12532:17;;12511:19;;;12504:46;12566:19;;;12559:35;;;12610:19;;;12603:35;;;3032:13:27::2;::::0;:21:::2;::::0;12225:19:34;;3032:50:27::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3025:57:::0;2748:341;-1:-1:-1;;;;;;;;;2748:341:27:o;1313:225:4:-;841:12;;-1:-1:-1;;;;;841:12:4;827:10;:26;819:35;;;;;;1406:12:::1;::::0;;1399:5;1378:41:::1;::::0;-1:-1:-1;;;;;1406:12:4;;::::1;::::0;1399:5;;::::1;::::0;1378:41:::1;::::0;1406:12:::1;::::0;1378:41:::1;1437:12;::::0;;1429:20;;-1:-1:-1;;;;;;1429:20:4::1;-1:-1:-1::0;;;;;1437:12:4;;::::1;1429:20:::0;;::::1;::::0;;1459:37:::1;::::0;1437:12:::1;::::0;1459:10:::1;:37::i;:::-;1506:12;:25:::0;;-1:-1:-1;;;;;;1506:25:4::1;::::0;;1313:225::o;3562:392:21:-;3796:4;2456:22:29;2467:10;2456;:22::i;:::-;2448:31;;;;;;-1:-1:-1;;;;;2969:29:0;;2946:4;2969:29;;;:12;;:29;:12;:29;;;3779:6:21;;2969:29:0;;2335:118:31::1;;;::::0;-1:-1:-1;;;2335:118:31;;11704:2:34;2335:118:31::1;::::0;::::1;11686:21:34::0;11743:2;11723:18;;;11716:30;11782:34;11762:18;;;11755:62;-1:-1:-1;;;11833:18:34;;;11826:40;11883:19;;2335:118:31::1;11502:406:34::0;2335:118:31::1;3833:5:21::2;::::0;:36:::2;::::0;;;;-1:-1:-1;;;;;3833:5:21;;::::2;:36;::::0;::::2;13050:34:34::0;13120:15;;;13100:18;;;13093:43;13152:18;;;13145:34;;;13195:18;;;13188:34;;;13271:4;13259:17;;13238:19;;;13231:46;13293:19;;;13286:35;;;13337:19;;;13330:35;;;3833:10:21::2;::::0;::::2;::::0;12961:19:34;;3833:36:21::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3812:114;;;::::0;-1:-1:-1;;;3812:114:21;;13578:2:34;3812:114:21::2;::::0;::::2;13560:21:34::0;13617:2;13597:18;;;13590:30;13656:33;13636:18;;;13629:61;13707:18;;3812:114:21::2;13376:355:34::0;3812:114:21::2;-1:-1:-1::0;3943:4:21::2;::::0;3562:392;-1:-1:-1;;;;;;;;3562:392:21:o;3975:155:31:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;4052:30:31::1;1104:23;4074:7;4052:9;:30::i;:::-;4097:26;::::0;-1:-1:-1;;;;;4097:26:31;::::1;::::0;::::1;::::0;;;::::1;3975:155:::0;:::o;4236:161::-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;4316:31:31::1;1104:23;4339:7;4316:10;:31::i;:::-;4362:28;::::0;-1:-1:-1;;;;;4362:28:31;::::1;::::0;::::1;::::0;;;::::1;4236:161:::0;:::o;4310:138:29:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;4391:8:29::1;::::0;4382:29:::1;::::0;-1:-1:-1;;;;;4382:29:29;;::::1;::::0;4391:8:::1;::::0;4382:29:::1;::::0;4391:8:::1;::::0;4382:29:::1;4421:8;:20:::0;;-1:-1:-1;;;;;;4421:20:29::1;-1:-1:-1::0;;;;;4421:20:29;;;::::1;::::0;;;::::1;::::0;;4310:138::o;8946:106::-;9024:5;;:21;;;;;-1:-1:-1;;;;;178:55:34;;;9024:21:29;;;160:74:34;9001:4:29;;9024:5;;:16;;133:18:34;;9024:21:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;7665:207::-;7801:7;2456:22;2467:10;2456;:22::i;:::-;2448:31;;;;;;7827:5:::1;::::0;:38:::1;::::0;;;;-1:-1:-1;;;;;7827:5:29;;::::1;:38;::::0;::::1;14057:34:34::0;14127:15;;;14107:18;;;14100:43;14179:15;;;14159:18;;;14152:43;14211:18;;;14204:34;;;7827:13:29::1;::::0;::::1;::::0;13968:19:34;;7827:38:29::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7820:45:::0;7665:207;-1:-1:-1;;;;7665:207:29:o;4169:241:21:-;4298:4;2456:22:29;2467:10;2456;:22::i;:::-;2448:31;;;;;;4277:10:21::1;2946:4:0::0;2969:29;;;:12;;:29;:12;:29;;;;;2335:118:31::1;;;::::0;-1:-1:-1;;;2335:118:31;;11704:2:34;2335:118:31::1;::::0;::::1;11686:21:34::0;11743:2;11723:18;;;11716:30;11782:34;11762:18;;;11755:62;-1:-1:-1;;;11833:18:34;;;11826:40;11883:19;;2335:118:31::1;11502:406:34::0;2335:118:31::1;4322:5:21::2;::::0;:24:::2;::::0;;;;-1:-1:-1;;;;;4322:5:21;;::::2;:24;::::0;::::2;10304:34:34::0;10374:15;;;10354:18;;;10347:43;10406:18;;;10399:34;;;4322:10:21::2;::::0;::::2;::::0;10216:18:34;;4322:24:21::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4314:68;;;::::0;-1:-1:-1;;;4314:68:21;;13578:2:34;4314:68:21::2;::::0;::::2;13560:21:34::0;13617:2;13597:18;;;13590:30;13656:33;13636:18;;;13629:61;13707:18;;4314:68:21::2;13376:355:34::0;4314:68:21::2;-1:-1:-1::0;4399:4:21::2;::::0;4169:241;-1:-1:-1;;;4169:241:21:o;4960:164:29:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;-1:-1:-1;;;;;5036:26:29;::::1;5065:5;5036:26:::0;;;:15:::1;:26;::::0;;;;;:34;;-1:-1:-1;;5036:34:29::1;::::0;;5085:32;::::1;::::0;5065:5;5085:32:::1;4960:164:::0;:::o;4628:205::-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;-1:-1:-1;;;;;4746:26:29;::::1;;::::0;;;:15:::1;:26;::::0;;;;;;:33;;-1:-1:-1;;4746:33:29::1;4775:4;4746:33;::::0;;4794:32;::::1;::::0;4820:5;;;;4794:32:::1;:::i;:::-;;::::0;;;;::::1;::::0;;;-1:-1:-1;;;;;4794:32:29;::::1;::::0;::::1;::::0;;;::::1;4628:205:::0;;;:::o;5505:152::-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;5593:5:29::1;::::0;5577:33:::1;::::0;-1:-1:-1;;;;;5577:33:29;;::::1;::::0;5593:5:::1;::::0;5577:33:::1;::::0;5593:5:::1;::::0;5577:33:::1;5620:5;:30:::0;;-1:-1:-1;;;;;;5620:30:29::1;-1:-1:-1::0;;;;;5620:30:29;;;::::1;::::0;;;::::1;::::0;;5505:152::o;5313:381:27:-;5514:39;;-1:-1:-1;;;5514:39:27;;:10;:39;;;14797:25:34;-1:-1:-1;;;;;14919:15:34;;;14899:18;;;14892:43;14971:15;;14951:18;;;14944:43;15003:18;;;14996:34;;;5477:4:27;;5514:19;;;;14769::34;;5514:39:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5493:119;;;;-1:-1:-1;;;5493:119:27;;15243:2:34;5493:119:27;;;15225:21:34;15282:2;15262:18;;;15255:30;15321:34;15301:18;;;15294:62;15392:3;15372:18;;;15365:31;15413:19;;5493:119:27;15041:397:34;5493:119:27;5629:58;5662:6;5670:2;5674:6;5682:4;;5629:32;:58::i;:::-;5622:65;5313:381;-1:-1:-1;;;;;;5313:381:27:o;3443:158:31:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;3521:31:31::1;1171:24;3544:7;3521:9;:31::i;:::-;3567:27;::::0;-1:-1:-1;;;;;3567:27:31;::::1;::::0;::::1;::::0;;;::::1;3443:158:::0;:::o;5978:89:29:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;6038:5:29::1;;;;;;;;;-1:-1:-1::0;;;;;6038:5:29::1;-1:-1:-1::0;;;;;6038:20:29::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;5978:89::o:0;5193:147:0:-;4417:7;4443:12;;;;;;;;;;:22;;;2470:16;2481:4;2470:10;:16::i;:::-;5307:26:::1;5319:4;5325:7;5307:11;:26::i;9297:157:29:-:0;9416:5;;:31;;;;;-1:-1:-1;;;;;9416:5:29;;;:31;;;15735:34:34;15805:15;;;15785:18;;;15778:43;15857:15;;;15837:18;;;15830:43;9393:4:29;;9416:15;;;;15647:18:34;;9416:31:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9409:38;9297:157;-1:-1:-1;;;9297:157:29:o;3500:325:27:-;3665:39;;-1:-1:-1;;;3665:39:27;;:10;:39;;;14797:25:34;-1:-1:-1;;;;;14919:15:34;;;14899:18;;;14892:43;14971:15;;14951:18;;;14944:43;15003:18;;;14996:34;;;3628:4:27;;3665:19;;;;14769::34;;3665:39:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3644:112;;;;-1:-1:-1;;;3644:112:27;;16086:2:34;3644:112:27;;;16068:21:34;16125:2;16105:18;;;16098:30;16164:28;16144:18;;;16137:56;16210:18;;3644:112:27;15884:350:34;3644:112:27;3773:45;3799:6;3807:2;3811:6;3773:25;:45::i;4383:363::-;4574:37;;-1:-1:-1;;;4574:37:27;;:10;:37;;;14797:25:34;-1:-1:-1;;;;;14919:15:34;;;14899:18;;;14892:43;14971:15;;14951:18;;;14944:43;15003:18;;;14996:34;;;4537:4:27;;4574:19;;;;14769::34;;4574:37:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4553:114;;;;-1:-1:-1;;;4553:114:27;;16441:2:34;4553:114:27;;;16423:21:34;16480:2;16460:18;;;16453:30;16519:32;16499:18;;;16492:60;16569:18;;4553:114:27;16239:354:34;4553:114:27;4684:55;4714:6;4722:4;4728:2;4732:6;4684:29;:55::i;:::-;4677:62;4383:363;-1:-1:-1;;;;;4383:363:27:o;3708:164:31:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;3789:32:31::1;1171:24;3813:7;3789:10;:32::i;:::-;3836:29;::::0;-1:-1:-1;;;;;3836:29:31;::::1;::::0;::::1;::::0;;;::::1;3708:164:::0;:::o;5788:119:29:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;5867:5:29::1;::::0;:33:::1;::::0;;;;-1:-1:-1;;;;;178:55:34;;;5867:33:29::1;::::0;::::1;160:74:34::0;5867:5:29;;::::1;::::0;:23:::1;::::0;133:18:34;;5867:33:29::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;5070:352:21::0;2632:10:31;2946:4:0;2969:29;;;:12;;:29;:12;:29;;;;;2591:120:31;;;;-1:-1:-1;;;2591:120:31;;16800:2:34;2591:120:31;;;16782:21:34;16839:2;16819:18;;;16812:30;16878:34;16858:18;;;16851:62;16949:12;16929:18;;;16922:40;16979:19;;2591:120:31;16598:406:34;2591:120:31;5225:16:21::1;;5215:6;:26;;5194:134;;;::::0;-1:-1:-1;;;5194:134:21;;17211:2:34;5194:134:21::1;::::0;::::1;17193:21:34::0;17250:2;17230:18;;;17223:30;17289:34;17269:18;;;17262:62;17360:31;17340:18;;;17333:59;17409:19;;5194:134:21::1;17009:425:34::0;5194:134:21::1;-1:-1:-1::0;;;;;5338:23:21;::::1;;::::0;;;:14:::1;:23;::::0;;;;;;:32;;;5385:30;::::1;::::0;::::1;::::0;5364:6;1331:25:34;;1319:2;1304:18;;1185:177;5385:30:21::1;;;;;;;;5070:352:::0;;:::o;1025:196:4:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;1158:12:4::1;::::0;1133:48:::1;::::0;-1:-1:-1;;;;;1133:48:4;;::::1;::::0;1158:12:::1;::::0;1133:48:::1;::::0;1158:12:::1;::::0;1133:48:::1;1191:12;:23:::0;;-1:-1:-1;;;;;;1191:23:4::1;-1:-1:-1::0;;;;;1191:23:4;;;::::1;::::0;;;::::1;::::0;;1025:196::o;4533:151:21:-;784:5:24;;-1:-1:-1;;;;;784:5:24;770:10;:19;762:28;;;;;;4618:24:21::1;::::0;1331:25:34;;;4618:24:21::1;::::0;1319:2:34;1304:18;4618:24:21::1;;;;;;;4652:16;:25:::0;4533:151::o;3299:103:0:-;3365:30;3376:4;719:10:5;3365::0;:30::i;:::-;3299:103;:::o;7426:233::-;2946:4;2969:12;;;;;;;;;;;-1:-1:-1;;;;;2969:29:0;;;;;;;;;;;;7504:149;;7547:6;:12;;;;;;;;;;;-1:-1:-1;;;;;7547:29:0;;;;;;;;;:36;;-1:-1:-1;;7547:36:0;7579:4;7547:36;;;7629:12;719:10:5;;640:96;7629:12:0;-1:-1:-1;;;;;7602:40:0;7620:7;-1:-1:-1;;;;;7602:40:0;7614:4;7602:40;;;;;;;;;;7426:233;;:::o;3415:402:29:-;-1:-1:-1;;;;;3485:18:29;;3477:51;;;;-1:-1:-1;;;3477:51:29;;17641:2:34;3477:51:29;;;17623:21:34;17680:2;17660:18;;;17653:30;17719:22;17699:18;;;17692:50;17759:18;;3477:51:29;17439:344:34;3477:51:29;-1:-1:-1;;;;;3546:19:29;;3560:4;3546:19;;3538:59;;;;-1:-1:-1;;;3538:59:29;;17990:2:34;3538:59:29;;;17972:21:34;18029:2;18009:18;;;18002:30;18068:29;18048:18;;;18041:57;18115:18;;3538:59:29;17788:351:34;3538:59:29;3629:5;;-1:-1:-1;;;;;3615:20:29;;;3629:5;;3615:20;;3607:63;;;;-1:-1:-1;;;3607:63:29;;18346:2:34;3607:63:29;;;18328:21:34;18385:2;18365:18;;;18358:30;18424:32;18404:18;;;18397:60;18474:18;;3607:63:29;18144:354:34;3607:63:29;3694:8;;-1:-1:-1;;;;;3688:14:29;;;3694:8;;3688:14;;3680:52;;;;-1:-1:-1;;;3680:52:29;;18705:2:34;3680:52:29;;;18687:21:34;18744:2;18724:18;;;18717:30;18783:27;18763:18;;;18756:55;18828:18;;3680:52:29;18503:349:34;3680:52:29;3750:14;3761:2;3750:10;:14::i;:::-;:23;3742:68;;;;-1:-1:-1;;;3742:68:29;;19059:2:34;3742:68:29;;;19041:21:34;;;19078:18;;;19071:30;19137:34;19117:18;;;19110:62;19189:18;;3742:68:29;18857:356:34;7830:234:0;2946:4;2969:12;;;;;;;;;;;-1:-1:-1;;;;;2969:29:0;;;;;;;;;;;;7909:149;;;7983:5;7951:12;;;;;;;;;;;-1:-1:-1;;;;;7951:29:0;;;;;;;;;;:37;;-1:-1:-1;;7951:37:0;;;8007:40;719:10:5;;7951:12:0;;8007:40;;7983:5;8007:40;7830:234;;:::o;6776:110::-;6854:25;6865:4;6871:7;6854:10;:25::i;8314:286:29:-;8490:7;2456:22;2467:10;2456;:22::i;:::-;2448:31;;;;;;8509:20:::1;8526:2;8509:16;:20::i;:::-;8546:5;::::0;:47:::1;::::0;;;;:21:::1;::::0;::::1;::::0;:47:::1;::::0;-1:-1:-1;;;;;8546:5:29::1;::::0;8568:6;;8576:2;;8580:6;;8588:4;;;;8546:47:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;6286:237::-:0;6426:7;2456:22;2467:10;2456;:22::i;:::-;2448:31;;;;;;6445:20:::1;6462:2;6445:16;:20::i;:::-;6482:5;::::0;:34:::1;::::0;;;;-1:-1:-1;;;;;6482:5:29;;::::1;:34;::::0;::::1;14057::34::0;14127:15;;;14107:18;;;14100:43;14179:15;;;14159:18;;;14152:43;14211:18;;;14204:34;;;6482:14:29::1;::::0;::::1;::::0;13968:19:34;;6482:34:29::1;13736:508:34::0;6883:273:29;7049:7;2456:22;2467:10;2456;:22::i;:::-;2448:31;;;;;;7068:20:::1;7085:2;7068:16;:20::i;:::-;7105:5;::::0;:44:::1;::::0;;;;-1:-1:-1;;;;;7105:5:29;;::::1;:44;::::0;::::1;20367:34:34::0;20437:15;;;20417:18;;;20410:43;20489:15;;;20469:18;;;20462:43;20541:15;;;20521:18;;;20514:43;20573:19;;;20566:35;;;7105:18:29::1;::::0;::::1;::::0;20278:19:34;;7105:44:29::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;3683:479:0:-:0;2946:4;2969:12;;;;;;;;;;;-1:-1:-1;;;;;2969:29:0;;;;;;;;;;;;3766:390;;3954:28;3974:7;3954:19;:28::i;:::-;4053:38;4081:4;4088:2;4053:19;:38::i;:::-;3861:252;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;3861:252:0;;;;;;;;;;-1:-1:-1;;;3809:336:0;;;;;;;:::i;2097:149:30:-;2155:13;2187:52;-1:-1:-1;;;;;2199:22:30;;306:2;1508:437;1583:13;1608:19;1640:10;1644:6;1640:1;:10;:::i;:::-;:14;;1653:1;1640:14;:::i;:::-;1630:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1630:25:30;;1608:47;;1665:15;:6;1672:1;1665:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1665:15:30;;;;;;;;;1690;:6;1697:1;1690:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1690:15:30;;;;;;;;-1:-1:-1;1720:9:30;1732:10;1736:6;1732:1;:10;:::i;:::-;:14;;1745:1;1732:14;:::i;:::-;1720:26;;1715:128;1752:1;1748;:5;1715:128;;;1786:8;1795:5;1803:3;1795:11;1786:21;;;;;;;:::i;:::-;;;;1774:6;1781:1;1774:9;;;;;;;;:::i;:::-;;;;:33;-1:-1:-1;;;;;1774:33:30;;;;;;;;-1:-1:-1;1831:1:30;1821:11;;;;;1755:3;;;:::i;:::-;;;1715:128;;;-1:-1:-1;1860:10:30;;1852:55;;;;-1:-1:-1;;;1852:55:30;;23081:2:34;1852:55:30;;;23063:21:34;;;23100:18;;;23093:30;23159:34;23139:18;;;23132:62;23211:18;;1852:55:30;22879:356:34;245:332;303:6;356:2;344:9;335:7;331:23;327:32;324:52;;;372:1;369;362:12;324:52;411:9;398:23;461:66;454:5;450:78;443:5;440:89;430:117;;543:1;540;533:12;774:154;-1:-1:-1;;;;;853:5:34;849:54;842:5;839:65;829:93;;918:1;915;908:12;933:247;992:6;1045:2;1033:9;1024:7;1020:23;1016:32;1013:52;;;1061:1;1058;1051:12;1013:52;1100:9;1087:23;1119:31;1144:5;1119:31;:::i;1367:180::-;1426:6;1479:2;1467:9;1458:7;1454:23;1450:32;1447:52;;;1495:1;1492;1485:12;1447:52;-1:-1:-1;1518:23:34;;1367:180;-1:-1:-1;1367:180:34:o;1734:315::-;1802:6;1810;1863:2;1851:9;1842:7;1838:23;1834:32;1831:52;;;1879:1;1876;1869:12;1831:52;1915:9;1902:23;1892:33;;1975:2;1964:9;1960:18;1947:32;1988:31;2013:5;1988:31;:::i;:::-;2038:5;2028:15;;;1734:315;;;;;:::o;2243:456::-;2320:6;2328;2336;2389:2;2377:9;2368:7;2364:23;2360:32;2357:52;;;2405:1;2402;2395:12;2357:52;2444:9;2431:23;2463:31;2488:5;2463:31;:::i;:::-;2513:5;-1:-1:-1;2570:2:34;2555:18;;2542:32;2583:33;2542:32;2583:33;:::i;:::-;2243:456;;2635:7;;-1:-1:-1;;;2689:2:34;2674:18;;;;2661:32;;2243:456::o;2704:156::-;2770:20;;2830:4;2819:16;;2809:27;;2799:55;;2850:1;2847;2840:12;2799:55;2704:156;;;:::o;2865:807::-;2976:6;2984;2992;3000;3008;3016;3024;3077:3;3065:9;3056:7;3052:23;3048:33;3045:53;;;3094:1;3091;3084:12;3045:53;3133:9;3120:23;3152:31;3177:5;3152:31;:::i;:::-;3202:5;-1:-1:-1;3259:2:34;3244:18;;3231:32;3272:33;3231:32;3272:33;:::i;:::-;3324:7;-1:-1:-1;3383:2:34;3368:18;;3355:32;3396:33;3355:32;3396:33;:::i;:::-;3448:7;-1:-1:-1;3502:2:34;3487:18;;3474:32;;-1:-1:-1;3525:37:34;3557:3;3542:19;;3525:37;:::i;:::-;3515:47;;3609:3;3598:9;3594:19;3581:33;3571:43;;3661:3;3650:9;3646:19;3633:33;3623:43;;2865:807;;;;;;;;;;:::o;3677:734::-;3788:6;3796;3804;3812;3820;3828;3836;3889:3;3877:9;3868:7;3864:23;3860:33;3857:53;;;3906:1;3903;3896:12;3857:53;3945:9;3932:23;3964:31;3989:5;3964:31;:::i;:::-;4014:5;-1:-1:-1;4071:2:34;4056:18;;4043:32;4084:33;4043:32;4084:33;:::i;:::-;4136:7;-1:-1:-1;4190:2:34;4175:18;;4162:32;;-1:-1:-1;4241:2:34;4226:18;;4213:32;;-1:-1:-1;4264:37:34;4296:3;4281:19;;4264:37;:::i;4416:315::-;4484:6;4492;4545:2;4533:9;4524:7;4520:23;4516:32;4513:52;;;4561:1;4558;4551:12;4513:52;4600:9;4587:23;4619:31;4644:5;4619:31;:::i;:::-;4669:5;4721:2;4706:18;;;;4693:32;;-1:-1:-1;;;4416:315:34:o;4989:348::-;5041:8;5051:6;5105:3;5098:4;5090:6;5086:17;5082:27;5072:55;;5123:1;5120;5113:12;5072:55;-1:-1:-1;5146:20:34;;5189:18;5178:30;;5175:50;;;5221:1;5218;5211:12;5175:50;5258:4;5250:6;5246:17;5234:29;;5310:3;5303:4;5294:6;5286;5282:19;5278:30;5275:39;5272:59;;;5327:1;5324;5317:12;5272:59;4989:348;;;;;:::o;5342:546::-;5422:6;5430;5438;5491:2;5479:9;5470:7;5466:23;5462:32;5459:52;;;5507:1;5504;5497:12;5459:52;5546:9;5533:23;5565:31;5590:5;5565:31;:::i;:::-;5615:5;-1:-1:-1;5671:2:34;5656:18;;5643:32;5698:18;5687:30;;5684:50;;;5730:1;5727;5720:12;5684:50;5769:59;5820:7;5811:6;5800:9;5796:22;5769:59;:::i;:::-;5342:546;;5847:8;;-1:-1:-1;5743:85:34;;-1:-1:-1;;;;5342:546:34:o;5893:755::-;5990:6;5998;6006;6014;6022;6075:3;6063:9;6054:7;6050:23;6046:33;6043:53;;;6092:1;6089;6082:12;6043:53;6131:9;6118:23;6150:31;6175:5;6150:31;:::i;:::-;6200:5;-1:-1:-1;6257:2:34;6242:18;;6229:32;6270:33;6229:32;6270:33;:::i;:::-;6322:7;-1:-1:-1;6376:2:34;6361:18;;6348:32;;-1:-1:-1;6431:2:34;6416:18;;6403:32;6458:18;6447:30;;6444:50;;;6490:1;6487;6480:12;6444:50;6529:59;6580:7;6571:6;6560:9;6556:22;6529:59;:::i;:::-;5893:755;;;;-1:-1:-1;5893:755:34;;-1:-1:-1;6607:8:34;;6503:85;5893:755;-1:-1:-1;;;5893:755:34:o;6653:388::-;6721:6;6729;6782:2;6770:9;6761:7;6757:23;6753:32;6750:52;;;6798:1;6795;6788:12;6750:52;6837:9;6824:23;6856:31;6881:5;6856:31;:::i;:::-;6906:5;-1:-1:-1;6963:2:34;6948:18;;6935:32;6976:33;6935:32;6976:33;:::i;7046:598::-;7132:6;7140;7148;7156;7209:3;7197:9;7188:7;7184:23;7180:33;7177:53;;;7226:1;7223;7216:12;7177:53;7265:9;7252:23;7284:31;7309:5;7284:31;:::i;:::-;7334:5;-1:-1:-1;7391:2:34;7376:18;;7363:32;7404:33;7363:32;7404:33;:::i;:::-;7456:7;-1:-1:-1;7515:2:34;7500:18;;7487:32;7528:33;7487:32;7528:33;:::i;:::-;7046:598;;;;-1:-1:-1;7580:7:34;;7634:2;7619:18;7606:32;;-1:-1:-1;;7046:598:34:o;8055:251::-;8125:6;8178:2;8166:9;8157:7;8153:23;8149:32;8146:52;;;8194:1;8191;8184:12;8146:52;8226:9;8220:16;8245:31;8270:5;8245:31;:::i;8652:184::-;8722:6;8775:2;8763:9;8754:7;8750:23;8746:32;8743:52;;;8791:1;8788;8781:12;8743:52;-1:-1:-1;8814:16:34;;8652:184;-1:-1:-1;8652:184:34:o;9693:::-;-1:-1:-1;;;9742:1:34;9735:88;9842:4;9839:1;9832:15;9866:4;9863:1;9856:15;9882:125;9922:4;9950:1;9947;9944:8;9941:34;;;9955:18;;:::i;:::-;-1:-1:-1;9992:9:34;;9882:125::o;10444:277::-;10511:6;10564:2;10552:9;10543:7;10539:23;10535:32;10532:52;;;10580:1;10577;10570:12;10532:52;10612:9;10606:16;10665:5;10658:13;10651:21;10644:5;10641:32;10631:60;;10687:1;10684;10677:12;14249:273;14434:6;14426;14421:3;14408:33;14390:3;14460:16;;14485:13;;;14460:16;14249:273;-1:-1:-1;14249:273:34:o;19218:795::-;19479:4;-1:-1:-1;;;;;19589:2:34;19581:6;19577:15;19566:9;19559:34;19641:2;19633:6;19629:15;19624:2;19613:9;19609:18;19602:43;19693:2;19685:6;19681:15;19676:2;19665:9;19661:18;19654:43;;19733:6;19728:2;19717:9;19713:18;19706:34;19777:3;19771;19760:9;19756:19;19749:32;19818:6;19812:3;19801:9;19797:19;19790:35;19876:6;19868;19862:3;19851:9;19847:19;19834:49;19933:1;19927:3;19918:6;19907:9;19903:22;19899:32;19892:43;20003:3;19996:2;19992:7;19987:2;19979:6;19975:15;19971:29;19960:9;19956:45;19952:55;19944:63;;19218:795;;;;;;;;;:::o;20612:258::-;20684:1;20694:113;20708:6;20705:1;20702:13;20694:113;;;20784:11;;;20778:18;20765:11;;;20758:39;20730:2;20723:10;20694:113;;;20825:6;20822:1;20819:13;20816:48;;;-1:-1:-1;;20860:1:34;20842:16;;20835:27;20612:258::o;20875:786::-;21286:25;21281:3;21274:38;21256:3;21341:6;21335:13;21357:62;21412:6;21407:2;21402:3;21398:12;21391:4;21383:6;21379:17;21357:62;:::i;:::-;21483:19;21478:2;21438:16;;;21470:11;;;21463:40;21528:13;;21550:63;21528:13;21599:2;21591:11;;21584:4;21572:17;;21550:63;:::i;:::-;21633:17;21652:2;21629:26;;20875:786;-1:-1:-1;;;;20875:786:34:o;21666:383::-;21815:2;21804:9;21797:21;21778:4;21847:6;21841:13;21890:6;21885:2;21874:9;21870:18;21863:34;21906:66;21965:6;21960:2;21949:9;21945:18;21940:2;21932:6;21928:15;21906:66;:::i;:::-;22033:2;22012:15;-1:-1:-1;;22008:29:34;21993:45;;;;22040:2;21989:54;;21666:383;-1:-1:-1;;21666:383:34:o;22054:168::-;22094:7;22160:1;22156;22152:6;22148:14;22145:1;22142:21;22137:1;22130:9;22123:17;22119:45;22116:71;;;22167:18;;:::i;:::-;-1:-1:-1;22207:9:34;;22054:168::o;22227:128::-;22267:3;22298:1;22294:6;22291:1;22288:13;22285:39;;;22304:18;;:::i;:::-;-1:-1:-1;22340:9:34;;22227:128::o;22360:184::-;-1:-1:-1;;;22409:1:34;22402:88;22509:4;22506:1;22499:15;22533:4;22530:1;22523:15;22549:184;-1:-1:-1;;;22598:1:34;22591:88;22698:4;22695:1;22688:15;22722:4;22719:1;22712:15;22738:136;22777:3;22805:5;22795:39;;22814:18;;:::i;:::-;-1:-1:-1;;;22850:18:34;;22738:136::o
Swarm Source
ipfs://e51bdfea16490038892f8feb2068851f6ae531d935e40110b020c2e80aafd7c6
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in XDAI
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.