Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 16491436 | 1138 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
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;
uint constant public 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 onlySystemAccounts {
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
guarded(caller)
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, uint amount)
public
override
guarded(caller)
whenNotPaused
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, uint amount)
public
override
guarded(caller)
whenNotPaused
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
guarded(caller)
whenNotPaused
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.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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.0;
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 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 {
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
// 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.5.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
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
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.
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 if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* See https://github.com/ethereum/EIPs/issues/179
*/
abstract contract ERC20Basic {
function totalSupply() public virtual view returns (uint256);
function balanceOf(address _who) public virtual view 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 "./SafeMath.sol";
import "./TokenStorage.sol";
/**
* @title ERC20Lib
* @dev Standard ERC20 token functionality.
* https://github.com/ethereum/EIPs/issues/20
*/
library ERC20Lib {
using SafeMath for uint;
/**
* @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, uint 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,
uint amount
)
external
returns (bool success)
{
uint allowance_ = db.getAllowed(from, caller);
db.subBalance(from, amount);
db.addBalance(to, amount);
db.setAllowed(from, caller, allowance_.sub(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, uint 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 (uint 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 (uint 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.0;
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.0;
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 (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: 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, uint 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, uint amount) external returns (bool valid);
}
/* 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";
import "./SystemRole.sol";
/**
* @title MintableController
* @dev This contracts implements functionality allowing for minting and burning of tokens.
*/
contract MintableController is SystemRole, StandardController {
using MintableTokenLib for TokenStorage;
/**
* @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_, uint initialSupply, address frontend_)
StandardController(storage_, initialSupply, frontend_)
{ }
/**
* @dev Assigns the system role to an account.
*/
function addSystemAccount(address account) public override onlyOwner {
super.addSystemAccount(account);
}
/**
* @dev Removes the system role from an account.
*/
function removeSystemAccount(address account) public override onlyOwner {
super.removeSystemAccount(account);
}
/**
* @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, uint amount)
public
guarded(caller)
onlySystemAccount(caller)
returns (bool)
{
avoidBlackholes(to);
return token.mint(to, amount);
}
/**
* @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, uint amount, bytes32 h, uint8 v, bytes32 r, bytes32 s)
public
guarded(caller)
onlySystemAccount(caller)
returns (bool)
{
return token.burn(from, amount, h, v, r, s);
}
/**
* @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, uint amount)
public
guarded(msg.sender)
onlySystemAccount(msg.sender)
returns (bool)
{
return token.burn(from, amount);
}
}
/* 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 "./SafeMath.sol";
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 SafeMath for uint;
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,
uint 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,
uint 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,
uint 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.0;
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 relinquish control of the contract.
* @notice Renouncing to ownership will leave the contract without an owner.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner);
owner = address(0);
}
/**
* @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
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
pragma solidity ^0.8.0;
import "./Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
/* SPDX-License-Identifier: MIT */
pragma solidity 0.8.11;
/**
* @title Roles
* @author Francisco Giordano (@frangio)
* @dev Library for managing addresses assigned to a Role.
* See RBAC.sol for example usage.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev give an address access to this role
*/
function add(Role storage _role, address _addr)
internal
{
_role.bearer[_addr] = true;
}
/**
* @dev remove an address' access to this role
*/
function remove(Role storage _role, address _addr)
internal
{
_role.bearer[_addr] = false;
}
/**
* @dev check if an address has this role
* // reverts
*/
function check(Role storage _role, address _addr)
internal
view
{
require(has(_role, _addr));
}
/**
* @dev check if an address has this role
* @return bool
*/
function has(Role storage _role, address _addr)
internal
view
returns (bool)
{
return _role.bearer[_addr];
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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 v4.4.1 (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.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, (bytes4)) == 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, uint 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, uint 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 (uint)
{
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"
);
uint amount = token.balanceOf(from);
token.burn(from, amount);
token.mint(to, amount);
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 "./Claimable.sol";
import "./Pausable.sol";
import "./TokenStorage.sol";
import "./IERC20.sol";
import "./ERC20Lib.sol";
import "./ERC677Lib.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 Pausable, Claimable {
using ERC20Lib for TokenStorage;
using ERC677Lib for TokenStorage;
TokenStorage internal token;
address internal frontend;
mapping(address => bool) internal bridgeFrontends;
string public name;
string public symbol;
uint 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 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 either be the sender or the function must be
* called via the frontend, otherwise the call is reverted.
* @param caller The address of the passed-in caller. Used to preserve the original caller.
*/
modifier guarded(address caller) {
require(
msg.sender == caller || isFrontend(msg.sender),
"either caller must be sender or calling via frontend"
);
_;
}
/**
* @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_, uint 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 {
emit BridgeFrontend(frontend_, title);
bridgeFrontends[frontend_] = true;
}
/**
* @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, uint amount)
public
virtual
guarded(caller)
whenNotPaused
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, uint amount)
public
virtual
guarded(caller)
whenNotPaused
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, uint amount)
public
guarded(caller)
whenNotPaused
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
guarded(caller)
whenNotPaused
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);
}
/**
* @dev Pause the function protected by Pausable modifier.
*/
function pause() public onlyOwner
{
_pause();
}
/**
* @dev Unpause the function protected by Pausable modifier.
*/
function unpause() public onlyOwner
{
_unpause();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
/* SPDX-License-Identifier: 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 "./Roles.sol";
/**
* @title SystemRole
* @dev SystemRole accounts have been approved to perform operational actions (e.g. mint and burn).
* @notice addSystemAccount and removeSystemAccount are unprotected by default, i.e. anyone can call them.
* @notice Contracts inheriting SystemRole *should* authorize the caller by overriding them.
* @notice The contract is an abstract contract.
*/
abstract contract SystemRole {
using Roles for Roles.Role;
Roles.Role private systemAccounts;
/**
* @dev Emitted when system account is added.
* @param account is a new system account.
*/
event SystemAccountAdded(address indexed account);
/**
* @dev Emitted when system account is removed.
* @param account is the old system account.
*/
event SystemAccountRemoved(address indexed account);
/**
* @dev Modifier which prevents non-system accounts from calling protected functions.
*/
modifier onlySystemAccounts() {
require(isSystemAccount(msg.sender));
_;
}
/**
* @dev Modifier which prevents non-system accounts from being passed to the guard.
* @param account The account to check.
*/
modifier onlySystemAccount(address account) {
require(
isSystemAccount(account),
"must be a system account"
);
_;
}
/**
* @dev Checks whether an address is a system account.
* @param account the address to check.
* @return true if system account.
*/
function isSystemAccount(address account) public view returns (bool) {
return systemAccounts.has(account);
}
/**
* @dev Assigns the system role to an account.
* @notice This method is unprotected and should be authorized in the child contract.
*/
function addSystemAccount(address account) public virtual {
systemAccounts.add(account);
emit SystemAccountAdded(account);
}
/**
* @dev Removes the system role from an account.
* @notice This method is unprotected and should be authorized in the child contract.
*/
function removeSystemAccount(address account) public virtual {
systemAccounts.remove(account);
emit SystemAccountRemoved(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, uint 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, uint 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 Qunatity of allowance.
*/
function setAllowed(address owner, address spender, uint amount) external onlyOwner {
tokenStorage.setAllowed(owner, spender, amount);
}
/**
* @dev Returns the supply of tokens.
* @return Total supply.
*/
function getSupply() external view returns (uint) {
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 (uint) {
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 (uint)
{
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;
import "./SafeMath.sol";
/*
* @title TokenStorageLib
* @dev Implementation of an[external storage for tokens.
*/
library TokenStorageLib {
using SafeMath for uint;
struct TokenStorage {
mapping (address => uint) balances;
mapping (address => mapping (address => uint)) allowed;
uint 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, uint amount)
external
{
self.totalSupply = self.totalSupply.add(amount);
self.balances[to] = self.balances[to].add(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, uint amount)
external
{
self.totalSupply = self.totalSupply.sub(amount);
self.balances[from] = self.balances[from].sub(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, uint 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":"frontend","type":"address"},{"indexed":true,"internalType":"string","name":"title","type":"string"}],"name":"BridgeFrontend","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":true,"internalType":"address","name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"INITIAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrontend","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"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":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"removeSystemAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","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":"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":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"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"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405260126008553480156200001657600080fd5b50604051620035bd380380620035bd8339810160408190526200003991620002f7565b600180546001600160a81b0319166101003302179055836000828282826001600160a01b03831615806200006b575081155b620000e35760405162461bcd60e51b815260206004820152603f60248201527f656974686572206120746f6b656e2073746f72616765206d757374206265206960448201527f6e697469616c697a6564206f72206e6f20696e697469616c20737570706c790060648201526084015b60405180910390fd5b6001600160a01b0383166200019a576040516200010090620002cc565b604051809103906000f0801580156200011d573d6000803e3d6000fd5b50600380546001600160a01b0319166001600160a01b039290921691821790556040516310f29c1d60e11b8152336004820152602481018490526321e5383a90604401600060405180830381600087803b1580156200017b57600080fd5b505af115801562000190573d6000803e3d6000fd5b50505050620001b6565b600380546001600160a01b0319166001600160a01b0385161790555b600480546001600160a01b0319166001600160a01b039283161790558816151594506200023793505050505760405162461bcd60e51b8152602060048201526024808201527f76616c696461746f722063616e6e6f7420626520746865206e756c6c206164646044820152637265737360e01b6064820152608401620000da565b60405163ad41534960e01b8152600960048201526001600160a01b0384166024820152732ecb7d02c0bfd824d88f47e26602a6ae861482429063ad4153499060440160006040518083038186803b1580156200029257600080fd5b505af4158015620002a7573d6000803e3d6000fd5b5050600a805462ffffff191660e89590951c9490941790935550620003639350505050565b610b5c8062002a6183390190565b80516001600160a01b0381168114620002f257600080fd5b919050565b600080600080608085870312156200030e57600080fd5b6200031985620002da565b93506200032960208601620002da565b60408601519093506001600160e81b0319811681146200034857600080fd5b91506200035860608601620002da565b905092959194509250565b6126ee80620003736000396000f3fe608060405234801561001057600080fd5b50600436106102765760003560e01c8063715018a6116101605780639e7f43ca116100d8578063e30c39781161008c578063ebbc3d4611610071578063ebbc3d46146104f3578063ee0b544514610506578063f2fde38b1461051957600080fd5b8063e30c3978146104cd578063e974fee9146104e057600080fd5b8063b516af70116100bd578063b516af701461049f578063dd62ed3e146104a7578063e174fd94146104ba57600080fd5b80639e7f43ca14610479578063a84c56d01461048c57600080fd5b80638ba47bdd1161012f5780638fb81d98116101145780638fb81d981461044b5780639137c1a71461045e57806395d89b411461047157600080fd5b80638ba47bdd146103f55780638da5cb5b1461043357600080fd5b8063715018a6146103bf578063774d5409146103c757806379cc6790146103da5780638456cb59146103ed57600080fd5b8063326ecb05116101f35780634e71e0c8116101c25780635c975abb116101a75780635c975abb1461038e57806369569a511461039957806370a08231146103ac57600080fd5b80634e71e0c8146103735780634eb007541461037b57600080fd5b8063326ecb05146103345780633408f73a146103475780633cd1570f146103585780633f4ba83a1461036b57600080fd5b806318160ddd1161024a5780632ff2e9dc1161022f5780632ff2e9dc14610310578063313ce56714610318578063322ec0fb1461032157600080fd5b806318160ddd146102d757806325ec2eb0146102ed57600080fd5b80623074ff1461027b57806306fdde03146102a55780631195e07e146102ba5780631327d3d8146102c2575b600080fd5b6004546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6102ad61052c565b60405161029c9190612231565b6102886105ba565b6102d56102d036600461229b565b61064f565b005b6102df6106ef565b60405190815260200161029c565b6103006102fb36600461229b565b610776565b604051901515815260200161029c565b6102df600081565b6102df60085481565b61030061032f3660046122b8565b6107b3565b61030061034236600461229b565b610950565b6003546001600160a01b0316610288565b6102df61036636600461230f565b610971565b6102d5610b2c565b6102d5610b52565b610300610389366004612386565b610bfa565b60015460ff16610300565b6102d56103a736600461229b565b610d9d565b6102df6103ba36600461229b565b610e22565b6102d5610eaa565b6103006103d53660046122b8565b610f22565b6103006103e83660046123d8565b6110a9565b6102d5611186565b600a546104029060e81b81565b6040517fffffff0000000000000000000000000000000000000000000000000000000000909116815260200161029c565b6001546102889061010090046001600160a01b031681565b6102d561045936600461244d565b6111aa565b6102d561046c36600461229b565b611237565b6102ad6112bc565b6103006104873660046124a2565b6112c9565b6102d561049a36600461229b565b6114b2565b6102d56114da565b6102df6104b5366004612515565b611560565b6103006104c83660046122b8565b611613565b600254610288906001600160a01b031681565b6103006104ee36600461254e565b6117c9565b6102d561050136600461229b565b611980565b6102d561051436600461229b565b6119a5565b6102d561052736600461229b565b611a35565b600680546105399061259f565b80601f01602080910402602001604051908101604052809291908181526020018280546105659061259f565b80156105b25780601f10610587576101008083540402835291602001916105b2565b820191906000526020600020905b81548152906001019060200180831161059557829003601f168201915b505050505081565b6040517f6271970c00000000000000000000000000000000000000000000000000000000815260096004820152600090732ecb7d02c0bfd824d88f47e26602a6ae8614824290636271970c90602401602060405180830381865af4158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a91906125f3565b905090565b61065833610950565b61066157600080fd5b6040517fad415349000000000000000000000000000000000000000000000000000000008152600960048201526001600160a01b0382166024820152732ecb7d02c0bfd824d88f47e26602a6ae861482429063ad4153499060440160006040518083038186803b1580156106d457600080fd5b505af41580156106e8573d6000803e3d6000fd5b5050505050565b600354604080517f6c9c2faf00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691636c9c2faf9160048083019260209291908290030181865afa158015610752573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a9190612610565b6004546000906001600160a01b03838116911614806107ad57506001600160a01b03821660009081526005602052604090205460ff165b92915050565b600083336001600160a01b03821614806107d157506107d133610776565b61083f5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b60648201526084015b60405180910390fd5b8461084981610950565b6108955760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b61089e85611a80565b6003546040517fb0c29c740000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015290861660248201526044810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063b0c29c7490606401602060405180830381865af4158015610922573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109469190612629565b9695505050505050565b6001600160a01b03811660009081526020819052604081205460ff166107ad565b600087336001600160a01b038216148061098f575061098f33610776565b6109f85760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b88610a0281610950565b610a4e5760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b610a5788611a80565b6003546040517f8f7227340000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528a8216602482015290891660448201526064810188905260ff8716608482015260a4810186905260c48101859052732ecb7d02c0bfd824d88f47e26602a6ae8614824290638f7227349060e401602060405180830381865af4158015610afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612610565b9a9950505050505050505050565b60015461010090046001600160a01b03163314610b4857600080fd5b610b50611c41565b565b6002546001600160a01b03163314610b6957600080fd5b6002546001546040516001600160a01b0392831692610100909204909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600280546001805474ffffffffffffffffffffffffffffffffffffffff0019166101006001600160a01b0384160217905573ffffffffffffffffffffffffffffffffffffffff19169055565b600087336001600160a01b0382161480610c185750610c1833610776565b610c815760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b88610c8b81610950565b610cd75760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b6003546040517f799639d40000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152908a166024820152604481018990526064810188905260ff8716608482015260a4810186905260c4810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063799639d49060e401602060405180830381865af4158015610d79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612629565b60015461010090046001600160a01b03163314610db957600080fd5b6004546040516001600160a01b038084169216907fcb01f884fc4203d4c1643cb0e126faeb397682c122ca8c0433776d42cdc0060a90600090a36004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6003546040517ff8b2cb4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063f8b2cb4f90602401602060405180830381865afa158015610e86573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ad9190612610565b60015461010090046001600160a01b03163314610ec657600080fd5b6001546040516101009091046001600160a01b0316907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26001805474ffffffffffffffffffffffffffffffffffffffff0019169055565b600083336001600160a01b0382161480610f405750610f4033610776565b610fa95760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff1615610fef5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6003546040517f365feff10000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152868216602482015290851660448201526064810184905273b912a741f60779390d789c3c5f78131b999493b59063365feff1906084015b602060405180830381865af415801561107c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a09190612629565b95945050505050565b600033336110b681610950565b6111025760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b6003546040517fa6c9ac280000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015290861660248201526044810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063a6c9ac2890606401602060405180830381865af415801561107c573d6000803e3d6000fd5b60015461010090046001600160a01b031633146111a257600080fd5b610b50611cdd565b60015461010090046001600160a01b031633146111c657600080fd5b81816040516111d692919061264b565b604051908190038120906001600160a01b038516907fec75908259de4d038ff5f2b6b99e3725bc21871f4d2a44adeff9bb814afbc9f790600090a350506001600160a01b03166000908152600560205260409020805460ff19166001179055565b60015461010090046001600160a01b0316331461125357600080fd5b6003546040516001600160a01b038084169216907fdaaa9d417a3107fd3d9db02eba3eeafbae2b8af16ee08c534f5bc449054c1c4c90600090a36003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600780546105399061259f565b600085336001600160a01b03821614806112e757506112e733610776565b6113505760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156113965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380891660248301528716604482015260648101869052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af4158015611404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114289190612629565b61149a5760405162461bcd60e51b815260206004820152602160248201527f7472616e73666572416e6443616c6c2072657175657374206e6f742076616c6960448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610836565b6114a78787878787611d56565b979650505050505050565b60015461010090046001600160a01b031633146114ce57600080fd5b6114d781611ed2565b50565b60015461010090046001600160a01b031633146114f657600080fd5b600360009054906101000a90046001600160a01b03166001600160a01b0316634e71e0c86040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561154657600080fd5b505af115801561155a573d6000803e3d6000fd5b50505050565b6003546040517f1045d7ce0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528382166024820152908216604482015260009073b912a741f60779390d789c3c5f78131b999493b590631045d7ce90606401602060405180830381865af41580156115e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160c9190612610565b9392505050565b600083336001600160a01b0382161480611631575061163133610776565b61169a5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156116e05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380871660248301528516604482015260648101849052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af415801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190612629565b6117be5760405162461bcd60e51b815260206004820152601a60248201527f7472616e736665722072657175657374206e6f742076616c69640000000000006044820152606401610836565b6110a0858585611f34565b600084336001600160a01b03821614806117e757506117e733610776565b6118505760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156118965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380871660248301528516604482015260648101849052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af4158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190612629565b6119745760405162461bcd60e51b815260206004820152601e60248201527f7472616e7366657246726f6d2072657175657374206e6f742076616c696400006044820152606401610836565b6109468686868661207e565b60015461010090046001600160a01b0316331461199c57600080fd5b6114d7816121e8565b60015461010090046001600160a01b031633146119c157600080fd5b6003546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063f2fde38b90602401600060405180830381600087803b158015611a2157600080fd5b505af11580156106e8573d6000803e3d6000fd5b60015461010090046001600160a01b03163314611a5157600080fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001600160a01b038116611ad65760405162461bcd60e51b815260206004820152601460248201527f6d757374206e6f742073656e6420746f203078300000000000000000000000006044820152606401610836565b6001600160a01b038116301415611b2f5760405162461bcd60e51b815260206004820152601b60248201527f6d757374206e6f742073656e6420746f20636f6e74726f6c6c657200000000006044820152606401610836565b6003546001600160a01b0382811691161415611b8d5760405162461bcd60e51b815260206004820152601e60248201527f6d757374206e6f742073656e6420746f20746f6b656e2073746f7261676500006044820152606401610836565b6004546001600160a01b0382811691161415611beb5760405162461bcd60e51b815260206004820152601960248201527f6d757374206e6f742073656e6420746f2066726f6e74656e64000000000000006044820152606401610836565b611bf481610776565b156114d75760405162461bcd60e51b815260206004820181905260248201527f6d757374206e6f742073656e6420746f2062726964676546726f6e74656e64736044820152606401610836565b60015460ff16611c935760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610836565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60015460ff1615611d235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833611cc0565b600085336001600160a01b0382161480611d745750611d7433610776565b611ddd5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff1615611e235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b611e2c86611a80565b6003546040517f1eb8bccb00000000000000000000000000000000000000000000000000000000815273f6d4568574c1de8f1eb002f58d1e5ecdf652b1d091631eb8bccb91611e91916001600160a01b0316908b908b908b908b908b9060040161265b565b602060405180830381865af4158015611eae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a79190612629565b611efd6000826001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6040516001600160a01b038216907fdfb5b1167ef9eadf5cac67570f1a2971a6f6175303b9d4166a65a11d0a294e3490600090a250565b600083336001600160a01b0382161480611f525750611f5233610776565b611fbb5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156120015760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b61200a84611a80565b6003546040517f44ded8ba0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152868216602482015290851660448201526064810184905273b912a741f60779390d789c3c5f78131b999493b5906344ded8ba9060840161105f565b600084336001600160a01b038216148061209c575061209c33610776565b6121055760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff161561214b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b61215484611a80565b6003546040517ff3a0ddf90000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528782166024820152868216604482015290851660648201526084810184905273b912a741f60779390d789c3c5f78131b999493b59063f3a0ddf99060a401602060405180830381865af4158015610922573d6000803e3d6000fd5b6001600160a01b038116600081815260208190526040808220805460ff19169055517f21bfb3de07221bc6197a8c23f7a059308b7a741f259cf4ef3b519cde0fde7ac39190a250565b600060208083528351808285015260005b8181101561225e57858101830151858201604001528201612242565b81811115612270576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146114d757600080fd5b6000602082840312156122ad57600080fd5b813561160c81612286565b6000806000606084860312156122cd57600080fd5b83356122d881612286565b925060208401356122e881612286565b929592945050506040919091013590565b803560ff8116811461230a57600080fd5b919050565b600080600080600080600060e0888a03121561232a57600080fd5b873561233581612286565b9650602088013561234581612286565b9550604088013561235581612286565b94506060880135935061236a608089016122f9565b925060a0880135915060c0880135905092959891949750929550565b600080600080600080600060e0888a0312156123a157600080fd5b87356123ac81612286565b965060208801356123bc81612286565b9550604088013594506060880135935061236a608089016122f9565b600080604083850312156123eb57600080fd5b82356123f681612286565b946020939093013593505050565b60008083601f84011261241657600080fd5b50813567ffffffffffffffff81111561242e57600080fd5b60208301915083602082850101111561244657600080fd5b9250929050565b60008060006040848603121561246257600080fd5b833561246d81612286565b9250602084013567ffffffffffffffff81111561248957600080fd5b61249586828701612404565b9497909650939450505050565b6000806000806000608086880312156124ba57600080fd5b85356124c581612286565b945060208601356124d581612286565b935060408601359250606086013567ffffffffffffffff8111156124f857600080fd5b61250488828901612404565b969995985093965092949392505050565b6000806040838503121561252857600080fd5b823561253381612286565b9150602083013561254381612286565b809150509250929050565b6000806000806080858703121561256457600080fd5b843561256f81612286565b9350602085013561257f81612286565b9250604085013561258f81612286565b9396929550929360600135925050565b600181811c908216806125b357607f821691505b602082108114156125ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561260557600080fd5b815161160c81612286565b60006020828403121561262257600080fd5b5051919050565b60006020828403121561263b57600080fd5b8151801515811461160c57600080fd5b8183823760009101908152919050565b60006001600160a01b038089168352808816602084015280871660408401525084606083015260a060808301528260a0830152828460c0840137600060c0848401015260c0601f19601f850116830101905097965050505050505056fea2646970667358221220589a221d8b174737710c755745052e2f1667b39f8d95fad86ef93c86334ff97964736f6c634300080b0033608060405234801561001057600080fd5b50600080546001600160a01b03191633179055341561002e57600080fd5b610b1f8061003d6000396000f3fe608060405234801561001057600080fd5b50600436106100ec5760003560e01c80638da5cb5b11610091578063cf8eeb7e11610063578063cf8eeb7e146101be578063e30c3978146101d1578063f2fde38b146101e4578063f8b2cb4f146101f757005b80638da5cb5b146101655780639f727c2714610190578063c0ee0b8a14610198578063c7c7e9ea146101ab57005b806333dd1b8a116100ca57806333dd1b8a146101275780634e71e0c81461013a5780636c9c2faf14610142578063715018a61461015d57005b806317ffc320146100ee57806321e5383a146101015780632aed7f3f14610114575b005b6100ec6100fc366004610962565b61020a565b6100ec61010f36600461097f565b6102c6565b6100ec610122366004610962565b610374565b6100ec6101353660046109ab565b610400565b6100ec6104b6565b61014a61053e565b6040519081526020015b60405180910390f35b6100ec6105d3565b600054610178906001600160a01b031681565b6040516001600160a01b039091168152602001610154565b6100ec61063f565b6100ec6101a63660046109ec565b600080fd5b61014a6101b9366004610a75565b610693565b6100ec6101cc36600461097f565b610741565b600154610178906001600160a01b031681565b6100ec6101f2366004610962565b6107bf565b61014a610205366004610962565b6107c8565b6000546001600160a01b0316331461022157600080fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610281573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a59190610aae565b6000549091506102c2906001600160a01b0384811691168361086d565b5050565b6000546001600160a01b031633146102dd57600080fd5b6040517f7aeb0ed5000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b03831660248201526044810182905273e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c90637aeb0ed5906064015b60006040518083038186803b15801561035857600080fd5b505af415801561036c573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461038b57600080fd5b6000546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152829182169063f2fde38b90602401600060405180830381600087803b1580156103ec57600080fd5b505af115801561036c573d6000803e3d6000fd5b6000546001600160a01b0316331461041757600080fd5b6040517f5599b4b7000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b038085166024830152831660448201526064810182905273e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c90635599b4b79060840160006040518083038186803b15801561049957600080fd5b505af41580156104ad573d6000803e3d6000fd5b50505050505050565b6001546001600160a01b031633146104cd57600080fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600180546000805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03841617909155169055565b6040517f072f9a500000000000000000000000000000000000000000000000000000000081526002600482015260009073e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c9063072f9a5090602401602060405180830381865af41580156105aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ce9190610aae565b905090565b6000546001600160a01b031633146105ea57600080fd5b600080546040516001600160a01b03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6000546001600160a01b0316331461065657600080fd5b600080546040516001600160a01b03909116914780156108fc02929091818181858888f19350505050158015610690573d6000803e3d6000fd5b50565b6040517f9daeae1e000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b0380841660248301528216604482015260009073e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c90639daeae1e90606401602060405180830381865af4158015610716573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073a9190610aae565b9392505050565b6000546001600160a01b0316331461075857600080fd5b6040517fd9c7339e000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b03831660248201526044810182905273e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c9063d9c7339e90606401610340565b61069081610907565b6040517fb0aacf24000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b038216602482015260009073e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c9063b0aacf2490604401602060405180830381865af4158015610843573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108679190610aae565b92915050565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af11580156108d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f99190610ac7565b61090257600080fd5b505050565b6000546001600160a01b0316331461091e57600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001600160a01b038116811461069057600080fd5b60006020828403121561097457600080fd5b813561073a8161094d565b6000806040838503121561099257600080fd5b823561099d8161094d565b946020939093013593505050565b6000806000606084860312156109c057600080fd5b83356109cb8161094d565b925060208401356109db8161094d565b929592945050506040919091013590565b60008060008060608587031215610a0257600080fd5b8435610a0d8161094d565b935060208501359250604085013567ffffffffffffffff80821115610a3157600080fd5b818701915087601f830112610a4557600080fd5b813581811115610a5457600080fd5b886020828501011115610a6657600080fd5b95989497505060200194505050565b60008060408385031215610a8857600080fd5b8235610a938161094d565b91506020830135610aa38161094d565b809150509250929050565b600060208284031215610ac057600080fd5b5051919050565b600060208284031215610ad957600080fd5b8151801515811461073a57600080fdfea2646970667358221220f0093be45eefa3b445c0e69fc35c23602399ad72137343475b219857f044da1564736f6c634300080b003300000000000000000000000057f1b40baf4d5708a15fea71e06841897cd2d262000000000000000000000000774681a648125d46f35017cf6cec43a41857254e45555200000000000000000000000000000000000000000000000000000000000000000000000000000000003231cb76718cdef2155fc47b5286d82e6eda273f
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102765760003560e01c8063715018a6116101605780639e7f43ca116100d8578063e30c39781161008c578063ebbc3d4611610071578063ebbc3d46146104f3578063ee0b544514610506578063f2fde38b1461051957600080fd5b8063e30c3978146104cd578063e974fee9146104e057600080fd5b8063b516af70116100bd578063b516af701461049f578063dd62ed3e146104a7578063e174fd94146104ba57600080fd5b80639e7f43ca14610479578063a84c56d01461048c57600080fd5b80638ba47bdd1161012f5780638fb81d98116101145780638fb81d981461044b5780639137c1a71461045e57806395d89b411461047157600080fd5b80638ba47bdd146103f55780638da5cb5b1461043357600080fd5b8063715018a6146103bf578063774d5409146103c757806379cc6790146103da5780638456cb59146103ed57600080fd5b8063326ecb05116101f35780634e71e0c8116101c25780635c975abb116101a75780635c975abb1461038e57806369569a511461039957806370a08231146103ac57600080fd5b80634e71e0c8146103735780634eb007541461037b57600080fd5b8063326ecb05146103345780633408f73a146103475780633cd1570f146103585780633f4ba83a1461036b57600080fd5b806318160ddd1161024a5780632ff2e9dc1161022f5780632ff2e9dc14610310578063313ce56714610318578063322ec0fb1461032157600080fd5b806318160ddd146102d757806325ec2eb0146102ed57600080fd5b80623074ff1461027b57806306fdde03146102a55780631195e07e146102ba5780631327d3d8146102c2575b600080fd5b6004546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6102ad61052c565b60405161029c9190612231565b6102886105ba565b6102d56102d036600461229b565b61064f565b005b6102df6106ef565b60405190815260200161029c565b6103006102fb36600461229b565b610776565b604051901515815260200161029c565b6102df600081565b6102df60085481565b61030061032f3660046122b8565b6107b3565b61030061034236600461229b565b610950565b6003546001600160a01b0316610288565b6102df61036636600461230f565b610971565b6102d5610b2c565b6102d5610b52565b610300610389366004612386565b610bfa565b60015460ff16610300565b6102d56103a736600461229b565b610d9d565b6102df6103ba36600461229b565b610e22565b6102d5610eaa565b6103006103d53660046122b8565b610f22565b6103006103e83660046123d8565b6110a9565b6102d5611186565b600a546104029060e81b81565b6040517fffffff0000000000000000000000000000000000000000000000000000000000909116815260200161029c565b6001546102889061010090046001600160a01b031681565b6102d561045936600461244d565b6111aa565b6102d561046c36600461229b565b611237565b6102ad6112bc565b6103006104873660046124a2565b6112c9565b6102d561049a36600461229b565b6114b2565b6102d56114da565b6102df6104b5366004612515565b611560565b6103006104c83660046122b8565b611613565b600254610288906001600160a01b031681565b6103006104ee36600461254e565b6117c9565b6102d561050136600461229b565b611980565b6102d561051436600461229b565b6119a5565b6102d561052736600461229b565b611a35565b600680546105399061259f565b80601f01602080910402602001604051908101604052809291908181526020018280546105659061259f565b80156105b25780601f10610587576101008083540402835291602001916105b2565b820191906000526020600020905b81548152906001019060200180831161059557829003601f168201915b505050505081565b6040517f6271970c00000000000000000000000000000000000000000000000000000000815260096004820152600090732ecb7d02c0bfd824d88f47e26602a6ae8614824290636271970c90602401602060405180830381865af4158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a91906125f3565b905090565b61065833610950565b61066157600080fd5b6040517fad415349000000000000000000000000000000000000000000000000000000008152600960048201526001600160a01b0382166024820152732ecb7d02c0bfd824d88f47e26602a6ae861482429063ad4153499060440160006040518083038186803b1580156106d457600080fd5b505af41580156106e8573d6000803e3d6000fd5b5050505050565b600354604080517f6c9c2faf00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691636c9c2faf9160048083019260209291908290030181865afa158015610752573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a9190612610565b6004546000906001600160a01b03838116911614806107ad57506001600160a01b03821660009081526005602052604090205460ff165b92915050565b600083336001600160a01b03821614806107d157506107d133610776565b61083f5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b60648201526084015b60405180910390fd5b8461084981610950565b6108955760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b61089e85611a80565b6003546040517fb0c29c740000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015290861660248201526044810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063b0c29c7490606401602060405180830381865af4158015610922573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109469190612629565b9695505050505050565b6001600160a01b03811660009081526020819052604081205460ff166107ad565b600087336001600160a01b038216148061098f575061098f33610776565b6109f85760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b88610a0281610950565b610a4e5760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b610a5788611a80565b6003546040517f8f7227340000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528a8216602482015290891660448201526064810188905260ff8716608482015260a4810186905260c48101859052732ecb7d02c0bfd824d88f47e26602a6ae8614824290638f7227349060e401602060405180830381865af4158015610afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612610565b9a9950505050505050505050565b60015461010090046001600160a01b03163314610b4857600080fd5b610b50611c41565b565b6002546001600160a01b03163314610b6957600080fd5b6002546001546040516001600160a01b0392831692610100909204909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600280546001805474ffffffffffffffffffffffffffffffffffffffff0019166101006001600160a01b0384160217905573ffffffffffffffffffffffffffffffffffffffff19169055565b600087336001600160a01b0382161480610c185750610c1833610776565b610c815760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b88610c8b81610950565b610cd75760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b6003546040517f799639d40000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152908a166024820152604481018990526064810188905260ff8716608482015260a4810186905260c4810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063799639d49060e401602060405180830381865af4158015610d79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612629565b60015461010090046001600160a01b03163314610db957600080fd5b6004546040516001600160a01b038084169216907fcb01f884fc4203d4c1643cb0e126faeb397682c122ca8c0433776d42cdc0060a90600090a36004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6003546040517ff8b2cb4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063f8b2cb4f90602401602060405180830381865afa158015610e86573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ad9190612610565b60015461010090046001600160a01b03163314610ec657600080fd5b6001546040516101009091046001600160a01b0316907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26001805474ffffffffffffffffffffffffffffffffffffffff0019169055565b600083336001600160a01b0382161480610f405750610f4033610776565b610fa95760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff1615610fef5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6003546040517f365feff10000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152868216602482015290851660448201526064810184905273b912a741f60779390d789c3c5f78131b999493b59063365feff1906084015b602060405180830381865af415801561107c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a09190612629565b95945050505050565b600033336110b681610950565b6111025760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b6003546040517fa6c9ac280000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015290861660248201526044810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063a6c9ac2890606401602060405180830381865af415801561107c573d6000803e3d6000fd5b60015461010090046001600160a01b031633146111a257600080fd5b610b50611cdd565b60015461010090046001600160a01b031633146111c657600080fd5b81816040516111d692919061264b565b604051908190038120906001600160a01b038516907fec75908259de4d038ff5f2b6b99e3725bc21871f4d2a44adeff9bb814afbc9f790600090a350506001600160a01b03166000908152600560205260409020805460ff19166001179055565b60015461010090046001600160a01b0316331461125357600080fd5b6003546040516001600160a01b038084169216907fdaaa9d417a3107fd3d9db02eba3eeafbae2b8af16ee08c534f5bc449054c1c4c90600090a36003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600780546105399061259f565b600085336001600160a01b03821614806112e757506112e733610776565b6113505760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156113965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380891660248301528716604482015260648101869052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af4158015611404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114289190612629565b61149a5760405162461bcd60e51b815260206004820152602160248201527f7472616e73666572416e6443616c6c2072657175657374206e6f742076616c6960448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610836565b6114a78787878787611d56565b979650505050505050565b60015461010090046001600160a01b031633146114ce57600080fd5b6114d781611ed2565b50565b60015461010090046001600160a01b031633146114f657600080fd5b600360009054906101000a90046001600160a01b03166001600160a01b0316634e71e0c86040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561154657600080fd5b505af115801561155a573d6000803e3d6000fd5b50505050565b6003546040517f1045d7ce0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528382166024820152908216604482015260009073b912a741f60779390d789c3c5f78131b999493b590631045d7ce90606401602060405180830381865af41580156115e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160c9190612610565b9392505050565b600083336001600160a01b0382161480611631575061163133610776565b61169a5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156116e05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380871660248301528516604482015260648101849052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af415801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190612629565b6117be5760405162461bcd60e51b815260206004820152601a60248201527f7472616e736665722072657175657374206e6f742076616c69640000000000006044820152606401610836565b6110a0858585611f34565b600084336001600160a01b03821614806117e757506117e733610776565b6118505760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156118965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380871660248301528516604482015260648101849052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af4158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190612629565b6119745760405162461bcd60e51b815260206004820152601e60248201527f7472616e7366657246726f6d2072657175657374206e6f742076616c696400006044820152606401610836565b6109468686868661207e565b60015461010090046001600160a01b0316331461199c57600080fd5b6114d7816121e8565b60015461010090046001600160a01b031633146119c157600080fd5b6003546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063f2fde38b90602401600060405180830381600087803b158015611a2157600080fd5b505af11580156106e8573d6000803e3d6000fd5b60015461010090046001600160a01b03163314611a5157600080fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001600160a01b038116611ad65760405162461bcd60e51b815260206004820152601460248201527f6d757374206e6f742073656e6420746f203078300000000000000000000000006044820152606401610836565b6001600160a01b038116301415611b2f5760405162461bcd60e51b815260206004820152601b60248201527f6d757374206e6f742073656e6420746f20636f6e74726f6c6c657200000000006044820152606401610836565b6003546001600160a01b0382811691161415611b8d5760405162461bcd60e51b815260206004820152601e60248201527f6d757374206e6f742073656e6420746f20746f6b656e2073746f7261676500006044820152606401610836565b6004546001600160a01b0382811691161415611beb5760405162461bcd60e51b815260206004820152601960248201527f6d757374206e6f742073656e6420746f2066726f6e74656e64000000000000006044820152606401610836565b611bf481610776565b156114d75760405162461bcd60e51b815260206004820181905260248201527f6d757374206e6f742073656e6420746f2062726964676546726f6e74656e64736044820152606401610836565b60015460ff16611c935760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610836565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60015460ff1615611d235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833611cc0565b600085336001600160a01b0382161480611d745750611d7433610776565b611ddd5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff1615611e235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b611e2c86611a80565b6003546040517f1eb8bccb00000000000000000000000000000000000000000000000000000000815273f6d4568574c1de8f1eb002f58d1e5ecdf652b1d091631eb8bccb91611e91916001600160a01b0316908b908b908b908b908b9060040161265b565b602060405180830381865af4158015611eae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a79190612629565b611efd6000826001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6040516001600160a01b038216907fdfb5b1167ef9eadf5cac67570f1a2971a6f6175303b9d4166a65a11d0a294e3490600090a250565b600083336001600160a01b0382161480611f525750611f5233610776565b611fbb5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156120015760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b61200a84611a80565b6003546040517f44ded8ba0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152868216602482015290851660448201526064810184905273b912a741f60779390d789c3c5f78131b999493b5906344ded8ba9060840161105f565b600084336001600160a01b038216148061209c575061209c33610776565b6121055760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff161561214b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b61215484611a80565b6003546040517ff3a0ddf90000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528782166024820152868216604482015290851660648201526084810184905273b912a741f60779390d789c3c5f78131b999493b59063f3a0ddf99060a401602060405180830381865af4158015610922573d6000803e3d6000fd5b6001600160a01b038116600081815260208190526040808220805460ff19169055517f21bfb3de07221bc6197a8c23f7a059308b7a741f259cf4ef3b519cde0fde7ac39190a250565b600060208083528351808285015260005b8181101561225e57858101830151858201604001528201612242565b81811115612270576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146114d757600080fd5b6000602082840312156122ad57600080fd5b813561160c81612286565b6000806000606084860312156122cd57600080fd5b83356122d881612286565b925060208401356122e881612286565b929592945050506040919091013590565b803560ff8116811461230a57600080fd5b919050565b600080600080600080600060e0888a03121561232a57600080fd5b873561233581612286565b9650602088013561234581612286565b9550604088013561235581612286565b94506060880135935061236a608089016122f9565b925060a0880135915060c0880135905092959891949750929550565b600080600080600080600060e0888a0312156123a157600080fd5b87356123ac81612286565b965060208801356123bc81612286565b9550604088013594506060880135935061236a608089016122f9565b600080604083850312156123eb57600080fd5b82356123f681612286565b946020939093013593505050565b60008083601f84011261241657600080fd5b50813567ffffffffffffffff81111561242e57600080fd5b60208301915083602082850101111561244657600080fd5b9250929050565b60008060006040848603121561246257600080fd5b833561246d81612286565b9250602084013567ffffffffffffffff81111561248957600080fd5b61249586828701612404565b9497909650939450505050565b6000806000806000608086880312156124ba57600080fd5b85356124c581612286565b945060208601356124d581612286565b935060408601359250606086013567ffffffffffffffff8111156124f857600080fd5b61250488828901612404565b969995985093965092949392505050565b6000806040838503121561252857600080fd5b823561253381612286565b9150602083013561254381612286565b809150509250929050565b6000806000806080858703121561256457600080fd5b843561256f81612286565b9350602085013561257f81612286565b9250604085013561258f81612286565b9396929550929360600135925050565b600181811c908216806125b357607f821691505b602082108114156125ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561260557600080fd5b815161160c81612286565b60006020828403121561262257600080fd5b5051919050565b60006020828403121561263b57600080fd5b8151801515811461160c57600080fd5b8183823760009101908152919050565b60006001600160a01b038089168352808816602084015280871660408401525084606083015260a060808301528260a0830152828460c0840137600060c0848401015260c0601f19601f850116830101905097965050505050505056fea2646970667358221220589a221d8b174737710c755745052e2f1667b39f8d95fad86ef93c86334ff97964736f6c634300080b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000057f1b40baf4d5708a15fea71e06841897cd2d262000000000000000000000000774681a648125d46f35017cf6cec43a41857254e45555200000000000000000000000000000000000000000000000000000000000000000000000000000000003231cb76718cdef2155fc47b5286d82e6eda273f
-----Decoded View---------------
Arg [0] : storage_ (address): 0x57f1B40BaF4D5708a15fEa71e06841897cd2d262
Arg [1] : validator (address): 0x774681A648125D46f35017cF6CEC43A41857254e
Arg [2] : ticker_ (bytes3): 0x455552
Arg [3] : frontend_ (address): 0x3231Cb76718CDeF2155FC47b5286d82e6eDA273f
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000057f1b40baf4d5708a15fea71e06841897cd2d262
Arg [1] : 000000000000000000000000774681a648125d46f35017cf6cec43a41857254e
Arg [2] : 4555520000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000003231cb76718cdef2155fc47b5286d82e6eda273f
Libraries Used
TokenStorageLib : 0xe0912ea0fe61ba97ad4f45a92b34e34643bbbb0cERC20Lib : 0xb912a741f60779390d789c3c5f78131b999493b5ERC677Lib : 0xf6d4568574c1de8f1eb002f58d1e5ecdf652b1d0MintableTokenLib : 0xb93a7f29e11f86469ea8d0e086c9993cdc148faaSmartTokenLib : 0x2ecb7d02c0bfd824d88f47e26602a6ae86148242
Deployed Bytecode Sourcemap
891:4979:24:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3916:81:26;3984:8;;-1:-1:-1;;;;;3984:8:26;3916:81;;;-1:-1:-1;;;;;178:55:31;;;160:74;;148:2;133:18;3916:81:26;;;;;;;;1316:18;;;:::i;:::-;;;;;;;:::i;5762:105:24:-;;;:::i;1818:120::-;;;;;;:::i;:::-;;:::i;:::-;;8323:87:26;;;:::i;:::-;;;1404:25:31;;;1392:2;1377:18;8323:87:26;1258:177:31;4865:137:26;;;;;;:::i;:::-;;:::i;:::-;;;1605:14:31;;1598:22;1580:41;;1568:2;1553:18;4865:137:26;1440:187:31;1081:39:24;;1119:1;1081:39;;1362:25:26;;;;;;1940:215:15;;;;;;:::i;:::-;;:::i;2201:120:28:-;;;;;;:::i;:::-;;:::i;4089:86:26:-;4164:5;;-1:-1:-1;;;;;4164:5:26;4089:86;;2695:317:24;;;;;;:::i;:::-;;:::i;9229:59:26:-;;;:::i;836:164:2:-;;;:::i;2579:250:15:-;;;;;;:::i;:::-;;:::i;1091:84:19:-;1161:7;;;;1091:84;;4273:128:26;;;;;;:::i;:::-;;:::i;8558:100::-;;;;;;:::i;:::-;;:::i;1022:111:18:-;;;:::i;7145:203:26:-;;;;;;:::i;:::-;;:::i;3030:177:15:-;;;;;;:::i;:::-;;:::i;9095:55:26:-;;;:::i;1055:20:24:-;;;;;;;;;;;;4299:66:31;4287:79;;;4269:98;;4257:2;4242:18;1055:20:24;4125:248:31;269:20:18;;;;;;;;-1:-1:-1;;;;;269:20:18;;;4569:173:26;;;;;;:::i;:::-;;:::i;5097:142::-;;;;;;:::i;:::-;;:::i;1338:20::-;;;:::i;5242:421:24:-;;;;;;:::i;:::-;;:::i;1441:111:15:-;;;;;;:::i;:::-;;:::i;5536:83:26:-;;;:::i;8889:129::-;;;;;;:::i;:::-;;:::i;3423:332:24:-;;;;;;:::i;:::-;;:::i;291:27:2:-;;;;;-1:-1:-1;;;;;291:27:2;;;4313:362:24;;;;;;:::i;:::-;;:::i;1619:117:15:-;;;;;;:::i;:::-;;:::i;5360:113:26:-;;;;;;:::i;:::-;;:::i;639::2:-;;;;;;:::i;:::-;;:::i;1316:18:26:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5762:105:24:-;5835:25;;;;;:10;:25;;;1404::31;5809:7:24;;5835:23;;;;1377:18:31;;5835:25:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5828:32;;5762:105;:::o;1818:120::-;1670:27:28;1686:10;1670:15;:27::i;:::-;1662:36;;;;;;1897:34:24::1;::::0;;;;:10:::1;:34;::::0;::::1;8170:25:31::0;-1:-1:-1;;;;;8231:55:31;;8211:18;;;8204:83;1897:23:24::1;::::0;::::1;::::0;8143:18:31;;1897:34:24::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;1818:120:::0;:::o;8323:87:26:-;8388:5;;:17;;;;;;;;8369:4;;-1:-1:-1;;;;;8388:5:26;;:15;;:17;;;;;;;;;;;;;;:5;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;4865:137::-;4958:8;;4925:4;;-1:-1:-1;;;;;4945:21:26;;;4958:8;;4945:21;;4944:53;;-1:-1:-1;;;;;;4971:26:26;;;;;;:15;:26;;;;;;;;4944:53;4937:60;4865:137;-1:-1:-1;;4865:137:26:o;1940:215:15:-;2082:4;2031:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;;;;;;;;;2061:6:15::1;1945:24:28;1961:7;1945:15;:24::i;:::-;1924:95;;;::::0;-1:-1:-1;;;1924:95:28;;9110:2:31;1924:95:28::1;::::0;::::1;9092:21:31::0;9149:2;9129:18;;;9122:30;9188:26;9168:18;;;9161:54;9232:18;;1924:95:28::1;8908:348:31::0;1924:95:28::1;2096:19:15::2;2112:2;2096:15;:19::i;:::-;2128:5;::::0;:22:::2;::::0;;;;-1:-1:-1;;;;;2128:5:15;;::::2;:22;::::0;::::2;9553:34:31::0;9623:15;;;9603:18;;;9596:43;9655:18;;;9648:34;;;2128:10:15::2;::::0;::::2;::::0;9465:18:31;;2128:22:15::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2121:29:::0;1940:215;-1:-1:-1;;;;;;1940:215:15:o;2201:120:28:-;-1:-1:-1;;;;;992:19:20;;2264:4:28;992:19:20;;;;;;;;;;;;;2287:27:28;888:128:20;2695:317:24;2899:4;2840:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;2874:6:24::1;1945:24:28;1961:7;1945:15;:24::i;:::-;1924:95;;;::::0;-1:-1:-1;;;1924:95:28;;9110:2:31;1924:95:28::1;::::0;::::1;9092:21:31::0;9149:2;9129:18;;;9122:30;9188:26;9168:18;;;9161:54;9232:18;;1924:95:28::1;8908:348:31::0;1924:95:28::1;2919:19:24::2;2935:2;2919:15;:19::i;:::-;2977:5;::::0;2955:50:::2;::::0;;;;-1:-1:-1;;;;;2977:5:24;;::::2;2955:50;::::0;::::2;10376:34:31::0;10446:15;;;10426:18;;;10419:43;10498:15;;;10478:18;;;10471:43;10530:18;;;10523:34;;;10606:4;10594:17;;10573:19;;;10566:46;10628:19;;;10621:35;;;10672:19;;;10665:35;;;2955:13:24::2;::::0;:21:::2;::::0;10287:19:31;;2955:50:24::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2948:57:::0;2695:317;-1:-1:-1;;;;;;;;;;2695:317:24:o;9229:59:26:-;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;9273:10:26::1;:8;:10::i;:::-;9229:59::o:0;836:164:2:-;471:12;;-1:-1:-1;;;;;471:12:2;457:10;:26;449:35;;;;;;925:12:::1;::::0;;918:5;897:41:::1;::::0;-1:-1:-1;;;;;925:12:2;;::::1;::::0;::::1;918:5:::0;;::::1;::::0;;::::1;::::0;897:41:::1;::::0;925:12:::1;::::0;897:41:::1;952:12;::::0;;;944:20;;-1:-1:-1;;944:20:2::1;952:12;-1:-1:-1::0;;;;;952:12:2;::::1;944:20;;::::0;;-1:-1:-1;;970:25:2::1;::::0;;836:164::o;2579:250:15:-;2767:4;2716:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;2746:6:15::1;1945:24:28;1961:7;1945:15;:24::i;:::-;1924:95;;;::::0;-1:-1:-1;;;1924:95:28;;9110:2:31;1924:95:28::1;::::0;::::1;9092:21:31::0;9149:2;9129:18;;;9122:30;9188:26;9168:18;;;9161:54;9232:18;;1924:95:28::1;8908:348:31::0;1924:95:28::1;2788:5:15::2;::::0;:36:::2;::::0;;;;-1:-1:-1;;;;;2788:5:15;;::::2;:36;::::0;::::2;11112:34:31::0;11182:15;;;11162:18;;;11155:43;11214:18;;;11207:34;;;11257:18;;;11250:34;;;11333:4;11321:17;;11300:19;;;11293:46;11355:19;;;11348:35;;;11399:19;;;11392:35;;;2788:10:15::2;::::0;::::2;::::0;11023:19:31;;2788:36:15::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;4273:128:26:-:0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;4350:8:26::1;::::0;4341:29:::1;::::0;-1:-1:-1;;;;;4341:29:26;;::::1;::::0;4350:8:::1;::::0;4341:29:::1;::::0;4350:8:::1;::::0;4341:29:::1;4376:8;:20:::0;;-1:-1:-1;;4376:20:26::1;-1:-1:-1::0;;;;;4376:20:26;;;::::1;::::0;;;::::1;::::0;;4273:128::o;8558:100::-;8632:5;;:21;;;;;-1:-1:-1;;;;;178:55:31;;;8632:21:26;;;160:74:31;8613:4:26;;8632:5;;:16;;133:18:31;;8632:21:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;1022:111:18:-;740:5;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;1098:5:::1;::::0;1079:25:::1;::::0;1098:5:::1;::::0;;::::1;-1:-1:-1::0;;;;;1098:5:18::1;::::0;1079:25:::1;::::0;;;::::1;1110:5;:18:::0;;-1:-1:-1;;1110:18:18::1;::::0;;1022:111::o;7145:203:26:-;7281:7;7242:6;2448:10;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;7305:5:26::2;::::0;:38:::2;::::0;;;;-1:-1:-1;;;;;7305:5:26;;::::2;:38;::::0;::::2;12104:34:31::0;12174:15;;;12154:18;;;12147:43;12226:15;;;12206:18;;;12199:43;12258:18;;;12251:34;;;7305:13:26::2;::::0;::::2;::::0;12015:19:31;;7305:38:26::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7298:45:::0;7145:203;-1:-1:-1;;;;;7145:203:26:o;3030:177:15:-;3157:4;3098:10;3132::::1;1945:24:28;1961:7;1945:15;:24::i;:::-;1924:95;;;::::0;-1:-1:-1;;;1924:95:28;;9110:2:31;1924:95:28::1;::::0;::::1;9092:21:31::0;9149:2;9129:18;;;9122:30;9188:26;9168:18;;;9161:54;9232:18;;1924:95:28::1;8908:348:31::0;1924:95:28::1;3178:5:15::2;::::0;:24:::2;::::0;;;;-1:-1:-1;;;;;3178:5:15;;::::2;:24;::::0;::::2;9553:34:31::0;9623:15;;;9603:18;;;9596:43;9655:18;;;9648:34;;;3178:10:15::2;::::0;::::2;::::0;9465:18:31;;3178:24:15::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;9095:55:26::0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;9137:8:26::1;:6;:8::i;4569:173::-:0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;4692:5:26::1;;4666:32;;;;;;;:::i;:::-;;::::0;;;;::::1;::::0;;;-1:-1:-1;;;;;4666:32:26;::::1;::::0;::::1;::::0;;;::::1;-1:-1:-1::0;;;;;;;4704:26:26::1;;::::0;;;:15:::1;:26;::::0;;;;:33;;-1:-1:-1;;4704:33:26::1;4733:4;4704:33;::::0;;4569:173::o;5097:142::-;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;5181:5:26::1;::::0;5165:33:::1;::::0;-1:-1:-1;;;;;5165:33:26;;::::1;::::0;5181:5:::1;::::0;5165:33:::1;::::0;5181:5:::1;::::0;5165:33:::1;5204:5;:30:::0;;-1:-1:-1;;5204:30:26::1;-1:-1:-1::0;;;;;5204:30:26;;;::::1;::::0;;;::::1;::::0;;5097:142::o;1338:20::-;;;;;;;:::i;5242:421:24:-;5476:4;5429:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;5504:39:24::2;::::0;-1:-1:-1;;;5504:39:24;;:10:::2;:39;::::0;::::2;12844:25:31::0;-1:-1:-1;;;;;12966:15:31;;;12946:18;;;12939:43;13018:15;;12998:18;;;12991:43;13050:18;;;13043:34;;;5504:19:24::2;::::0;::::2;::::0;12816::31;;5504:39:24::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5496:85;;;::::0;-1:-1:-1;;;5496:85:24;;13290:2:31;5496:85:24::2;::::0;::::2;13272:21:31::0;13329:2;13309:18;;;13302:30;13368:34;13348:18;;;13341:62;13439:3;13419:18;;;13412:31;13460:19;;5496:85:24::2;13088:397:31::0;5496:85:24::2;5598:58;5631:6;5639:2;5643:6;5651:4;;5598:32;:58::i;:::-;5591:65:::0;5242:421;-1:-1:-1;;;;;;;5242:421:24:o;1441:111:15:-;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;1516:31:15::1;1539:7;1516:22;:31::i;:::-;1441:111:::0;:::o;5536:83:26:-;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;5592:5:26::1;;;;;;;;;-1:-1:-1::0;;;;;5592:5:26::1;-1:-1:-1::0;;;;;5592:20:26::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;5536:83::o:0;8889:129::-;8982:5;;:31;;;;;-1:-1:-1;;;;;8982:5:26;;;:31;;;13782:34:31;13852:15;;;13832:18;;;13825:43;13904:15;;;13884:18;;;13877:43;8963:4:26;;8982:15;;;;13694:18:31;;8982:31:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8975:38;8889:129;-1:-1:-1;;;8889:129:26:o;3423:332:24:-;3588:4;3541:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;3616:39:24::2;::::0;-1:-1:-1;;;3616:39:24;;:10:::2;:39;::::0;::::2;12844:25:31::0;-1:-1:-1;;;;;12966:15:31;;;12946:18;;;12939:43;13018:15;;12998:18;;;12991:43;13050:18;;;13043:34;;;3616:19:24::2;::::0;::::2;::::0;12816::31;;3616:39:24::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3608:78;;;::::0;-1:-1:-1;;;3608:78:24;;14133:2:31;3608:78:24::2;::::0;::::2;14115:21:31::0;14172:2;14152:18;;;14145:30;14211:28;14191:18;;;14184:56;14257:18;;3608:78:24::2;13931:350:31::0;3608:78:24::2;3703:45;3729:6;3737:2;3741:6;3703:25;:45::i;4313:362::-:0;4496:4;4449:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;4524:37:24::2;::::0;-1:-1:-1;;;4524:37:24;;:10:::2;:37;::::0;::::2;12844:25:31::0;-1:-1:-1;;;;;12966:15:31;;;12946:18;;;12939:43;13018:15;;12998:18;;;12991:43;13050:18;;;13043:34;;;4524:19:24::2;::::0;::::2;::::0;12816::31;;4524:37:24::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4516:80;;;::::0;-1:-1:-1;;;4516:80:24;;14488:2:31;4516:80:24::2;::::0;::::2;14470:21:31::0;14527:2;14507:18;;;14500:30;14566:32;14546:18;;;14539:60;14616:18;;4516:80:24::2;14286:354:31::0;4516:80:24::2;4613:55;4643:6;4651:4;4657:2;4661:6;4613:29;:55::i;1619:117:15:-:0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;1697:34:15::1;1723:7;1697:25;:34::i;5360:113:26:-:0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;5435:5:26::1;::::0;:33:::1;::::0;;;;-1:-1:-1;;;;;178:55:31;;;5435:33:26::1;::::0;::::1;160:74:31::0;5435:5:26;;::::1;::::0;:23:::1;::::0;133:18:31;;5435:33:26::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;639:113:2::0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;724:12:2::1;:23:::0;;-1:-1:-1;;724:23:2::1;-1:-1:-1::0;;;;;724:23:2;;;::::1;::::0;;;::::1;::::0;;639:113::o;3443:379:26:-;-1:-1:-1;;;;;3508:18:26;;3500:51;;;;-1:-1:-1;;;3500:51:26;;14847:2:31;3500:51:26;;;14829:21:31;14886:2;14866:18;;;14859:30;14925:22;14905:18;;;14898:50;14965:18;;3500:51:26;14645:344:31;3500:51:26;-1:-1:-1;;;;;3565:19:26;;3579:4;3565:19;;3557:59;;;;-1:-1:-1;;;3557:59:26;;15196:2:31;3557:59:26;;;15178:21:31;15235:2;15215:18;;;15208:30;15274:29;15254:18;;;15247:57;15321:18;;3557:59:26;14994:351:31;3557:59:26;3644:5;;-1:-1:-1;;;;;3630:20:26;;;3644:5;;3630:20;;3622:63;;;;-1:-1:-1;;;3622:63:26;;15552:2:31;3622:63:26;;;15534:21:31;15591:2;15571:18;;;15564:30;15630:32;15610:18;;;15603:60;15680:18;;3622:63:26;15350:354:31;3622:63:26;3705:8;;-1:-1:-1;;;;;3699:14:26;;;3705:8;;3699:14;;3691:52;;;;-1:-1:-1;;;3691:52:26;;15911:2:31;3691:52:26;;;15893:21:31;15950:2;15930:18;;;15923:30;15989:27;15969:18;;;15962:55;16034:18;;3691:52:26;15709:349:31;3691:52:26;3757:14;3768:2;3757:10;:14::i;:::-;:23;3749:68;;;;-1:-1:-1;;;3749:68:26;;16265:2:31;3749:68:26;;;16247:21:31;;;16284:18;;;16277:30;16343:34;16323:18;;;16316:62;16395:18;;3749:68:26;16063:356:31;2103:117:19;1161:7;;;;1662:41;;;;-1:-1:-1;;;1662:41:19;;16626:2:31;1662:41:19;;;16608:21:31;16665:2;16645:18;;;16638:30;16704:22;16684:18;;;16677:50;16744:18;;1662:41:19;16424:344:31;1662:41:19;2161:7:::1;:15:::0;;-1:-1:-1;;2161:15:19::1;::::0;;2191:22:::1;719:10:3::0;2200:12:19::1;2191:22;::::0;-1:-1:-1;;;;;178:55:31;;;160:74;;148:2;133:18;2191:22:19::1;;;;;;;2103:117::o:0;1856:115::-;1161:7;;;;1404:9;1396:38;;;;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19;;;11622:21:31;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19;11438:340:31;1396:38:19;1925:4:::1;1915:14:::0;;-1:-1:-1;;1915:14:19::1;::::0;::::1;::::0;;1944:20:::1;719:10:3::0;1951:12:19::1;640:96:3::0;7772:468:26;8139:7;8100:6;2448:10;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;8156:19:26::2;8172:2;8156:15;:19::i;:::-;8188:5;::::0;:47:::2;::::0;;;;:21:::2;::::0;::::2;::::0;:47:::2;::::0;-1:-1:-1;;;;;8188:5:26::2;::::0;8210:6;;8218:2;;8222:6;;8230:4;;;;8188:47:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;2484:144:28:-:0;2552:27;:14;2571:7;-1:-1:-1;;;;;423:19:20;:12;:19;;;;;;;;;;;:26;;-1:-1:-1;;423:26:20;445:4;423:26;;;354:100;2552:27:28;2594;;-1:-1:-1;;;;;2594:27:28;;;;;;;;2484:144;:::o;5824:232:26:-;5968:7;5929:6;2448:10;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;5985:19:26::2;6001:2;5985:15;:19::i;:::-;6017:5;::::0;:34:::2;::::0;;;;-1:-1:-1;;;;;6017:5:26;;::::2;:34;::::0;::::2;12104::31::0;12174:15;;;12154:18;;;12147:43;12226:15;;;12206:18;;;12199:43;12258:18;;;12251:34;;;6017:14:26::2;::::0;::::2;::::0;12015:19:31;;6017:34:26::2;11783:508:31::0;6398:260:26;6560:7;6521:6;2448:10;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;6577:19:26::2;6593:2;6577:15;:19::i;:::-;6609:5;::::0;:44:::2;::::0;;;;-1:-1:-1;;;;;6609:5:26;;::::2;:44;::::0;::::2;17922:34:31::0;17992:15;;;17972:18;;;17965:43;18044:15;;;18024:18;;;18017:43;18096:15;;;18076:18;;;18069:43;18128:19;;;18121:35;;;6609:18:26::2;::::0;::::2;::::0;17833:19:31;;6609:44:26::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;2793:152:28::0;-1:-1:-1;;;;;591:19:20;;2864:14:28;591:19:20;;;;;;;;;;;:27;;-1:-1:-1;;591:27:20;;;2909:29:28;;;2864:14;2909:29;2793:152;:::o;245:597:31:-;357:4;386:2;415;404:9;397:21;447:6;441:13;490:6;485:2;474:9;470:18;463:34;515:1;525:140;539:6;536:1;533:13;525:140;;;634:14;;;630:23;;624:30;600:17;;;619:2;596:26;589:66;554:10;;525:140;;;683:6;680:1;677:13;674:91;;;753:1;748:2;739:6;728:9;724:22;720:31;713:42;674:91;-1:-1:-1;826:2:31;805:15;-1:-1:-1;;801:29:31;786:45;;;;833:2;782:54;;245:597;-1:-1:-1;;;245:597:31:o;847:154::-;-1:-1:-1;;;;;926:5:31;922:54;915:5;912:65;902:93;;991:1;988;981:12;1006:247;1065:6;1118:2;1106:9;1097:7;1093:23;1089:32;1086:52;;;1134:1;1131;1124:12;1086:52;1173:9;1160:23;1192:31;1217:5;1192:31;:::i;1632:456::-;1709:6;1717;1725;1778:2;1766:9;1757:7;1753:23;1749:32;1746:52;;;1794:1;1791;1784:12;1746:52;1833:9;1820:23;1852:31;1877:5;1852:31;:::i;:::-;1902:5;-1:-1:-1;1959:2:31;1944:18;;1931:32;1972:33;1931:32;1972:33;:::i;:::-;1632:456;;2024:7;;-1:-1:-1;;;2078:2:31;2063:18;;;;2050:32;;1632:456::o;2093:156::-;2159:20;;2219:4;2208:16;;2198:27;;2188:55;;2239:1;2236;2229:12;2188:55;2093:156;;;:::o;2254:807::-;2365:6;2373;2381;2389;2397;2405;2413;2466:3;2454:9;2445:7;2441:23;2437:33;2434:53;;;2483:1;2480;2473:12;2434:53;2522:9;2509:23;2541:31;2566:5;2541:31;:::i;:::-;2591:5;-1:-1:-1;2648:2:31;2633:18;;2620:32;2661:33;2620:32;2661:33;:::i;:::-;2713:7;-1:-1:-1;2772:2:31;2757:18;;2744:32;2785:33;2744:32;2785:33;:::i;:::-;2837:7;-1:-1:-1;2891:2:31;2876:18;;2863:32;;-1:-1:-1;2914:37:31;2946:3;2931:19;;2914:37;:::i;:::-;2904:47;;2998:3;2987:9;2983:19;2970:33;2960:43;;3050:3;3039:9;3035:19;3022:33;3012:43;;2254:807;;;;;;;;;;:::o;3066:734::-;3177:6;3185;3193;3201;3209;3217;3225;3278:3;3266:9;3257:7;3253:23;3249:33;3246:53;;;3295:1;3292;3285:12;3246:53;3334:9;3321:23;3353:31;3378:5;3353:31;:::i;:::-;3403:5;-1:-1:-1;3460:2:31;3445:18;;3432:32;3473:33;3432:32;3473:33;:::i;:::-;3525:7;-1:-1:-1;3579:2:31;3564:18;;3551:32;;-1:-1:-1;3630:2:31;3615:18;;3602:32;;-1:-1:-1;3653:37:31;3685:3;3670:19;;3653:37;:::i;3805:315::-;3873:6;3881;3934:2;3922:9;3913:7;3909:23;3905:32;3902:52;;;3950:1;3947;3940:12;3902:52;3989:9;3976:23;4008:31;4033:5;4008:31;:::i;:::-;4058:5;4110:2;4095:18;;;;4082:32;;-1:-1:-1;;;3805:315:31:o;4378:348::-;4430:8;4440:6;4494:3;4487:4;4479:6;4475:17;4471:27;4461:55;;4512:1;4509;4502:12;4461:55;-1:-1:-1;4535:20:31;;4578:18;4567:30;;4564:50;;;4610:1;4607;4600:12;4564:50;4647:4;4639:6;4635:17;4623:29;;4699:3;4692:4;4683:6;4675;4671:19;4667:30;4664:39;4661:59;;;4716:1;4713;4706:12;4661:59;4378:348;;;;;:::o;4731:546::-;4811:6;4819;4827;4880:2;4868:9;4859:7;4855:23;4851:32;4848:52;;;4896:1;4893;4886:12;4848:52;4935:9;4922:23;4954:31;4979:5;4954:31;:::i;:::-;5004:5;-1:-1:-1;5060:2:31;5045:18;;5032:32;5087:18;5076:30;;5073:50;;;5119:1;5116;5109:12;5073:50;5158:59;5209:7;5200:6;5189:9;5185:22;5158:59;:::i;:::-;4731:546;;5236:8;;-1:-1:-1;5132:85:31;;-1:-1:-1;;;;4731:546:31:o;5282:755::-;5379:6;5387;5395;5403;5411;5464:3;5452:9;5443:7;5439:23;5435:33;5432:53;;;5481:1;5478;5471:12;5432:53;5520:9;5507:23;5539:31;5564:5;5539:31;:::i;:::-;5589:5;-1:-1:-1;5646:2:31;5631:18;;5618:32;5659:33;5618:32;5659:33;:::i;:::-;5711:7;-1:-1:-1;5765:2:31;5750:18;;5737:32;;-1:-1:-1;5820:2:31;5805:18;;5792:32;5847:18;5836:30;;5833:50;;;5879:1;5876;5869:12;5833:50;5918:59;5969:7;5960:6;5949:9;5945:22;5918:59;:::i;:::-;5282:755;;;;-1:-1:-1;5282:755:31;;-1:-1:-1;5996:8:31;;5892:85;5282:755;-1:-1:-1;;;5282:755:31:o;6042:388::-;6110:6;6118;6171:2;6159:9;6150:7;6146:23;6142:32;6139:52;;;6187:1;6184;6177:12;6139:52;6226:9;6213:23;6245:31;6270:5;6245:31;:::i;:::-;6295:5;-1:-1:-1;6352:2:31;6337:18;;6324:32;6365:33;6324:32;6365:33;:::i;:::-;6417:7;6407:17;;;6042:388;;;;;:::o;6435:598::-;6521:6;6529;6537;6545;6598:3;6586:9;6577:7;6573:23;6569:33;6566:53;;;6615:1;6612;6605:12;6566:53;6654:9;6641:23;6673:31;6698:5;6673:31;:::i;:::-;6723:5;-1:-1:-1;6780:2:31;6765:18;;6752:32;6793:33;6752:32;6793:33;:::i;:::-;6845:7;-1:-1:-1;6904:2:31;6889:18;;6876:32;6917:33;6876:32;6917:33;:::i;:::-;6435:598;;;;-1:-1:-1;6969:7:31;;7023:2;7008:18;6995:32;;-1:-1:-1;;6435:598:31:o;7038:437::-;7117:1;7113:12;;;;7160;;;7181:61;;7235:4;7227:6;7223:17;7213:27;;7181:61;7288:2;7280:6;7277:14;7257:18;7254:38;7251:218;;;7325:77;7322:1;7315:88;7426:4;7423:1;7416:15;7454:4;7451:1;7444:15;7251:218;;7038:437;;;:::o;7701:251::-;7771:6;7824:2;7812:9;7803:7;7799:23;7795:32;7792:52;;;7840:1;7837;7830:12;7792:52;7872:9;7866:16;7891:31;7916:5;7891:31;:::i;8298:184::-;8368:6;8421:2;8409:9;8400:7;8396:23;8392:32;8389:52;;;8437:1;8434;8427:12;8389:52;-1:-1:-1;8460:16:31;;8298:184;-1:-1:-1;8298:184:31:o;9693:277::-;9760:6;9813:2;9801:9;9792:7;9788:23;9784:32;9781:52;;;9829:1;9826;9819:12;9781:52;9861:9;9855:16;9914:5;9907:13;9900:21;9893:5;9890:32;9880:60;;9936:1;9933;9926:12;12296:273;12481:6;12473;12468:3;12455:33;12437:3;12507:16;;12532:13;;;12507:16;12296:273;-1:-1:-1;12296:273:31:o;16773:795::-;17034:4;-1:-1:-1;;;;;17144:2:31;17136:6;17132:15;17121:9;17114:34;17196:2;17188:6;17184:15;17179:2;17168:9;17164:18;17157:43;17248:2;17240:6;17236:15;17231:2;17220:9;17216:18;17209:43;;17288:6;17283:2;17272:9;17268:18;17261:34;17332:3;17326;17315:9;17311:19;17304:32;17373:6;17367:3;17356:9;17352:19;17345:35;17431:6;17423;17417:3;17406:9;17402:19;17389:49;17488:1;17482:3;17473:6;17462:9;17458:22;17454:32;17447:43;17558:3;17551:2;17547:7;17542:2;17534:6;17530:15;17526:29;17515:9;17511:45;17507:55;17499:63;;16773:795;;;;;;;;;:::o
Swarm Source
ipfs://f0093be45eefa3b445c0e69fc35c23602399ad72137343475b219857f044da15
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.