POL Price: $0.622906 (+4.21%)
Gas: 38.9 GWei
 

Overview

Max Total Supply

42 MSFT

Holders

12

Total Transfers

-

Market

Price

$0.00 @ 0.000000 POL

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xa13e07B1...8727976bE
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
AssetToken

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 7 : AssetToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../interfaces/IAssetTokenData.sol";

/// @author Swarm Markets
/// @title AssetToken
/// @notice Main Asset Token Contract
contract AssetToken is ERC20, ReentrancyGuard {
    /// @dev Used to check access to functions as a kindof modifiers
    uint256 private constant ACTIVE_CONTRACT = 1 << 0;
    uint256 private constant UNFROZEN_CONTRACT = 1 << 1;
    uint256 private constant ONLY_ISSUER = 1 << 2;
    uint256 private constant ONLY_ISSUER_OR_GUARDIAN = 1 << 3;
    uint256 private constant ONLY_ISSUER_OR_AGENT = 1 << 4;

    uint8 private immutable _decimals;

    /// @dev This is a WAD on DSMATH representing 1
    uint256 public constant DECIMALS = 10 ** 18;
    /// @dev This is a proportion of 1 representing 100%, equal to a WAD
    uint256 public constant HUNDRED_PERCENT = 10 ** 18;

    /// @notice AssetTokenData Address
    address public assetTokenDataAddress;

    /// @notice Structure to hold the Mint Requests
    struct MintRequest {
        address destination;
        uint256 amount;
        string referenceTo;
        bool completed;
    }
    /// @notice Mint Requests mapping and last ID
    mapping(uint256 => MintRequest) public mintRequests;
    uint256 public mintRequestID;

    /// @notice Structure to hold the Redemption Requests
    struct RedemptionRequest {
        address sender;
        string receipt;
        uint256 assetTokenAmount;
        uint256 underlyingAssetAmount;
        bool completed;
        bool fromStake;
        string approveTxID;
        address canceledBy;
    }
    /// @notice Redemption Requests mapping and last ID
    mapping(uint256 => RedemptionRequest) public redemptionRequests;
    uint256 public redemptionRequestID;

    /// @notice stakedRedemptionRequests is map from requester to request ID
    /// @notice exists to detect that sender already has request from stake function
    mapping(address => uint256) public stakedRedemptionRequests;

    /// @notice mapping to hold each user safeguardStake amoun
    mapping(address => uint256) public safeguardStakes;

    /// @notice sum of the total stakes amounts
    uint256 public totalStakes;

    /// @notice the percetage (on 18 digits)
    /// @notice if this gets overgrown the contract change state
    uint256 public statePercent;

    /// @notice know your asset string
    string public kya;

    /// @notice minimum Redemption Amount (in Asset token value)
    uint256 public minimumRedemptionAmount;

    /// @notice Emitted when the address of the asset token data is set
    event AssetTokenDataChanged(address indexed _oldAddress, address indexed _newAddress, address indexed _caller);

    /// @notice Emitted when kya string is set
    event KyaChanged(string _kya, address indexed _caller);

    /// @notice Emitted when minimumRedemptionAmount is set
    event MinimumRedemptionAmountChanged(uint256 _newAmount, address indexed _caller);

    /// @notice Emitted when a mint request is requested
    event MintRequested(
        uint256 indexed _mintRequestID,
        address indexed _destination,
        uint256 _amount,
        address indexed _caller
    );

    /// @notice Emitted when a mint request gets approved
    event MintApproved(
        uint256 indexed _mintRequestID,
        address indexed _destination,
        uint256 _amountMinted,
        address indexed _caller
    );

    /// @notice Emitted when a redemption request is requested
    event RedemptionRequested(
        uint256 indexed _redemptionRequestID,
        uint256 _assetTokenAmount,
        uint256 _underlyingAssetAmount,
        bool _fromStake,
        address indexed _caller
    );

    /// @notice Emitted when a redemption request is cancelled
    event RedemptionCanceled(
        uint256 indexed _redemptionRequestID,
        address indexed _requestReceiver,
        string _motive,
        address indexed _caller
    );

    /// @notice Emitted when a redemption request is approved
    event RedemptionApproved(
        uint256 indexed _redemptionRequestID,
        uint256 _assetTokenAmount,
        uint256 _underlyingAssetAmount,
        address indexed _requestReceiver,
        address indexed _caller
    );

    /// @notice Emitted when the token gets bruned
    event TokenBurned(uint256 _amount, address indexed _caller);

    /// @notice Emitted when the contract change to safeguard
    event SafeguardUnstaked(uint256 _amount, address indexed _caller);

    /// @notice Constructor: sets the state variables and provide proper checks to deploy
    /// @param _assetTokenData the asset token data contract address
    /// @param _statePercent the state percent to check the safeguard convertion
    /// @param _kya verification link
    /// @param _minimumRedemptionAmount less than this value is not allowed
    /// @param _name of the token
    /// @param _symbol of the token
    constructor(
        address _assetTokenData,
        uint256 _statePercent,
        string memory _kya,
        uint256 _minimumRedemptionAmount,
        string memory _name,
        string memory _symbol
    ) ERC20(_name, _symbol) {
        require(_assetTokenData != address(0), "AssetToken: assetTokenData is address 0");
        require(_statePercent > 0, "AssetToken: statePercent must be > 0");
        require(_statePercent <= HUNDRED_PERCENT, "AssetToken: statePercent <= HUNDRED_PERCENT");
        require(bytes(_kya).length > 3, "AssetToken: incorrect kya passed");

        // IT IS THE WAD EQUIVALENT USED IN DSMATH
        _decimals = 18;
        assetTokenDataAddress = _assetTokenData;
        statePercent = _statePercent;
        kya = _kya;
        minimumRedemptionAmount = _minimumRedemptionAmount;
    }

    /// @notice kindof modifier to frist-check data on functions
    /// @param modifiers an array containing the modifiers to check (the enums)
    function checkAccessToFunction(uint256 modifiers) internal view {
        bool found;
        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
        if (modifiers & ACTIVE_CONTRACT != 0) {
            assetTknDtaContract.onlyActiveContract(address(this));
            found = true;
        }
        if (modifiers & UNFROZEN_CONTRACT != 0) {
            assetTknDtaContract.onlyUnfrozenContract(address(this));
            found = true;
        }
        if (modifiers & ONLY_ISSUER != 0) {
            assetTknDtaContract.onlyIssuer(address(this), _msgSender());
            found = true;
        }
        if (modifiers & ONLY_ISSUER_OR_GUARDIAN != 0) {
            assetTknDtaContract.onlyIssuerOrGuardian(address(this), _msgSender());
            found = true;
        }
        if (modifiers & ONLY_ISSUER_OR_AGENT != 0) {
            assetTknDtaContract.onlyIssuerOrAgent(address(this), _msgSender());
            found = true;
        }
        require(found, "AssetToken: access not found");
    }

    /// @notice Hook to be executed before every transfer and mint
    /// @notice This overrides the ERC20 defined function
    /// @param _from the sender
    /// @param _to the receipent
    /// @param _amount the amount (it is not used  but needed to be defined to override)
    function _beforeTokenTransfer(address _from, address _to, uint256 _amount) internal virtual override {
        //  on safeguard the only available transfers are from allowed addresses and guardian
        //  or from an authorized user to this contract
        //  address(this) is added as the _from for approving redemption (burn)
        //  address(this) is added as the _to for requesting redemption (transfer to this contract)
        //  address(0) is added to the condition to allow burn on safeguard
        checkAccessToFunction(UNFROZEN_CONTRACT);
        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);

        if (assetTknDtaContract.isOnSafeguard(address(this))) {
            /// @dev  State is SAFEGUARD
            if (
                // receiver is NOT this contract AND sender is NOT this contract AND sender is NOT guardian
                _to != address(this) &&
                _from != address(this) &&
                _from != assetTknDtaContract.getGuardian(address(this))
            ) {
                require(
                    assetTknDtaContract.isAllowedTransferOnSafeguard(address(this), _from),
                    "AssetToken: beforeTokenTransfer: not allowed (onSafeguard)"
                );
            } else {
                require(
                    assetTknDtaContract.mustBeAuthorizedHolders(address(this), _from, _to, _amount),
                    "AssetToken: beforeTokenTransfer: not authorized (onActive)"
                );
            }
        } else {
            /// @dev State is ACTIVE
            // this is mint or transfer
            // mint signature: ==> _beforeTokenTransfer(address(0), account, amount);
            // burn signature: ==> _beforeTokenTransfer(account, address(0), amount);
            require(
                assetTknDtaContract.mustBeAuthorizedHolders(address(this), _from, _to, _amount),
                "AssetToken: beforeTokenTransfer: not authorized (onActive)"
            );
        }

        super._beforeTokenTransfer(_from, _to, _amount);
    }

    /// @notice Sets Asset Token Data Address
    /// @param _newAddress value to be set
    function setAssetTokenData(address _newAddress) external {
        checkAccessToFunction(UNFROZEN_CONTRACT | ONLY_ISSUER_OR_GUARDIAN);
        require(_newAddress != address(0), "AssetToken: newAddress is address 0");
        emit AssetTokenDataChanged(assetTokenDataAddress, _newAddress, _msgSender());
        assetTokenDataAddress = _newAddress;
    }

    /// @notice Sets the verification link
    /// @param _kya value to be set
    function setKya(string calldata _kya) external {
        checkAccessToFunction(ONLY_ISSUER_OR_GUARDIAN | UNFROZEN_CONTRACT);
        require(bytes(_kya).length > 3, "AssetToken: incorrect kya passed");
        emit KyaChanged(_kya, _msgSender());
        kya = _kya;
    }

    /// @notice Sets the _minimumRedemptionAmount
    /// @param _minimumRedemptionAmount value to be set
    function setMinimumRedemptionAmount(uint256 _minimumRedemptionAmount) external {
        checkAccessToFunction(ONLY_ISSUER_OR_GUARDIAN | UNFROZEN_CONTRACT);
        emit MinimumRedemptionAmountChanged(_minimumRedemptionAmount, _msgSender());
        minimumRedemptionAmount = _minimumRedemptionAmount;
    }

    /// @notice Freeze the contract
    function freezeContract() external {
        checkAccessToFunction(ONLY_ISSUER_OR_GUARDIAN);
        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
        require(!assetTknDtaContract.isContractFrozen(address(this)), "AssetToken: contract is frozen");
        require(assetTknDtaContract.freezeContract(address(this)), "AssetToken: freezing failed");
    }

    /// @notice unfreeze the contract
    function unfreezeContract() external {
        checkAccessToFunction(ONLY_ISSUER_OR_GUARDIAN);
        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
        require(assetTknDtaContract.isContractFrozen(address(this)), "AssetToken: contract is not frozen");
        require(assetTknDtaContract.unfreezeContract(address(this)), "AssetToken: unfreezing failed");
    }

    /// @notice Requests a mint to the caller
    /// @param _amount the amount to mint in asset token format
    /// @return uint256 request ID to be referenced in the mapping
    function requestMint(uint256 _amount) external returns (uint256) {
        return _requestMint(_amount, _msgSender());
    }

    /// @notice Requests a mint to the _destination address
    /// @param _amount the amount to mint in asset token format
    /// @param _destination the receiver of the tokens
    /// @return uint256 request ID to be referenced in the mapping
    function requestMint(uint256 _amount, address _destination) external returns (uint256) {
        return _requestMint(_amount, _destination);
    }

    /// @notice Performs the Mint Request to the destination address
    /// @param _amount entered in the external functions
    /// @param _destination the receiver of the tokens
    /// @return uint256 request ID to be referenced in the mapping
    function _requestMint(uint256 _amount, address _destination) private returns (uint256) {
        checkAccessToFunction(ACTIVE_CONTRACT | UNFROZEN_CONTRACT | ONLY_ISSUER_OR_AGENT);
        require(_amount > 0, "AssetToken: amount must be > 0");

        mintRequestID++;
        emit MintRequested(mintRequestID, _destination, _amount, _msgSender());

        mintRequests[mintRequestID] = MintRequest(_destination, _amount, "", false);

        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
        if (_msgSender() == assetTknDtaContract.getIssuer(address(this))) {
            approveMint(mintRequestID, "IssuerMint");
        }
        return mintRequestID;
    }

    /// @notice Approves the Mint Request
    /// @param _mintRequestID the ID to be referenced in the mapping
    /// @param _referenceTo reference comment for the issuer
    function approveMint(uint256 _mintRequestID, string memory _referenceTo) public nonReentrant {
        checkAccessToFunction(ACTIVE_CONTRACT | ONLY_ISSUER);
        require(mintRequests[_mintRequestID].destination != address(0), "AssetToken: requestID does not exist");
        require(!mintRequests[_mintRequestID].completed, "AssetToken: request is completed");

        mintRequests[_mintRequestID].completed = true;
        mintRequests[_mintRequestID].referenceTo = _referenceTo;

        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
        assetTknDtaContract.update(address(this));
        uint256 currentRate = assetTknDtaContract.getCurrentRate(address(this));

        uint256 amountToMint = (mintRequests[_mintRequestID].amount * (DECIMALS)) / (currentRate);
        emit MintApproved(_mintRequestID, mintRequests[_mintRequestID].destination, amountToMint, _msgSender());

        _mint(mintRequests[_mintRequestID].destination, amountToMint);
    }

    /// @notice Requests an amount of assetToken Redemption
    /// @param _assetTokenAmount the amount of Asset Token to be redeemed
    /// @param _destination the off chain hash of the redemption transaction
    /// @return uint256 redemptionRequest ID to be referenced in the mapping
    function requestRedemption(
        uint256 _assetTokenAmount,
        string memory _destination
    ) external nonReentrant returns (uint256) {
        require(_assetTokenAmount > 0, "AssetToken: assetTokenAmount must be > 0");
        require(balanceOf(_msgSender()) >= _assetTokenAmount, "AssetToken: caller has insufficient funds");

        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
        address issuer = assetTknDtaContract.getIssuer(address(this));
        address guardian = assetTknDtaContract.getGuardian(address(this));
        bool isOnSafeguard = assetTknDtaContract.isOnSafeguard(address(this));

        if ((!isOnSafeguard && _msgSender() != issuer) || (isOnSafeguard && _msgSender() != guardian)) {
            require(
                _assetTokenAmount >= minimumRedemptionAmount,
                "AssetToken: minimumRedemptionAmount not reached yet"
            );
        }

        assetTknDtaContract.update(address(this));
        uint256 currentRate = assetTknDtaContract.getCurrentRate(address(this));
        uint256 underlyingAssetAmount = (_assetTokenAmount * (currentRate)) / (DECIMALS);

        redemptionRequestID++;
        emit RedemptionRequested(redemptionRequestID, _assetTokenAmount, underlyingAssetAmount, false, _msgSender());

        redemptionRequests[redemptionRequestID] = RedemptionRequest(
            _msgSender(),
            _destination,
            _assetTokenAmount,
            underlyingAssetAmount,
            false,
            false,
            "",
            address(0)
        );

        /// @dev make the transfer to the contract for the amount requested (18 digits)
        _transfer(_msgSender(), address(this), _assetTokenAmount);

        /// @dev approve instantly when called by issuer or guardian
        if ((!isOnSafeguard && _msgSender() == issuer) || (isOnSafeguard && _msgSender() == guardian)) {
            approveRedemption(redemptionRequestID, "AutomaticRedemptionApproval");
        }

        return redemptionRequestID;
    }

    /// @notice Approves the Redemption Requests
    /// @param _redemptionRequestID redemption request ID to be referenced in the mapping
    /// @param _motive motive of the cancelation
    function cancelRedemptionRequest(uint256 _redemptionRequestID, string memory _motive) external {
        require(
            redemptionRequests[_redemptionRequestID].sender != address(0),
            "AssetToken: redemptionRequestID does not exist"
        );
        require(
            redemptionRequests[_redemptionRequestID].canceledBy == address(0),
            "AssetToken: redemption has been cancelled"
        );
        require(!redemptionRequests[_redemptionRequestID].completed, "AssetToken: redemption already completed");
        require(!redemptionRequests[_redemptionRequestID].fromStake, "AssetToken: staked request - unstake to redeem");
        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
        if (_msgSender() != redemptionRequests[_redemptionRequestID].sender) {
            // not owner of the redemption so guardian or issuer should be the caller
            assetTknDtaContract.onlyIssuerOrGuardian(address(this), _msgSender());
        }

        uint256 refundAmount = redemptionRequests[_redemptionRequestID].assetTokenAmount;
        emit RedemptionCanceled(
            _redemptionRequestID,
            redemptionRequests[_redemptionRequestID].sender,
            _motive,
            _msgSender()
        );

        redemptionRequests[_redemptionRequestID].assetTokenAmount = 0;
        redemptionRequests[_redemptionRequestID].underlyingAssetAmount = 0;
        redemptionRequests[_redemptionRequestID].canceledBy = _msgSender();

        _transfer(address(this), redemptionRequests[_redemptionRequestID].sender, refundAmount);
    }

    /// @notice Approves the Redemption Requests
    /// @param _redemptionRequestID redemption request ID to be referenced in the mapping
    /// @param _approveTxID the transaction ID
    function approveRedemption(uint256 _redemptionRequestID, string memory _approveTxID) public {
        checkAccessToFunction(ONLY_ISSUER_OR_GUARDIAN);
        require(
            redemptionRequests[_redemptionRequestID].canceledBy == address(0),
            "AssetToken: redemptionRequestID has been cancelled"
        );
        require(
            redemptionRequests[_redemptionRequestID].sender != address(0),
            "AssetToken: redemptionRequestID is incorrect"
        );
        require(!redemptionRequests[_redemptionRequestID].completed, "AssetToken: redemptionRequestID completed");

        if (redemptionRequests[_redemptionRequestID].fromStake) {
            IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
            require(
                assetTknDtaContract.isOnSafeguard(address(this)),
                "AssetToken: contract is active (not onSafeguard)"
            );
        }

        emit RedemptionApproved(
            _redemptionRequestID,
            redemptionRequests[_redemptionRequestID].assetTokenAmount,
            redemptionRequests[_redemptionRequestID].underlyingAssetAmount,
            redemptionRequests[_redemptionRequestID].sender,
            _msgSender()
        );
        redemptionRequests[_redemptionRequestID].completed = true;
        redemptionRequests[_redemptionRequestID].approveTxID = _approveTxID;

        // burn tokens from the contract
        _burn(address(this), redemptionRequests[_redemptionRequestID].assetTokenAmount);
    }

    /// @notice Burns a certain amount of tokens
    /// @param _amount qty of assetTokens to be burned
    function burn(uint256 _amount) external {
        emit TokenBurned(_amount, _msgSender());
        _burn(_msgSender(), _amount);
    }

    /// @notice Performs the Safeguard Stake
    /// @param _amount the assetToken amount to be staked
    /// @param _receipt the off chain hash of the redemption transaction
    function safeguardStake(uint256 _amount, string calldata _receipt) external nonReentrant {
        checkAccessToFunction(ACTIVE_CONTRACT);
        require(balanceOf(_msgSender()) >= _amount, "AssetToken: caller has insufficient funds");

        safeguardStakes[_msgSender()] = safeguardStakes[_msgSender()] + _amount;
        totalStakes = totalStakes + (_amount);
        uint256 stakedPercent = (totalStakes * (HUNDRED_PERCENT)) / (totalSupply());

        IAssetTokenData assetTknDtaContract = IAssetTokenData(assetTokenDataAddress);
        if (stakedPercent >= statePercent) {
            require(assetTknDtaContract.setContractToSafeguard(address(this)), "AssetToken: error on safeguard change");
            /// @dev now the contract is on safeguard
        }

        uint256 _requestID = stakedRedemptionRequests[_msgSender()];
        if (_requestID == 0) {
            /// @dev zero means that it's new request
            redemptionRequestID++;
            redemptionRequests[redemptionRequestID] = RedemptionRequest(
                _msgSender(),
                _receipt,
                _amount,
                0,
                false,
                true,
                "",
                address(0)
            );

            stakedRedemptionRequests[_msgSender()] = redemptionRequestID;
            _requestID = redemptionRequestID;
        } else {
            /// @dev non zero means the request already exist and need only add amount
            redemptionRequests[_requestID].assetTokenAmount =
                redemptionRequests[_requestID].assetTokenAmount +
                (_amount);
        }

        emit RedemptionRequested(
            _requestID,
            redemptionRequests[_requestID].assetTokenAmount,
            redemptionRequests[_requestID].underlyingAssetAmount,
            true,
            _msgSender()
        );
        _transfer(_msgSender(), address(this), _amount);
    }

    /// @notice Calls to UnStake all the funds
    function safeguardUnstake() external {
        _safeguardUnstake(safeguardStakes[_msgSender()]);
    }

    /// @notice Calls to UnStake with a certain amount
    /// @param _amount to be unStaked in asset token
    function safeguardUnstake(uint256 _amount) external {
        _safeguardUnstake(_amount);
    }

    /// @notice Performs the UnStake with a certain amount
    /// @param _amount to be unStaked in asset token
    function _safeguardUnstake(uint256 _amount) private {
        checkAccessToFunction(ACTIVE_CONTRACT | UNFROZEN_CONTRACT);
        require(_amount > 0, "AssetToken: amount must be > 0");
        require(safeguardStakes[_msgSender()] >= _amount, "AssetToken: amount exceeds staked");

        emit SafeguardUnstaked(_amount, _msgSender());
        safeguardStakes[_msgSender()] = safeguardStakes[_msgSender()] - (_amount);
        totalStakes = totalStakes - (_amount);

        uint256 _requestID = stakedRedemptionRequests[_msgSender()];
        redemptionRequests[_requestID].assetTokenAmount = redemptionRequests[_requestID].assetTokenAmount - _amount;

        _transfer(address(this), _msgSender(), _amount);
    }

    function decimals() public view virtual override returns (uint8) {
        return _decimals;
    }
}

File 2 of 7 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 3 of 7 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 4 of 7 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 5 of 7 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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.
     *
     * IMPORTANT: 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 `from` to `to` 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 from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 6 of 7 : Context.sol
// 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;
    }
}

File 7 of 7 : IAssetTokenData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/// @author Swarm Markets
/// @title
/// @notice
/// @notice

interface IAssetTokenData {
    function getIssuer(address _tokenAddress) external view returns (address);

    function getGuardian(address _tokenAddress) external view returns (address);

    function setContractToSafeguard(address _tokenAddress) external returns (bool);

    function freezeContract(address _tokenAddress) external returns (bool);

    function unfreezeContract(address _tokenAddress) external returns (bool);

    function isOnSafeguard(address _tokenAddress) external view returns (bool);

    function isContractFrozen(address _tokenAddress) external view returns (bool);

    function beforeTokenTransfer(address, address) external;

    function onlyStoredToken(address _tokenAddress) external view;

    function onlyActiveContract(address _tokenAddress) external view;

    function onlyUnfrozenContract(address _tokenAddress) external view;

    function onlyIssuer(address _tokenAddress, address _functionCaller) external view;

    function onlyIssuerOrGuardian(address _tokenAddress, address _functionCaller) external view;

    function onlyIssuerOrAgent(address _tokenAddress, address _functionCaller) external view;

    function checkIfTransactionIsAllowed(
        address _caller,
        address _from,
        address _to,
        address _tokenAddress,
        bytes4 _operation,
        bytes calldata _data
    ) external view returns (bool);

    function mustBeAuthorizedHolders(
        address _tokenAddress,
        address _from,
        address _to,
        uint256 _amount
    ) external returns (bool);

    function update(address _tokenAddress) external;

    function getCurrentRate(address _tokenAddress) external view returns (uint256);

    function getInterestRate(address _tokenAddress) external view returns (uint256, bool);

    function hasRole(bytes32 role, address account) external view returns (bool);

    function isAllowedTransferOnSafeguard(address _tokenAddress, address _account) external view returns (bool);

    function registerAssetToken(address _tokenAddress, address _issuer, address _guardian) external returns (bool);

    function transferIssuer(address _tokenAddress, address _newIssuer) external;

    function setInterestRate(address _tokenAddress, uint256 _interestRate, bool _positiveInterest) external;

    function addAgent(address _tokenAddress, address _newAgent) external;

    function removeAgent(address _tokenAddress, address _agent) external;

    function addMemberToBlacklist(address _tokenAddress, address _account) external;

    function removeMemberFromBlacklist(address _tokenAddress, address _account) external;

    function allowTransferOnSafeguard(address _tokenAddress, address _account) external;

    function preventTransferOnSafeguard(address _tokenAddress, address _account) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_assetTokenData","type":"address"},{"internalType":"uint256","name":"_statePercent","type":"uint256"},{"internalType":"string","name":"_kya","type":"string"},{"internalType":"uint256","name":"_minimumRedemptionAmount","type":"uint256"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_oldAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_newAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"AssetTokenDataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_kya","type":"string"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"KyaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"MinimumRedemptionAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_mintRequestID","type":"uint256"},{"indexed":true,"internalType":"address","name":"_destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amountMinted","type":"uint256"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"MintApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_mintRequestID","type":"uint256"},{"indexed":true,"internalType":"address","name":"_destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"MintRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_redemptionRequestID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_assetTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_underlyingAssetAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"_requestReceiver","type":"address"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"RedemptionApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_redemptionRequestID","type":"uint256"},{"indexed":true,"internalType":"address","name":"_requestReceiver","type":"address"},{"indexed":false,"internalType":"string","name":"_motive","type":"string"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"RedemptionCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_redemptionRequestID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_assetTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_underlyingAssetAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_fromStake","type":"bool"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"RedemptionRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"SafeguardUnstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"_caller","type":"address"}],"name":"TokenBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HUNDRED_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintRequestID","type":"uint256"},{"internalType":"string","name":"_referenceTo","type":"string"}],"name":"approveMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_redemptionRequestID","type":"uint256"},{"internalType":"string","name":"_approveTxID","type":"string"}],"name":"approveRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assetTokenDataAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_redemptionRequestID","type":"uint256"},{"internalType":"string","name":"_motive","type":"string"}],"name":"cancelRedemptionRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freezeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"kya","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumRedemptionAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintRequestID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mintRequests","outputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"referenceTo","type":"string"},{"internalType":"bool","name":"completed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionRequestID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"redemptionRequests","outputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"receipt","type":"string"},{"internalType":"uint256","name":"assetTokenAmount","type":"uint256"},{"internalType":"uint256","name":"underlyingAssetAmount","type":"uint256"},{"internalType":"bool","name":"completed","type":"bool"},{"internalType":"bool","name":"fromStake","type":"bool"},{"internalType":"string","name":"approveTxID","type":"string"},{"internalType":"address","name":"canceledBy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"requestMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_destination","type":"address"}],"name":"requestMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetTokenAmount","type":"uint256"},{"internalType":"string","name":"_destination","type":"string"}],"name":"requestRedemption","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_receipt","type":"string"}],"name":"safeguardStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"safeguardStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"safeguardUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"safeguardUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAddress","type":"address"}],"name":"setAssetTokenData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_kya","type":"string"}],"name":"setKya","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumRedemptionAmount","type":"uint256"}],"name":"setMinimumRedemptionAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakedRedemptionRequests","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"statePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unfreezeContract","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b5060405162003c2838038062003c288339810160408190526200003491620002ee565b8181600362000044838262000441565b50600462000053828262000441565b50506001600555506001600160a01b038616620000c75760405162461bcd60e51b815260206004820152602760248201527f4173736574546f6b656e3a206173736574546f6b656e446174612069732061646044820152660647265737320360cc1b60648201526084015b60405180910390fd5b60008511620001255760405162461bcd60e51b8152602060048201526024808201527f4173736574546f6b656e3a20737461746550657263656e74206d7573742062656044820152630203e20360e41b6064820152608401620000be565b670de0b6b3a7640000851115620001935760405162461bcd60e51b815260206004820152602b60248201527f4173736574546f6b656e3a20737461746550657263656e74203c3d2048554e4460448201526a14915117d4115490d1539560aa1b6064820152608401620000be565b6003845111620001e65760405162461bcd60e51b815260206004820181905260248201527f4173736574546f6b656e3a20696e636f7272656374206b7961207061737365646044820152606401620000be565b6012608052600680546001600160a01b0319166001600160a01b038816179055600e859055600f62000219858262000441565b505050601055506200050d915050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200025157600080fd5b81516001600160401b03808211156200026e576200026e62000229565b604051601f8301601f19908116603f0116810190828211818310171562000299576200029962000229565b81604052838152602092508683858801011115620002b657600080fd5b600091505b83821015620002da5785820183015181830184015290820190620002bb565b600093810190920192909252949350505050565b60008060008060008060c087890312156200030857600080fd5b86516001600160a01b03811681146200032057600080fd5b6020880151604089015191975095506001600160401b03808211156200034557600080fd5b620003538a838b016200023f565b95506060890151945060808901519150808211156200037157600080fd5b6200037f8a838b016200023f565b935060a08901519150808211156200039657600080fd5b50620003a589828a016200023f565b9150509295509295509295565b600181811c90821680620003c757607f821691505b602082108103620003e857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200043c57600081815260208120601f850160051c81016020861015620004175750805b601f850160051c820191505b81811015620004385782815560010162000423565b5050505b505050565b81516001600160401b038111156200045d576200045d62000229565b62000475816200046e8454620003b2565b84620003ee565b602080601f831160018114620004ad5760008415620004945750858301515b600019600386901b1c1916600185901b17855562000438565b600085815260208120601f198616915b82811015620004de57888601518255948401946001909101908401620004bd565b5085821015620004fd5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6080516136ff6200052960003960006102fb01526136ff6000f3fe608060405234801561001057600080fd5b506004361061023d5760003560e01c8063793f255c1161013b578063dc174960116100b8578063ee7611891161007c578063ee761189146104ec578063f15965d9146104ff578063f4917dd314610512578063f634d4e81461051a578063ff322ba11461053a57600080fd5b8063dc1749601461048d578063dd62ed3e146104a0578063e0f486ef146104b3578063e1a0cc6f146104bc578063ea4a1d5c146104e357600080fd5b8063a457c2d7116100ff578063a457c2d71461044d578063a584a9b514610460578063a9059cbb14610468578063bad9d0e41461047b578063bf9befb11461048457600080fd5b8063793f255c146103e157806386511595146103f45780638660970c1461040757806395d89b411461043257806398d9423e1461043a57600080fd5b8063377a1a62116101c957806349733d041161018d57806349733d041461037f5780634ef1ccd1146103925780635605a998146103a55780636ed93dd0146102e557806370a08231146103b857600080fd5b8063377a1a6214610325578063395093511461032e5780633fc7293a14610341578063424e65751461034957806342966c681461036c57600080fd5b8063189d1e0b11610210578063189d1e0b146102aa5780631d0b56af146102b257806323b872dd146102d25780632e0f2625146102e5578063313ce567146102f457600080fd5b806306fdde0314610242578063095ea7b3146102605780630ac7f4e61461028357806318160ddd14610298575b600080fd5b61024a61054d565b6040516102579190612fc8565b60405180910390f35b61027361026e366004612ff0565b6105df565b6040519015158152602001610257565b61029661029136600461301c565b6105f9565b005b6002545b604051908152602001610257565b6102966106c9565b61029c6102c036600461301c565b600c6020526000908152604090205481565b6102736102e0366004613039565b6106e4565b61029c670de0b6b3a764000081565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610257565b61029c60085481565b61027361033c366004612ff0565b610708565b61024a61072a565b61035c61035736600461307a565b6107b8565b6040516102579493929190613093565b61029661037a36600461307a565b610876565b61029c61038d36600461307a565b6108b8565b6102966103a036600461307a565b6108c4565b6102966103b336600461307a565b610908565b61029c6103c636600461301c565b6001600160a01b031660009081526020819052604090205490565b6102966103ef366004613116565b610911565b61029c610402366004613178565b610cd0565b60065461041a906001600160a01b031681565b6040516001600160a01b039091168152602001610257565b61024a611257565b610296610448366004613233565b611266565b61027361045b366004612ff0565b611310565b61029661138b565b610273610476366004612ff0565b611506565b61029c600e5481565b61029c600d5481565b61029661049b366004613178565b611514565b61029c6104ae366004613275565b6117ab565b61029c60105481565b6104cf6104ca36600461307a565b6117d6565b6040516102579897969594939291906132ae565b61029c600a5481565b6102966104fa366004613178565b611944565b61029661050d366004613178565b611c4f565b610296611f35565b61029c61052836600461301c565b600b6020526000908152604090205481565b61029c61054836600461331d565b6120ba565b60606003805461055c90613342565b80601f016020809104026020016040519081016040528092919081815260200182805461058890613342565b80156105d55780601f106105aa576101008083540402835291602001916105d5565b820191906000526020600020905b8154815290600101906020018083116105b857829003601f168201915b5050505050905090565b6000336105ed8185856120cd565b60019150505b92915050565b610603600a6121f1565b6001600160a01b03811661066a5760405162461bcd60e51b815260206004820152602360248201527f4173736574546f6b656e3a206e6577416464726573732069732061646472657360448201526207320360ec1b60648201526084015b60405180910390fd5b60065460405133916001600160a01b03848116929116907f1bd2f11f284e6391695ec5dc02786a2f817560fab3a4c6ecebf1f483204f966890600090a4600680546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600c60205260409020546106e29061246d565b565b6000336106f28582856125eb565b6106fd85858561265f565b506001949350505050565b6000336105ed81858561071b83836117ab565b6107259190613392565b6120cd565b600f805461073790613342565b80601f016020809104026020016040519081016040528092919081815260200182805461076390613342565b80156107b05780601f10610785576101008083540402835291602001916107b0565b820191906000526020600020905b81548152906001019060200180831161079357829003601f168201915b505050505081565b6007602052600090815260409020805460018201546002830180546001600160a01b039093169391926107ea90613342565b80601f016020809104026020016040519081016040528092919081815260200182805461081690613342565b80156108635780601f1061083857610100808354040283529160200191610863565b820191906000526020600020905b81548152906001019060200180831161084657829003601f168201915b5050506003909301549192505060ff1684565b60405181815233907f33631bcd0a4d34a7e2c240ab0753d5adfb7284d8ac89dab6876ec785c0cfa0e69060200160405180910390a26108b5338261280e565b50565b60006105f3823361294c565b6108ce600a6121f1565b60405181815233907fc30bbd22b0c6378065c37f72e8e5e352368ad2c72d3d107ec28e11c61d16a05e9060200160405180910390a2601055565b6108b58161246d565b610919612b5b565b61092360016121f1565b8261092d336103c6565b101561094b5760405162461bcd60e51b8152600401610661906133a5565b336000908152600c6020526040902054610966908490613392565b336000908152600c6020526040902055600d54610984908490613392565b600d55600061099260025490565b670de0b6b3a7640000600d546109a891906133ee565b6109b29190613405565b600654600e549192506001600160a01b0316908210610a8f57604051632c0edf6560e11b81523060048201526001600160a01b0382169063581dbeca906024016020604051808303816000875af1158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a359190613427565b610a8f5760405162461bcd60e51b815260206004820152602560248201527f4173736574546f6b656e3a206572726f72206f6e20736166656775617264206360448201526468616e676560d81b6064820152608401610661565b336000908152600b602052604081205490819003610c2457600a8054906000610ab783613449565b9190505550604051806101000160405280610acf3390565b6001600160a01b0316815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093855250505060208083018a90526040808401839052606084018390526001608085018190528151808401835284815260a086015260c0909401839052600a54835260098252909120835181546001600160a01b0319166001600160a01b03909116178155908301519091820190610b8790826134b0565b506040820151600282015560608201516003820155608082015160048201805460a085015115156101000261ff00199315159390931661ffff199091161791909117905560c08201516005820190610bdf90826134b0565b5060e09190910151600690910180546001600160a01b0319166001600160a01b0390921691909117905550600a54336000908152600b60205260409020819055610c54565b600081815260096020526040902060020154610c41908790613392565b6000828152600960205260409020600201555b60008181526009602090815260409182902060028101546003909101548351918252918101919091526001818301529051339183917fa8cb3abff9d33baf50c27997f56858a870eece3044d19c6645d25719ee4eb5859181900360600190a3610cbe33308861265f565b505050610ccb6001600555565b505050565b6000610cda612b5b565b60008311610d3b5760405162461bcd60e51b815260206004820152602860248201527f4173736574546f6b656e3a206173736574546f6b656e416d6f756e74206d7573604482015267074206265203e20360c41b6064820152608401610661565b82610d45336103c6565b1015610d635760405162461bcd60e51b8152600401610661906133a5565b60065460405163fef03da360e01b81523060048201526001600160a01b0390911690600090829063fef03da390602401602060405180830381865afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190613570565b604051635980ec8160e11b81523060048201529091506000906001600160a01b0384169063b301d90290602401602060405180830381865afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e429190613570565b604051636306be8560e01b81523060048201529091506000906001600160a01b03851690636306be8590602401602060405180830381865afa158015610e8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb09190613427565b905080158015610ec95750336001600160a01b03841614155b80610ee55750808015610ee55750336001600160a01b03831614155b15610f5857601054871015610f585760405162461bcd60e51b815260206004820152603360248201527f4173736574546f6b656e3a206d696e696d756d526564656d7074696f6e416d6f6044820152721d5b9d081b9bdd081c995858da1959081e595d606a1b6064820152608401610661565b604051630e0dc3b960e11b81523060048201526001600160a01b03851690631c1b877290602401600060405180830381600087803b158015610f9957600080fd5b505af1158015610fad573d6000803e3d6000fd5b5050604051633739df6160e21b8152306004820152600092506001600160a01b038716915063dce77d8490602401602060405180830381865afa158015610ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101c919061358d565b90506000670de0b6b3a7640000611033838b6133ee565b61103d9190613405565b600a8054919250600061104f83613449565b919050555061105b3390565b600a54604080518c81526020810185905260008183015290516001600160a01b0393909316927fa8cb3abff9d33baf50c27997f56858a870eece3044d19c6645d25719ee4eb5859181900360600190a36040518061010001604052806110be3390565b6001600160a01b03908116825260208083018c905260408084018e90526060840186905260006080850181905260a085018190528151808401835281815260c086015260e0909401849052600a54845260098252909220835181546001600160a01b031916921691909117815590820151600182019061113e90826134b0565b506040820151600282015560608201516003820155608082015160048201805460a085015115156101000261ff00199315159390931661ffff199091161791909117905560c0820151600582019061119690826134b0565b5060e09190910151600690910180546001600160a01b0319166001600160a01b039092169190911790556111cb33308b61265f565b821580156111e15750336001600160a01b038616145b806111fc57508280156111fc5750336001600160a01b038516145b1561124257611242600a546040518060400160405280601b81526020017f4175746f6d61746963526564656d7074696f6e417070726f76616c0000000000815250611c4f565b600a5496505050505050506105f36001600555565b60606004805461055c90613342565b611270600a6121f1565b600381116112c05760405162461bcd60e51b815260206004820181905260248201527f4173736574546f6b656e3a20696e636f7272656374206b7961207061737365646044820152606401610661565b336001600160a01b03167fa968454fe42ca93a4780be08eb42cedc78e3f1dd75d23e0daf15c615e2594d6783836040516112fb9291906135a6565b60405180910390a2600f610ccb8284836135d5565b6000338161131e82866117ab565b90508381101561137e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610661565b6106fd82868684036120cd565b61139560086121f1565b600654604051632526693d60e11b81523060048201526001600160a01b03909116908190634a4cd27a90602401602060405180830381865afa1580156113df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114039190613427565b156114505760405162461bcd60e51b815260206004820152601e60248201527f4173736574546f6b656e3a20636f6e74726163742069732066726f7a656e00006044820152606401610661565b604051631bef0dc360e01b81523060048201526001600160a01b03821690631bef0dc3906024016020604051808303816000875af1158015611496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ba9190613427565b6108b55760405162461bcd60e51b815260206004820152601b60248201527f4173736574546f6b656e3a20667265657a696e67206661696c656400000000006044820152606401610661565b6000336105ed81858561265f565b61151c612b5b565b61152660056121f1565b6000828152600760205260409020546001600160a01b03166115965760405162461bcd60e51b8152602060048201526024808201527f4173736574546f6b656e3a2072657175657374494420646f6573206e6f7420656044820152631e1a5cdd60e21b6064820152608401610661565b60008281526007602052604090206003015460ff16156115f85760405162461bcd60e51b815260206004820181905260248201527f4173736574546f6b656e3a207265717565737420697320636f6d706c657465646044820152606401610661565b600082815260076020526040902060038101805460ff1916600117905560020161162282826134b0565b50600654604051630e0dc3b960e11b81523060048201526001600160a01b03909116908190631c1b877290602401600060405180830381600087803b15801561166a57600080fd5b505af115801561167e573d6000803e3d6000fd5b5050604051633739df6160e21b8152306004820152600092506001600160a01b038416915063dce77d8490602401602060405180830381865afa1580156116c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ed919061358d565b60008581526007602052604081206001015491925090829061171890670de0b6b3a7640000906133ee565b6117229190613405565b600086815260076020908152604091829020548251848152925193945033936001600160a01b039091169289927f293a53949964e4a793f245e9ef19f0b1134ea644f51d51df86331137bb9232c692918290030190a460008581526007602052604090205461179a906001600160a01b031682612bb4565b5050506117a76001600555565b5050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600960205260009081526040902080546001820180546001600160a01b03909216929161180290613342565b80601f016020809104026020016040519081016040528092919081815260200182805461182e90613342565b801561187b5780601f106118505761010080835404028352916020019161187b565b820191906000526020600020905b81548152906001019060200180831161185e57829003601f168201915b505050506002830154600384015460048501546005860180549596939592945060ff8083169461010090930416926118b290613342565b80601f01602080910402602001604051908101604052809291908181526020018280546118de90613342565b801561192b5780601f106119005761010080835404028352916020019161192b565b820191906000526020600020905b81548152906001019060200180831161190e57829003601f168201915b505050600690930154919250506001600160a01b031688565b6000828152600960205260409020546001600160a01b03166119ad5760405162461bcd60e51b815260206004820152602e60248201526000805160206136aa83398151915260448201526d191bd95cc81b9bdd08195e1a5cdd60921b6064820152608401610661565b6000828152600960205260409020600601546001600160a01b031615611a275760405162461bcd60e51b815260206004820152602960248201527f4173736574546f6b656e3a20726564656d7074696f6e20686173206265656e2060448201526818d85b98d95b1b195960ba1b6064820152608401610661565b60008281526009602052604090206004015460ff1615611a9a5760405162461bcd60e51b815260206004820152602860248201527f4173736574546f6b656e3a20726564656d7074696f6e20616c726561647920636044820152671bdb5c1b195d195960c21b6064820152608401610661565b600082815260096020526040902060040154610100900460ff1615611b185760405162461bcd60e51b815260206004820152602e60248201527f4173736574546f6b656e3a207374616b65642072657175657374202d20756e7360448201526d74616b6520746f2072656465656d60901b6064820152608401610661565b6006546000838152600960205260409020546001600160a01b0391821691163314611ba257604080516362d1cb6760e01b815230600482015233602482015290516001600160a01b038316916362d1cb67916044808301926000929190829003018186803b158015611b8957600080fd5b505afa158015611b9d573d6000803e3d6000fd5b505050505b60008381526009602052604090819020600281015490549151909133916001600160a01b039091169086907f31916b1311adb3f7a4a9092ec7c3d79cc1eab54bddaa4e1db9f7e1097797f92990611bfa908890612fc8565b60405180910390a460008481526009602052604081206002810182905560038101919091556006810180546001600160a01b0319163317905554611c499030906001600160a01b03168361265f565b50505050565b611c5960086121f1565b6000828152600960205260409020600601546001600160a01b031615611cca5760405162461bcd60e51b815260206004820152603260248201526000805160206136aa8339815191526044820152711a185cc81899595b8818d85b98d95b1b195960721b6064820152608401610661565b6000828152600960205260409020546001600160a01b0316611d315760405162461bcd60e51b815260206004820152602c60248201526000805160206136aa83398151915260448201526b1a5cc81a5b98dbdc9c9958dd60a21b6064820152608401610661565b60008281526009602052604090206004015460ff1615611d935760405162461bcd60e51b815260206004820152602960248201526000805160206136aa83398151915260448201526818dbdb5c1b195d195960ba1b6064820152608401610661565b600082815260096020526040902060040154610100900460ff1615611e8757600654604051636306be8560e01b81523060048201526001600160a01b03909116908190636306be8590602401602060405180830381865afa158015611dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e209190613427565b611e855760405162461bcd60e51b815260206004820152603060248201527f4173736574546f6b656e3a20636f6e747261637420697320616374697665202860448201526f6e6f74206f6e5361666567756172642960801b6064820152608401610661565b505b6000828152600960209081526040918290208054600282015460039092015484519283529282019290925233926001600160a01b039092169185917f77ac421ef93134bdf8b76efd922614ddca35f3f14e97c693dd88b4a3aa160636910160405180910390a4600082815260096020526040902060048101805460ff19166001179055600501611f1782826134b0565b506000828152600960205260409020600201546117a790309061280e565b611f3f60086121f1565b600654604051632526693d60e11b81523060048201526001600160a01b03909116908190634a4cd27a90602401602060405180830381865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad9190613427565b6120045760405162461bcd60e51b815260206004820152602260248201527f4173736574546f6b656e3a20636f6e7472616374206973206e6f742066726f7a60448201526132b760f11b6064820152608401610661565b6040516370e6513b60e11b81523060048201526001600160a01b0382169063e1cca276906024016020604051808303816000875af115801561204a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206e9190613427565b6108b55760405162461bcd60e51b815260206004820152601d60248201527f4173736574546f6b656e3a20756e667265657a696e67206661696c65640000006044820152606401610661565b60006120c6838361294c565b9392505050565b6001600160a01b03831661212f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610661565b6001600160a01b0382166121905760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610661565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6006546000906001600160a01b03166001831615612265576040516348f261b960e01b81523060048201526001600160a01b038216906348f261b99060240160006040518083038186803b15801561224857600080fd5b505afa15801561225c573d6000803e3d6000fd5b50505050600191505b60028316156122ca576040516331e11d4160e01b81523060048201526001600160a01b038216906331e11d419060240160006040518083038186803b1580156122ad57600080fd5b505afa1580156122c1573d6000803e3d6000fd5b50505050600191505b600483161561233c576040805163d9253c7d60e01b815230600482015233602482015290516001600160a01b0383169163d9253c7d916044808301926000929190829003018186803b15801561231f57600080fd5b505afa158015612333573d6000803e3d6000fd5b50505050600191505b60088316156123ae57604080516362d1cb6760e01b815230600482015233602482015290516001600160a01b038316916362d1cb67916044808301926000929190829003018186803b15801561239157600080fd5b505afa1580156123a5573d6000803e3d6000fd5b50505050600191505b6010831615612420576040805163b14cfbb960e01b815230600482015233602482015290516001600160a01b0383169163b14cfbb9916044808301926000929190829003018186803b15801561240357600080fd5b505afa158015612417573d6000803e3d6000fd5b50505050600191505b81610ccb5760405162461bcd60e51b815260206004820152601c60248201527f4173736574546f6b656e3a20616363657373206e6f7420666f756e64000000006044820152606401610661565b61247760036121f1565b600081116124c75760405162461bcd60e51b815260206004820152601e60248201527f4173736574546f6b656e3a20616d6f756e74206d757374206265203e203000006044820152606401610661565b336000908152600c60205260409020548111156125305760405162461bcd60e51b815260206004820152602160248201527f4173736574546f6b656e3a20616d6f756e742065786365656473207374616b656044820152601960fa1b6064820152608401610661565b60405181815233907f59696ca7031c7df7a856426d8eb521fa3033d4257b16cd455de5f30590591c7e9060200160405180910390a2336000908152600c6020526040902054612580908290613696565b336000908152600c6020526040902055600d5461259e908290613696565b600d55336000908152600b60209081526040808320548084526009909252909120600201546125ce908390613696565b6000828152600960205260409020600201556117a730338461265f565b60006125f784846117ab565b90506000198114611c4957818110156126525760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610661565b611c4984848484036120cd565b6001600160a01b0383166126c35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610661565b6001600160a01b0382166127255760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610661565b612730838383612c7f565b6001600160a01b038316600090815260208190526040902054818110156127a85760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610661565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3611c49565b6001600160a01b03821661286e5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610661565b61287a82600083612c7f565b6001600160a01b038216600090815260208190526040902054818110156128ee5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610661565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b600061295860136121f1565b600083116129a85760405162461bcd60e51b815260206004820152601e60248201527f4173736574546f6b656e3a20616d6f756e74206d757374206265203e203000006044820152606401610661565b600880549060006129b883613449565b91905055506129c43390565b6001600160a01b0316826001600160a01b03166008547fd44ca9091dc2db8840a4a2459864b4bb02cd1f06f285f304ec45aa15ec28e0ea86604051612a0b91815260200190565b60405180910390a4604080516080810182526001600160a01b0384811682526020808301878152845180830186526000808252858701918252606086018190526008548152600790935294909120835181546001600160a01b031916931692909217825551600182015591519091906002820190612a8990826134b0565b50606091909101516003909101805460ff191691151591909117905560065460405163fef03da360e01b81523060048201526001600160a01b0390911690819063fef03da390602401602060405180830381865afa158015612aef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b139190613570565b6001600160a01b03163303612b5057612b506008546040518060400160405280600a815260200169125cdcdd595c935a5b9d60b21b815250611514565b505060085492915050565b600260055403612bad5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610661565b6002600555565b6001600160a01b038216612c0a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610661565b612c1660008383612c7f565b8060026000828254612c289190613392565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b612c8960026121f1565b600654604051636306be8560e01b81523060048201526001600160a01b03909116908190636306be8590602401602060405180830381865afa158015612cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf79190613427565b15612e8f576001600160a01b0383163014801590612d1e57506001600160a01b0384163014155b8015612da35750604051635980ec8160e11b81523060048201526001600160a01b0382169063b301d90290602401602060405180830381865afa158015612d69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8d9190613570565b6001600160a01b0316846001600160a01b031614155b15612e8f5760405163db5f725760e01b81523060048201526001600160a01b03858116602483015282169063db5f725790604401602060405180830381865afa158015612df4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e189190613427565b612e8a5760405162461bcd60e51b815260206004820152603a60248201527f4173736574546f6b656e3a206265666f7265546f6b656e5472616e736665723a60448201527f206e6f7420616c6c6f77656420286f6e536166656775617264290000000000006064820152608401610661565b611c49565b604051632325e69f60e21b81523060048201526001600160a01b038581166024830152848116604483015260648201849052821690638c979a7c906084016020604051808303816000875af1158015612eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f109190613427565b612e8a5760405162461bcd60e51b815260206004820152603a60248201527f4173736574546f6b656e3a206265666f7265546f6b656e5472616e736665723a60448201527f206e6f7420617574686f72697a656420286f6e416374697665290000000000006064820152608401610661565b6000815180845260005b81811015612fa857602081850181015186830182015201612f8c565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006120c66020830184612f82565b6001600160a01b03811681146108b557600080fd5b6000806040838503121561300357600080fd5b823561300e81612fdb565b946020939093013593505050565b60006020828403121561302e57600080fd5b81356120c681612fdb565b60008060006060848603121561304e57600080fd5b833561305981612fdb565b9250602084013561306981612fdb565b929592945050506040919091013590565b60006020828403121561308c57600080fd5b5035919050565b60018060a01b03851681528360208201526080604082015260006130ba6080830185612f82565b9050821515606083015295945050505050565b60008083601f8401126130df57600080fd5b50813567ffffffffffffffff8111156130f757600080fd5b60208301915083602082850101111561310f57600080fd5b9250929050565b60008060006040848603121561312b57600080fd5b83359250602084013567ffffffffffffffff81111561314957600080fd5b613155868287016130cd565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561318b57600080fd5b82359150602083013567ffffffffffffffff808211156131aa57600080fd5b818501915085601f8301126131be57600080fd5b8135818111156131d0576131d0613162565b604051601f8201601f19908116603f011681019083821181831017156131f8576131f8613162565b8160405282815288602084870101111561321157600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000806020838503121561324657600080fd5b823567ffffffffffffffff81111561325d57600080fd5b613269858286016130cd565b90969095509350505050565b6000806040838503121561328857600080fd5b823561329381612fdb565b915060208301356132a381612fdb565b809150509250929050565b6001600160a01b038981168252610100602083018190526000916132d48483018c612f82565b9150896040850152886060850152871515608085015286151560a085015283820360c08501526133048287612f82565b925080851660e085015250509998505050505050505050565b6000806040838503121561333057600080fd5b8235915060208301356132a381612fdb565b600181811c9082168061335657607f821691505b60208210810361337657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156105f3576105f361337c565b60208082526029908201527f4173736574546f6b656e3a2063616c6c65722068617320696e73756666696369604082015268656e742066756e647360b81b606082015260800190565b80820281158282048414176105f3576105f361337c565b60008261342257634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561343957600080fd5b815180151581146120c657600080fd5b60006001820161345b5761345b61337c565b5060010190565b601f821115610ccb57600081815260208120601f850160051c810160208610156134895750805b601f850160051c820191505b818110156134a857828155600101613495565b505050505050565b815167ffffffffffffffff8111156134ca576134ca613162565b6134de816134d88454613342565b84613462565b602080601f83116001811461351357600084156134fb5750858301515b600019600386901b1c1916600185901b1785556134a8565b600085815260208120601f198616915b8281101561354257888601518255948401946001909101908401613523565b50858210156135605787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561358257600080fd5b81516120c681612fdb565b60006020828403121561359f57600080fd5b5051919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b67ffffffffffffffff8311156135ed576135ed613162565b613601836135fb8354613342565b83613462565b6000601f841160018114613635576000851561361d5750838201355b600019600387901b1c1916600186901b17835561368f565b600083815260209020601f19861690835b828110156136665786850135825560209485019460019092019101613646565b50868210156136835760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b818103818111156105f3576105f361337c56fe4173736574546f6b656e3a20726564656d7074696f6e52657175657374494420a2646970667358221220989008ac89cd312bd5d6e33da341ec8e16f8718e8548ca029335a2d8644fcfa464736f6c6343000813003300000000000000000000000044fd5ecb21380db8fbac8c2e0f0ae5f86c0c335b00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000a697066733a2f2f74626400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4150504c4520494e432e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044141504c00000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061023d5760003560e01c8063793f255c1161013b578063dc174960116100b8578063ee7611891161007c578063ee761189146104ec578063f15965d9146104ff578063f4917dd314610512578063f634d4e81461051a578063ff322ba11461053a57600080fd5b8063dc1749601461048d578063dd62ed3e146104a0578063e0f486ef146104b3578063e1a0cc6f146104bc578063ea4a1d5c146104e357600080fd5b8063a457c2d7116100ff578063a457c2d71461044d578063a584a9b514610460578063a9059cbb14610468578063bad9d0e41461047b578063bf9befb11461048457600080fd5b8063793f255c146103e157806386511595146103f45780638660970c1461040757806395d89b411461043257806398d9423e1461043a57600080fd5b8063377a1a62116101c957806349733d041161018d57806349733d041461037f5780634ef1ccd1146103925780635605a998146103a55780636ed93dd0146102e557806370a08231146103b857600080fd5b8063377a1a6214610325578063395093511461032e5780633fc7293a14610341578063424e65751461034957806342966c681461036c57600080fd5b8063189d1e0b11610210578063189d1e0b146102aa5780631d0b56af146102b257806323b872dd146102d25780632e0f2625146102e5578063313ce567146102f457600080fd5b806306fdde0314610242578063095ea7b3146102605780630ac7f4e61461028357806318160ddd14610298575b600080fd5b61024a61054d565b6040516102579190612fc8565b60405180910390f35b61027361026e366004612ff0565b6105df565b6040519015158152602001610257565b61029661029136600461301c565b6105f9565b005b6002545b604051908152602001610257565b6102966106c9565b61029c6102c036600461301c565b600c6020526000908152604090205481565b6102736102e0366004613039565b6106e4565b61029c670de0b6b3a764000081565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000012168152602001610257565b61029c60085481565b61027361033c366004612ff0565b610708565b61024a61072a565b61035c61035736600461307a565b6107b8565b6040516102579493929190613093565b61029661037a36600461307a565b610876565b61029c61038d36600461307a565b6108b8565b6102966103a036600461307a565b6108c4565b6102966103b336600461307a565b610908565b61029c6103c636600461301c565b6001600160a01b031660009081526020819052604090205490565b6102966103ef366004613116565b610911565b61029c610402366004613178565b610cd0565b60065461041a906001600160a01b031681565b6040516001600160a01b039091168152602001610257565b61024a611257565b610296610448366004613233565b611266565b61027361045b366004612ff0565b611310565b61029661138b565b610273610476366004612ff0565b611506565b61029c600e5481565b61029c600d5481565b61029661049b366004613178565b611514565b61029c6104ae366004613275565b6117ab565b61029c60105481565b6104cf6104ca36600461307a565b6117d6565b6040516102579897969594939291906132ae565b61029c600a5481565b6102966104fa366004613178565b611944565b61029661050d366004613178565b611c4f565b610296611f35565b61029c61052836600461301c565b600b6020526000908152604090205481565b61029c61054836600461331d565b6120ba565b60606003805461055c90613342565b80601f016020809104026020016040519081016040528092919081815260200182805461058890613342565b80156105d55780601f106105aa576101008083540402835291602001916105d5565b820191906000526020600020905b8154815290600101906020018083116105b857829003601f168201915b5050505050905090565b6000336105ed8185856120cd565b60019150505b92915050565b610603600a6121f1565b6001600160a01b03811661066a5760405162461bcd60e51b815260206004820152602360248201527f4173736574546f6b656e3a206e6577416464726573732069732061646472657360448201526207320360ec1b60648201526084015b60405180910390fd5b60065460405133916001600160a01b03848116929116907f1bd2f11f284e6391695ec5dc02786a2f817560fab3a4c6ecebf1f483204f966890600090a4600680546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600c60205260409020546106e29061246d565b565b6000336106f28582856125eb565b6106fd85858561265f565b506001949350505050565b6000336105ed81858561071b83836117ab565b6107259190613392565b6120cd565b600f805461073790613342565b80601f016020809104026020016040519081016040528092919081815260200182805461076390613342565b80156107b05780601f10610785576101008083540402835291602001916107b0565b820191906000526020600020905b81548152906001019060200180831161079357829003601f168201915b505050505081565b6007602052600090815260409020805460018201546002830180546001600160a01b039093169391926107ea90613342565b80601f016020809104026020016040519081016040528092919081815260200182805461081690613342565b80156108635780601f1061083857610100808354040283529160200191610863565b820191906000526020600020905b81548152906001019060200180831161084657829003601f168201915b5050506003909301549192505060ff1684565b60405181815233907f33631bcd0a4d34a7e2c240ab0753d5adfb7284d8ac89dab6876ec785c0cfa0e69060200160405180910390a26108b5338261280e565b50565b60006105f3823361294c565b6108ce600a6121f1565b60405181815233907fc30bbd22b0c6378065c37f72e8e5e352368ad2c72d3d107ec28e11c61d16a05e9060200160405180910390a2601055565b6108b58161246d565b610919612b5b565b61092360016121f1565b8261092d336103c6565b101561094b5760405162461bcd60e51b8152600401610661906133a5565b336000908152600c6020526040902054610966908490613392565b336000908152600c6020526040902055600d54610984908490613392565b600d55600061099260025490565b670de0b6b3a7640000600d546109a891906133ee565b6109b29190613405565b600654600e549192506001600160a01b0316908210610a8f57604051632c0edf6560e11b81523060048201526001600160a01b0382169063581dbeca906024016020604051808303816000875af1158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a359190613427565b610a8f5760405162461bcd60e51b815260206004820152602560248201527f4173736574546f6b656e3a206572726f72206f6e20736166656775617264206360448201526468616e676560d81b6064820152608401610661565b336000908152600b602052604081205490819003610c2457600a8054906000610ab783613449565b9190505550604051806101000160405280610acf3390565b6001600160a01b0316815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093855250505060208083018a90526040808401839052606084018390526001608085018190528151808401835284815260a086015260c0909401839052600a54835260098252909120835181546001600160a01b0319166001600160a01b03909116178155908301519091820190610b8790826134b0565b506040820151600282015560608201516003820155608082015160048201805460a085015115156101000261ff00199315159390931661ffff199091161791909117905560c08201516005820190610bdf90826134b0565b5060e09190910151600690910180546001600160a01b0319166001600160a01b0390921691909117905550600a54336000908152600b60205260409020819055610c54565b600081815260096020526040902060020154610c41908790613392565b6000828152600960205260409020600201555b60008181526009602090815260409182902060028101546003909101548351918252918101919091526001818301529051339183917fa8cb3abff9d33baf50c27997f56858a870eece3044d19c6645d25719ee4eb5859181900360600190a3610cbe33308861265f565b505050610ccb6001600555565b505050565b6000610cda612b5b565b60008311610d3b5760405162461bcd60e51b815260206004820152602860248201527f4173736574546f6b656e3a206173736574546f6b656e416d6f756e74206d7573604482015267074206265203e20360c41b6064820152608401610661565b82610d45336103c6565b1015610d635760405162461bcd60e51b8152600401610661906133a5565b60065460405163fef03da360e01b81523060048201526001600160a01b0390911690600090829063fef03da390602401602060405180830381865afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190613570565b604051635980ec8160e11b81523060048201529091506000906001600160a01b0384169063b301d90290602401602060405180830381865afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e429190613570565b604051636306be8560e01b81523060048201529091506000906001600160a01b03851690636306be8590602401602060405180830381865afa158015610e8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb09190613427565b905080158015610ec95750336001600160a01b03841614155b80610ee55750808015610ee55750336001600160a01b03831614155b15610f5857601054871015610f585760405162461bcd60e51b815260206004820152603360248201527f4173736574546f6b656e3a206d696e696d756d526564656d7074696f6e416d6f6044820152721d5b9d081b9bdd081c995858da1959081e595d606a1b6064820152608401610661565b604051630e0dc3b960e11b81523060048201526001600160a01b03851690631c1b877290602401600060405180830381600087803b158015610f9957600080fd5b505af1158015610fad573d6000803e3d6000fd5b5050604051633739df6160e21b8152306004820152600092506001600160a01b038716915063dce77d8490602401602060405180830381865afa158015610ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101c919061358d565b90506000670de0b6b3a7640000611033838b6133ee565b61103d9190613405565b600a8054919250600061104f83613449565b919050555061105b3390565b600a54604080518c81526020810185905260008183015290516001600160a01b0393909316927fa8cb3abff9d33baf50c27997f56858a870eece3044d19c6645d25719ee4eb5859181900360600190a36040518061010001604052806110be3390565b6001600160a01b03908116825260208083018c905260408084018e90526060840186905260006080850181905260a085018190528151808401835281815260c086015260e0909401849052600a54845260098252909220835181546001600160a01b031916921691909117815590820151600182019061113e90826134b0565b506040820151600282015560608201516003820155608082015160048201805460a085015115156101000261ff00199315159390931661ffff199091161791909117905560c0820151600582019061119690826134b0565b5060e09190910151600690910180546001600160a01b0319166001600160a01b039092169190911790556111cb33308b61265f565b821580156111e15750336001600160a01b038616145b806111fc57508280156111fc5750336001600160a01b038516145b1561124257611242600a546040518060400160405280601b81526020017f4175746f6d61746963526564656d7074696f6e417070726f76616c0000000000815250611c4f565b600a5496505050505050506105f36001600555565b60606004805461055c90613342565b611270600a6121f1565b600381116112c05760405162461bcd60e51b815260206004820181905260248201527f4173736574546f6b656e3a20696e636f7272656374206b7961207061737365646044820152606401610661565b336001600160a01b03167fa968454fe42ca93a4780be08eb42cedc78e3f1dd75d23e0daf15c615e2594d6783836040516112fb9291906135a6565b60405180910390a2600f610ccb8284836135d5565b6000338161131e82866117ab565b90508381101561137e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610661565b6106fd82868684036120cd565b61139560086121f1565b600654604051632526693d60e11b81523060048201526001600160a01b03909116908190634a4cd27a90602401602060405180830381865afa1580156113df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114039190613427565b156114505760405162461bcd60e51b815260206004820152601e60248201527f4173736574546f6b656e3a20636f6e74726163742069732066726f7a656e00006044820152606401610661565b604051631bef0dc360e01b81523060048201526001600160a01b03821690631bef0dc3906024016020604051808303816000875af1158015611496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ba9190613427565b6108b55760405162461bcd60e51b815260206004820152601b60248201527f4173736574546f6b656e3a20667265657a696e67206661696c656400000000006044820152606401610661565b6000336105ed81858561265f565b61151c612b5b565b61152660056121f1565b6000828152600760205260409020546001600160a01b03166115965760405162461bcd60e51b8152602060048201526024808201527f4173736574546f6b656e3a2072657175657374494420646f6573206e6f7420656044820152631e1a5cdd60e21b6064820152608401610661565b60008281526007602052604090206003015460ff16156115f85760405162461bcd60e51b815260206004820181905260248201527f4173736574546f6b656e3a207265717565737420697320636f6d706c657465646044820152606401610661565b600082815260076020526040902060038101805460ff1916600117905560020161162282826134b0565b50600654604051630e0dc3b960e11b81523060048201526001600160a01b03909116908190631c1b877290602401600060405180830381600087803b15801561166a57600080fd5b505af115801561167e573d6000803e3d6000fd5b5050604051633739df6160e21b8152306004820152600092506001600160a01b038416915063dce77d8490602401602060405180830381865afa1580156116c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ed919061358d565b60008581526007602052604081206001015491925090829061171890670de0b6b3a7640000906133ee565b6117229190613405565b600086815260076020908152604091829020548251848152925193945033936001600160a01b039091169289927f293a53949964e4a793f245e9ef19f0b1134ea644f51d51df86331137bb9232c692918290030190a460008581526007602052604090205461179a906001600160a01b031682612bb4565b5050506117a76001600555565b5050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600960205260009081526040902080546001820180546001600160a01b03909216929161180290613342565b80601f016020809104026020016040519081016040528092919081815260200182805461182e90613342565b801561187b5780601f106118505761010080835404028352916020019161187b565b820191906000526020600020905b81548152906001019060200180831161185e57829003601f168201915b505050506002830154600384015460048501546005860180549596939592945060ff8083169461010090930416926118b290613342565b80601f01602080910402602001604051908101604052809291908181526020018280546118de90613342565b801561192b5780601f106119005761010080835404028352916020019161192b565b820191906000526020600020905b81548152906001019060200180831161190e57829003601f168201915b505050600690930154919250506001600160a01b031688565b6000828152600960205260409020546001600160a01b03166119ad5760405162461bcd60e51b815260206004820152602e60248201526000805160206136aa83398151915260448201526d191bd95cc81b9bdd08195e1a5cdd60921b6064820152608401610661565b6000828152600960205260409020600601546001600160a01b031615611a275760405162461bcd60e51b815260206004820152602960248201527f4173736574546f6b656e3a20726564656d7074696f6e20686173206265656e2060448201526818d85b98d95b1b195960ba1b6064820152608401610661565b60008281526009602052604090206004015460ff1615611a9a5760405162461bcd60e51b815260206004820152602860248201527f4173736574546f6b656e3a20726564656d7074696f6e20616c726561647920636044820152671bdb5c1b195d195960c21b6064820152608401610661565b600082815260096020526040902060040154610100900460ff1615611b185760405162461bcd60e51b815260206004820152602e60248201527f4173736574546f6b656e3a207374616b65642072657175657374202d20756e7360448201526d74616b6520746f2072656465656d60901b6064820152608401610661565b6006546000838152600960205260409020546001600160a01b0391821691163314611ba257604080516362d1cb6760e01b815230600482015233602482015290516001600160a01b038316916362d1cb67916044808301926000929190829003018186803b158015611b8957600080fd5b505afa158015611b9d573d6000803e3d6000fd5b505050505b60008381526009602052604090819020600281015490549151909133916001600160a01b039091169086907f31916b1311adb3f7a4a9092ec7c3d79cc1eab54bddaa4e1db9f7e1097797f92990611bfa908890612fc8565b60405180910390a460008481526009602052604081206002810182905560038101919091556006810180546001600160a01b0319163317905554611c499030906001600160a01b03168361265f565b50505050565b611c5960086121f1565b6000828152600960205260409020600601546001600160a01b031615611cca5760405162461bcd60e51b815260206004820152603260248201526000805160206136aa8339815191526044820152711a185cc81899595b8818d85b98d95b1b195960721b6064820152608401610661565b6000828152600960205260409020546001600160a01b0316611d315760405162461bcd60e51b815260206004820152602c60248201526000805160206136aa83398151915260448201526b1a5cc81a5b98dbdc9c9958dd60a21b6064820152608401610661565b60008281526009602052604090206004015460ff1615611d935760405162461bcd60e51b815260206004820152602960248201526000805160206136aa83398151915260448201526818dbdb5c1b195d195960ba1b6064820152608401610661565b600082815260096020526040902060040154610100900460ff1615611e8757600654604051636306be8560e01b81523060048201526001600160a01b03909116908190636306be8590602401602060405180830381865afa158015611dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e209190613427565b611e855760405162461bcd60e51b815260206004820152603060248201527f4173736574546f6b656e3a20636f6e747261637420697320616374697665202860448201526f6e6f74206f6e5361666567756172642960801b6064820152608401610661565b505b6000828152600960209081526040918290208054600282015460039092015484519283529282019290925233926001600160a01b039092169185917f77ac421ef93134bdf8b76efd922614ddca35f3f14e97c693dd88b4a3aa160636910160405180910390a4600082815260096020526040902060048101805460ff19166001179055600501611f1782826134b0565b506000828152600960205260409020600201546117a790309061280e565b611f3f60086121f1565b600654604051632526693d60e11b81523060048201526001600160a01b03909116908190634a4cd27a90602401602060405180830381865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad9190613427565b6120045760405162461bcd60e51b815260206004820152602260248201527f4173736574546f6b656e3a20636f6e7472616374206973206e6f742066726f7a60448201526132b760f11b6064820152608401610661565b6040516370e6513b60e11b81523060048201526001600160a01b0382169063e1cca276906024016020604051808303816000875af115801561204a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206e9190613427565b6108b55760405162461bcd60e51b815260206004820152601d60248201527f4173736574546f6b656e3a20756e667265657a696e67206661696c65640000006044820152606401610661565b60006120c6838361294c565b9392505050565b6001600160a01b03831661212f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610661565b6001600160a01b0382166121905760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610661565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6006546000906001600160a01b03166001831615612265576040516348f261b960e01b81523060048201526001600160a01b038216906348f261b99060240160006040518083038186803b15801561224857600080fd5b505afa15801561225c573d6000803e3d6000fd5b50505050600191505b60028316156122ca576040516331e11d4160e01b81523060048201526001600160a01b038216906331e11d419060240160006040518083038186803b1580156122ad57600080fd5b505afa1580156122c1573d6000803e3d6000fd5b50505050600191505b600483161561233c576040805163d9253c7d60e01b815230600482015233602482015290516001600160a01b0383169163d9253c7d916044808301926000929190829003018186803b15801561231f57600080fd5b505afa158015612333573d6000803e3d6000fd5b50505050600191505b60088316156123ae57604080516362d1cb6760e01b815230600482015233602482015290516001600160a01b038316916362d1cb67916044808301926000929190829003018186803b15801561239157600080fd5b505afa1580156123a5573d6000803e3d6000fd5b50505050600191505b6010831615612420576040805163b14cfbb960e01b815230600482015233602482015290516001600160a01b0383169163b14cfbb9916044808301926000929190829003018186803b15801561240357600080fd5b505afa158015612417573d6000803e3d6000fd5b50505050600191505b81610ccb5760405162461bcd60e51b815260206004820152601c60248201527f4173736574546f6b656e3a20616363657373206e6f7420666f756e64000000006044820152606401610661565b61247760036121f1565b600081116124c75760405162461bcd60e51b815260206004820152601e60248201527f4173736574546f6b656e3a20616d6f756e74206d757374206265203e203000006044820152606401610661565b336000908152600c60205260409020548111156125305760405162461bcd60e51b815260206004820152602160248201527f4173736574546f6b656e3a20616d6f756e742065786365656473207374616b656044820152601960fa1b6064820152608401610661565b60405181815233907f59696ca7031c7df7a856426d8eb521fa3033d4257b16cd455de5f30590591c7e9060200160405180910390a2336000908152600c6020526040902054612580908290613696565b336000908152600c6020526040902055600d5461259e908290613696565b600d55336000908152600b60209081526040808320548084526009909252909120600201546125ce908390613696565b6000828152600960205260409020600201556117a730338461265f565b60006125f784846117ab565b90506000198114611c4957818110156126525760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610661565b611c4984848484036120cd565b6001600160a01b0383166126c35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610661565b6001600160a01b0382166127255760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610661565b612730838383612c7f565b6001600160a01b038316600090815260208190526040902054818110156127a85760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610661565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3611c49565b6001600160a01b03821661286e5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610661565b61287a82600083612c7f565b6001600160a01b038216600090815260208190526040902054818110156128ee5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610661565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b600061295860136121f1565b600083116129a85760405162461bcd60e51b815260206004820152601e60248201527f4173736574546f6b656e3a20616d6f756e74206d757374206265203e203000006044820152606401610661565b600880549060006129b883613449565b91905055506129c43390565b6001600160a01b0316826001600160a01b03166008547fd44ca9091dc2db8840a4a2459864b4bb02cd1f06f285f304ec45aa15ec28e0ea86604051612a0b91815260200190565b60405180910390a4604080516080810182526001600160a01b0384811682526020808301878152845180830186526000808252858701918252606086018190526008548152600790935294909120835181546001600160a01b031916931692909217825551600182015591519091906002820190612a8990826134b0565b50606091909101516003909101805460ff191691151591909117905560065460405163fef03da360e01b81523060048201526001600160a01b0390911690819063fef03da390602401602060405180830381865afa158015612aef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b139190613570565b6001600160a01b03163303612b5057612b506008546040518060400160405280600a815260200169125cdcdd595c935a5b9d60b21b815250611514565b505060085492915050565b600260055403612bad5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610661565b6002600555565b6001600160a01b038216612c0a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610661565b612c1660008383612c7f565b8060026000828254612c289190613392565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b612c8960026121f1565b600654604051636306be8560e01b81523060048201526001600160a01b03909116908190636306be8590602401602060405180830381865afa158015612cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf79190613427565b15612e8f576001600160a01b0383163014801590612d1e57506001600160a01b0384163014155b8015612da35750604051635980ec8160e11b81523060048201526001600160a01b0382169063b301d90290602401602060405180830381865afa158015612d69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8d9190613570565b6001600160a01b0316846001600160a01b031614155b15612e8f5760405163db5f725760e01b81523060048201526001600160a01b03858116602483015282169063db5f725790604401602060405180830381865afa158015612df4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e189190613427565b612e8a5760405162461bcd60e51b815260206004820152603a60248201527f4173736574546f6b656e3a206265666f7265546f6b656e5472616e736665723a60448201527f206e6f7420616c6c6f77656420286f6e536166656775617264290000000000006064820152608401610661565b611c49565b604051632325e69f60e21b81523060048201526001600160a01b038581166024830152848116604483015260648201849052821690638c979a7c906084016020604051808303816000875af1158015612eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f109190613427565b612e8a5760405162461bcd60e51b815260206004820152603a60248201527f4173736574546f6b656e3a206265666f7265546f6b656e5472616e736665723a60448201527f206e6f7420617574686f72697a656420286f6e416374697665290000000000006064820152608401610661565b6000815180845260005b81811015612fa857602081850181015186830182015201612f8c565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006120c66020830184612f82565b6001600160a01b03811681146108b557600080fd5b6000806040838503121561300357600080fd5b823561300e81612fdb565b946020939093013593505050565b60006020828403121561302e57600080fd5b81356120c681612fdb565b60008060006060848603121561304e57600080fd5b833561305981612fdb565b9250602084013561306981612fdb565b929592945050506040919091013590565b60006020828403121561308c57600080fd5b5035919050565b60018060a01b03851681528360208201526080604082015260006130ba6080830185612f82565b9050821515606083015295945050505050565b60008083601f8401126130df57600080fd5b50813567ffffffffffffffff8111156130f757600080fd5b60208301915083602082850101111561310f57600080fd5b9250929050565b60008060006040848603121561312b57600080fd5b83359250602084013567ffffffffffffffff81111561314957600080fd5b613155868287016130cd565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561318b57600080fd5b82359150602083013567ffffffffffffffff808211156131aa57600080fd5b818501915085601f8301126131be57600080fd5b8135818111156131d0576131d0613162565b604051601f8201601f19908116603f011681019083821181831017156131f8576131f8613162565b8160405282815288602084870101111561321157600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000806020838503121561324657600080fd5b823567ffffffffffffffff81111561325d57600080fd5b613269858286016130cd565b90969095509350505050565b6000806040838503121561328857600080fd5b823561329381612fdb565b915060208301356132a381612fdb565b809150509250929050565b6001600160a01b038981168252610100602083018190526000916132d48483018c612f82565b9150896040850152886060850152871515608085015286151560a085015283820360c08501526133048287612f82565b925080851660e085015250509998505050505050505050565b6000806040838503121561333057600080fd5b8235915060208301356132a381612fdb565b600181811c9082168061335657607f821691505b60208210810361337657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156105f3576105f361337c565b60208082526029908201527f4173736574546f6b656e3a2063616c6c65722068617320696e73756666696369604082015268656e742066756e647360b81b606082015260800190565b80820281158282048414176105f3576105f361337c565b60008261342257634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561343957600080fd5b815180151581146120c657600080fd5b60006001820161345b5761345b61337c565b5060010190565b601f821115610ccb57600081815260208120601f850160051c810160208610156134895750805b601f850160051c820191505b818110156134a857828155600101613495565b505050505050565b815167ffffffffffffffff8111156134ca576134ca613162565b6134de816134d88454613342565b84613462565b602080601f83116001811461351357600084156134fb5750858301515b600019600386901b1c1916600185901b1785556134a8565b600085815260208120601f198616915b8281101561354257888601518255948401946001909101908401613523565b50858210156135605787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561358257600080fd5b81516120c681612fdb565b60006020828403121561359f57600080fd5b5051919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b67ffffffffffffffff8311156135ed576135ed613162565b613601836135fb8354613342565b83613462565b6000601f841160018114613635576000851561361d5750838201355b600019600387901b1c1916600186901b17835561368f565b600083815260209020601f19861690835b828110156136665786850135825560209485019460019092019101613646565b50868210156136835760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b818103818111156105f3576105f361337c56fe4173736574546f6b656e3a20726564656d7074696f6e52657175657374494420a2646970667358221220989008ac89cd312bd5d6e33da341ec8e16f8718e8548ca029335a2d8644fcfa464736f6c63430008130033

Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.