Address Details
contract
token

0x84e2979d56e1bE192C7b72F1dE401A15B9af3c67

Token
Proof of Attendance Verified (TICK)
Creator
0x4c546b–174345 at 0xf283eb–a929fb
Balance
0 CELO ( )
Tokens
Fetching tokens...
Transactions
978 Transactions
Transfers
0 Transfers
Gas Used
486,273,157
Last Balance Update
17468341
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
POAVToken




Optimization enabled
true
Compiler version
v0.8.7+commit.e28d00a7




Optimization runs
200
EVM Version
london




Verified at
2022-10-28T00:47:17.614188Z

POAV_C.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
pragma experimental ABIEncoderV2;
library SafeMath {
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a, "SafeMath: addition overflow");
    return c;
  }
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    return sub(a, b, "SafeMath: subtraction overflow");
  }

  function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b <= a, errorMessage);
    uint256 c = a - b;

    return c;
  }
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b, "SafeMath: multiplication overflow");

    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    return div(a, b, "SafeMath: division by zero");
  }

  function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, errorMessage);
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    return mod(a, b, "SafeMath: modulo by zero");
  }

  function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b != 0, errorMessage);
    return a % b;
  }
}
library Counters {
    using SafeMath for uint256;

    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        counter._value += 1;
    }

    function decrement(Counter storage counter) internal {
        counter._value = counter._value.sub(1);
    }
}
library ECDSA {
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;
        if (signature.length == 65) {
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
        } else if (signature.length == 64) {
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            // solhint-disable-next-line no-inline-assembly
            assembly {
                let vs := mload(add(signature, 0x40))
                r := mload(add(signature, 0x20))
                s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
                v := add(shr(255, vs), 27)
            }
        } else {
            revert("ECDSA: invalid signature length");
        }

        return recover(hash, v, r, s);
    }
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value");
        require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");
        address signer = ecrecover(hash, v, r, s);
        require(signer != address(0), "ECDSA: invalid signature");
        return signer;
    }
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}
contract Ownable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev The Ownable constructor sets the original `owner` of the contract to the sender
     * account.
     */
    constructor ()  {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), _owner);
    }

    /**
     * @return the address of the owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner());
        _;
    }

    /**
     * @return true if `msg.sender` is the owner of the contract.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == _owner;
    }

    /**
     * @dev Allows the current owner to relinquish control of the contract.
     * It will not be possible to call the functions with the `onlyOwner`
     * modifier anymore.
     * @notice Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0));
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

library AddressUtils {
  function isContract(address _addr) internal view returns (bool addressCheck) {
    // This method relies in extcodesize, which returns 0 for contracts in
    // construction, since the code is only stored at the end of the
    // constructor execution.

    // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
    // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
    // for accounts without code, i.e. `keccak256('')`
    bytes32 codehash;
    bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
    assembly { codehash := extcodehash(_addr) } // solhint-disable-line
    addressCheck = (codehash != 0x0 && codehash != accountHash);
  }
}

contract NFToken is Ownable {
  using AddressUtils for address;
    

  /**
   * @dev List of revert message codes. Implementing dApp should handle showing the correct message.
   * Based on 0xcert framework error codes.
   */
  string constant ZERO_ADDRESS = "003001";
  string constant NOT_VALID_NFT = "003002";
  string constant NOT_OWNER_OR_OPERATOR = "003003";
  string constant NOT_OWNER_APPROVED_OR_OPERATOR = "003004";
  string constant NOT_ABLE_TO_RECEIVE_NFT = "003005";
  string constant NFT_ALREADY_EXISTS = "003006";
  string constant NOT_OWNER = "003007";
  string constant IS_OWNER = "003008";
  address contractOwner ;
  /**
   * @dev Magic value of a smart contract that can recieve NFT.
   * Equal to: bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")).
   */
  bytes4 internal constant MAGIC_ON_ERC721_RECEIVED = 0x150b7a02;

    
  /**
   * @dev A mapping from NFT ID to the address that owns it.
   */
  mapping (uint256 => address) internal idToOwner;



   /**
   * @dev Mapping from owner address to count of his tokens.
   */
  mapping (address => uint256) private ownerToNFTokenCount;

 
  modifier validNFToken(uint256 _tokenId) {
    require(idToOwner[_tokenId] != address(0), NOT_VALID_NFT);
    _;
  }


  mapping(bytes4 => bool) internal supportedInterfaces;
  constructor()  {
    supportedInterfaces[0x80ac58cd] = true; // ERC721
    supportedInterfaces[0x01ffc9a7] = true; // ERC165
  }


  function supportsInterface (bytes4 _interfaceID) external  view returns (bool) {
    return supportedInterfaces[_interfaceID];
  }

  function balancePOAVOf(address subject) external  view returns (uint256) {
    require(subject != address(0), ZERO_ADDRESS);
    return _getOwnerNFTCount(subject);
  }

  function ownerOf(uint256 _tokenId) external  view returns (address _owner) {
    _owner = idToOwner[_tokenId];
    require(_owner != address(0), NOT_VALID_NFT);
  }

  function _mint(address _to, uint256 _tokenId) internal  {
    require(_to != address(0), ZERO_ADDRESS);
    require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);
    _addNFToken(_to, _tokenId);
  }

  function _addNFToken(address _to, uint256 _tokenId) internal  {
    require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);
    idToOwner[_tokenId] = _to;
    ownerToNFTokenCount[_to] = ownerToNFTokenCount[_to] + 1;
    
  }

  function _getOwnerNFTCount(address _owner) internal  view returns (uint256) {
    return ownerToNFTokenCount[_owner];
  }

    

}

contract NFTokenMetadata is  NFToken{
  mapping (uint256 => string) internal idToUri;
  string internal  _baseURI; 
  string public name;
  string public symbol;
  uint256 public decimals;
  event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
  constructor()  {
    decimals = 0;
    
  
    supportedInterfaces[0x5b5e139f] = true; // ERC721Metadata
    _baseURI = "https://stamping.mypinata.cloud/ipfs/";
  }

  function tokenURI(uint256 _tokenId) external  view validNFToken(_tokenId) returns (string memory) {
        return bytes(_baseURI).length > 0
            ? string(abi.encodePacked(_baseURI, idToUri[_tokenId]))
            : '';

  }

  function baseURI() public view returns (string memory) {
        return _baseURI;
    }

  function setBaseURI(string calldata _uri) external onlyOwner() {
    _baseURI = _uri;
  }

  function _setTokenUri(uint256 _tokenId, string  memory _uri) internal validNFToken(_tokenId) {
     idToUri[_tokenId] = _uri;
  } 


}

contract EIP712  {
  using ECDSA for bytes32;
  bytes32 DOMAIN_SEPARATOR;
  bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
  bytes32 constant internal VERIFIABLE_CREDENTIAL_TYPEHASH = keccak256("VerifiableCredential(address issuer,address subject,bytes32 POAV,uint256 validFrom,uint256 validTo)");
  struct EIP712Domain {string name;string version;uint256 chainId;address verifyingContract;}
  constructor()  {
        DOMAIN_SEPARATOR = hashEIP712Domain(
            EIP712Domain({
                name : "EIP712Domain",
                version : "1",
                chainId : 100,
                verifyingContract : address(this)
                }));
  }
  function hashEIP712Domain(EIP712Domain memory eip712Domain) internal pure returns (bytes32) {
        return keccak256(abi.encode(EIP712DOMAIN_TYPEHASH,keccak256(bytes(eip712Domain.name)),keccak256(bytes(eip712Domain.version)),eip712Domain.chainId,eip712Domain.verifyingContract));
    }

    function hashVerifiableCredential(address _issuer,address _subject,string memory POAVURI,uint256 _validFrom,uint256 _validTo) internal pure returns (bytes32) {//0xAABBCC11223344....556677
        return keccak256(abi.encode(VERIFIABLE_CREDENTIAL_TYPEHASH,_issuer,_subject,POAVURI,_validFrom,_validTo));
    }


    function _hashForSigned(string memory _credentialSubject, address _issuer, address _subject, uint validFrom, uint validTo) internal view returns (bytes32) {
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                hashVerifiableCredential(_issuer, _subject, _credentialSubject, validFrom, validTo)
            )
        );
        return (digest);
    }
    

    function _validateSignature(string memory _credentialSubject, address _issuer, address _subject, uint validFrom, uint validTo,bytes32  _credentialHash, bytes memory _signature ) internal view 
        returns (address issuer, bytes32 hashSha256, bytes32 hashKeccak256) {
        return (_credentialHash.recover(_signature), _hashForSigned(_credentialSubject, _issuer, _subject, validFrom, validTo), 
        keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hashForSigned(_credentialSubject, _issuer, _subject, validFrom, validTo))));
    }
}
contract FANToken {
  using SafeMath for uint256;
  
  //address ==> Balance
  mapping(address => uint256) internal _balanceFANToken;
  //POAV ==> claims
  mapping(string => uint8) internal _claimFANToken;

  function balanceOf (address subject) external view returns(uint256) {
    return (_balanceFANToken[subject]);
  }

  function claimFANTokenOf (string memory POAVURI) external view returns(uint256) {
    return (_claimFANToken[POAVURI]);
  }

}
contract POAVToken is  EIP712, FANToken, NFTokenMetadata {
  using ECDSA for bytes32;
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;
    enum Status {Undefined, Active, Inactive, Revoked, StandBy}
    mapping(string => address) private issuerOfPOAV;
    mapping(string => uint256) private validFromOfPOAV;
    
    mapping(string => uint256) public countPOAVOf;
    
    mapping(string => mapping(address  => Status)) private statusOfPOAVSubject;
    uint256 private POAVURIs;
    //address=>POAVs
    struct _POAV {
        address issuer;
        uint256 id;
        string uri;
        uint8 FANToken;
        uint timestamp;
        uint256 blockNumber;
    }
    struct _POAVMetadata {
        address issuer;
        string uri;
        uint8 FANToken;
        uint validFrom;
        uint timestamp;
        uint256 blockNumber;
        bool isFreeClaim;
    }
    mapping(address => _POAV[]) private _listPOAVFromAddress;
    event minted(address indexed issuer, string indexed POAV, uint validFrom );
    event sent(address indexed issuer, string indexed POAV, address indexed subject, uint256 validFrom);
    event statusChanged(string indexed POAV, address indexed subject, Status _status);
    
    string public DAOUri;
    address public coordinatorDAO;
    address[] private _attendeesOfDAO;
    _POAVMetadata[] private _listPOAV;
    
    mapping (address => uint8) public maxFANTokenIssuer;
    mapping (address => _POAVMetadata[]) internal _listPOAVOf;
    
    //Address of Issuer => FANTokens Total;
    mapping (address => uint256) private _balanceFANTokenEmissionsOf;

    //Address of Issuer => POAV Total;
    mapping (address => uint256) private _balancePOAVEmissions;
    
    //POAV , address of subject ==> true is auth or false not Auth 
    mapping (string => mapping (address => bool)) private _claimAuth;
    uint8 private maxFUNToken;
    //constructor(uint8 _maxFUN, string memory _DAOUri, string memory _symbol)  {
      constructor()  {
      POAVURIs = 0;
      DAOUri = "NFTicket.pe";//_DAOUri;
      maxFUNToken = 100;//_maxFUN;
      coordinatorDAO = msg.sender;
      maxFANTokenIssuer[msg.sender] = 100;//_maxFUN;
      name   = "Proof of Attendance Verified";
      symbol = "TICK";//_symbol;
    }
    function getAttendeesList() external view returns (address[] memory) {
        return _attendeesOfDAO;
    }
    function balanceFANTokenEmissionsOf(address _issuer) external view returns (uint256 FANTokens) {
        return (_balanceFANTokenEmissionsOf[_issuer]);
    }
    function balancePOAVEmissionsOf(address _issuer) external view returns (uint256 POAVs) {
        return (_balancePOAVEmissions[_issuer]);
    }
    function renounceCoordinatorship() external {
         require(coordinatorDAO==msg.sender , "Does not have access");
        coordinatorDAO=address(0);
    }
    function addIssuer(address newIssuer, uint8 _maxFUN) external {
        require(coordinatorDAO==msg.sender || coordinatorDAO==address(0), "Does not have access");
        if (maxFUNToken >= _maxFUN) {
           maxFANTokenIssuer[newIssuer] = _maxFUN;
        }
    }
    /**
    * @dev List of POAVs claims by address.
   */
    function getPOAVListOf(address subject) external view returns(_POAV[] memory){
        return (_listPOAVFromAddress[subject]);
    }
    /**
    * @dev List of POAVs claims by address.
   */
    function getAllPOAVListOf() external view returns(_POAVMetadata[] memory){
        return (_listPOAV);
    }

    function getPOAVListIssuedOf(address _issuer) external view returns(_POAVMetadata[] memory){
        return (_listPOAVOf[_issuer]);
    }

    function getIssuerPOAVOf(string memory POAVURI) external view returns (address) {
      return (issuerOfPOAV[POAVURI]);
    }
    function getValidFromPOAVOf(string memory POAVURI) external view returns (uint256) {
      return (validFromOfPOAV[POAVURI]);
    }
    function getStatusPOAVOf(string memory POAVURI, address _subject) external view returns (Status) {
      return (statusOfPOAVSubject[POAVURI][_subject]);
    }
    /**
    * @dev Mint of POAVs.
      #POAVUri: CID of POAV (IPFS)
   */
    function mint(string memory POAVUri, uint8 _FANToken, bool _freeClaim) public returns (bool) {
       _mintPOAV( POAVUri, msg.sender, block.timestamp, _FANToken, _freeClaim);
        return true;
    }

    function mintEndorsed(string memory POAVURI, bytes32  _credentialHash, bytes memory _signature, uint8 _FANToken, bool _freeClaim) public returns (bool) {
        address  _issuer = _credentialHash.recover(_signature);
        require(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",hashForSigned(POAVURI, _issuer)))==_credentialHash, "Rejected POAV");
        require(_issuer!=msg.sender,"You cannot endorse from the same wallet");
        _mintPOAV(POAVURI, _issuer, block.timestamp, _FANToken, _freeClaim);
        return true;
    }

    function _mintPOAV(string memory POAVURI, address _issuer, uint256 _validFrom, uint8 _FanToken,bool _freeClaim) private returns (bool) {
        require(issuerOfPOAV[POAVURI] == address(0), "POAV already exists");
        require(maxFANTokenIssuer[_issuer] >= _FanToken, "Exceeds the MAXFUN allowed in the DAO or the sender has no access");
        _balancePOAVEmissions[_issuer]++;
        issuerOfPOAV[POAVURI] = _issuer;
        _claimAuth[POAVURI][msg.sender]=_freeClaim;
        validFromOfPOAV[POAVURI] = _validFrom;
        POAVURIs++;
        _POAVMetadata memory _poavmetadata = _POAVMetadata(
            _issuer,
            POAVURI,
            _FanToken,
            _validFrom,
            block.timestamp,
            block.number,
            _freeClaim
        );
        _listPOAVOf[_issuer].push(_poavmetadata);
        _listPOAV.push(_poavmetadata);
        _claimFANToken[POAVURI] = _FanToken;
        emit minted(_issuer, POAVURI, _validFrom);
        return true;
    } 

    //EIP712    
    function hashForSigned(string memory POAVURI, address _subject) public view returns (bytes32) {
      return (_hashForSigned(POAVURI,issuerOfPOAV[POAVURI], _subject, validFromOfPOAV[POAVURI], validFromOfPOAV[POAVURI]+252478800 ));
    }

    
    function validateSignature(
      string memory POAVURI, 
      address _subject, 
      bytes32  _credentialHash, 
      bytes memory _signature ) external view 
        returns (address issuer, bytes32 hashKeccak256) {
        return (_credentialHash.recover(_signature), 
        keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hashForSigned(POAVURI, issuerOfPOAV[POAVURI], _subject,validFromOfPOAV[POAVURI], validFromOfPOAV[POAVURI]+252478800))));
    }

    function close(string memory POAVURI) public returns (bool) {
        require(issuerOfPOAV[POAVURI]==msg.sender, "Does not have access");
        issuerOfPOAV[POAVURI] = address(0);
        return true;
    }

    function changeStatus(string memory POAVURI, address _subject, Status _status) public returns (bool) {
        require(issuerOfPOAV[POAVURI]==msg.sender, "Does not have access");
        require(statusOfPOAVSubject[POAVURI][_subject] != _status, "There is no change of state");
        statusOfPOAVSubject[POAVURI][_subject] = _status;
        emit statusChanged(POAVURI, _subject, _status);
        return true;
    }
    
    function burn(string memory POAVURI) public returns (bool) {
        require(issuerOfPOAV[POAVURI]==msg.sender, "Does not have access");
        delete issuerOfPOAV[POAVURI];
        delete validFromOfPOAV[POAVURI] ;
        return true;
    }

    function sendToBatchEndorsed(string memory POAVURI, address[] memory _subjects, bytes32  _credentialHash, bytes memory _signature) public returns (bool) {
        address  _issuer = _credentialHash.recover(_signature);
        require(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",hashForSigned(POAVURI, _issuer)))==_credentialHash, "Rejected POAV");
        require(_issuer!=msg.sender,"You cannot endorse from the same wallet");
        
        require(issuerOfPOAV[POAVURI]==_issuer, "Does not have access");
        for(uint256 indx = 0; indx < _subjects.length; indx++) {
            _claim(POAVURI, _subjects[indx]);
        }
        return (true);
    }

    function sendToBatch(string memory POAVURI, address[] memory _subjects) public returns (bool) {
        require(issuerOfPOAV[POAVURI]==msg.sender, "Does not have access");
        for(uint256 indx = 0; indx < _subjects.length; indx++) {
            _claim(POAVURI, _subjects[indx]);
        }
        return (true);
    }

    function sendToEndorsed(string memory POAVURI, address _subject, bytes32  _credentialHash, bytes memory _signature) public returns (uint256) {
        address  _issuer = _credentialHash.recover(_signature);
        require(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",hashForSigned(POAVURI, _subject)))==_credentialHash, "Rejected POAV");
        require(_issuer!=msg.sender,"You cannot endorse from the same wallet");
        require(issuerOfPOAV[POAVURI]==_issuer, "Does not have access");
        
        return (_claim(POAVURI, _subject));
    }

    function sendTo(string memory POAVURI, address _subject) public returns (uint256) {
        require(issuerOfPOAV[POAVURI]==msg.sender, "Does not have access");
        return (_claim(POAVURI, _subject));
    }

  
    function claim(string memory POAVURI) public returns (uint256) {
        require(_claimAuth[POAVURI][issuerOfPOAV[POAVURI]]==true, "Subject: Does not have access");
        return (_claim(POAVURI, msg.sender));
    }
    
    function claimEndorsed(string memory POAVURI, address _ZPK, bytes32  _credentialHash, bytes memory _signature ) public returns (uint256) {
        require((issuerOfPOAV[POAVURI]!=address(0) && issuerOfPOAV[POAVURI]==_credentialHash.recover(_signature)), "Does not have access");
        require(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",hashForSigned(POAVURI, _ZPK)))==_credentialHash, "Rejected POAV");
        return (_claim(POAVURI, msg.sender));
    }

    function claimCodeEndorsed(string memory POAVURI,  bytes32 _credentialHash, bytes memory _signature ) public returns (uint256) {
        require((issuerOfPOAV[POAVURI]!=address(0) && issuerOfPOAV[POAVURI]==_credentialHash.recover(_signature)), "Does not have access");
        require(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",POAVURI))==_credentialHash, "Rejected POAV");
        return (_claim(POAVURI, msg.sender));
    }


 /*
    function claimCodeZKPEndorsed(string memory POAVURI, uint8 code , bytes32 _credentialHash, bytes memory _signature ) public returns (uint256) {
        require((issuerOfPOAV[POAVURI]!=address(0) && issuerOfPOAV[POAVURI]==_credentialHash.recover(_signature)), "Does not have access");
        require(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",POAVURI, code))==_credentialHash, "Rejected POAV");
        return (_claim(POAVURI, msg.sender));
    }*/

    function _claim(string memory POAVURI, address _subject) private returns (uint256) {
         require(issuerOfPOAV[POAVURI]!=_subject, "Can't self-certify");
         require(statusOfPOAVSubject[POAVURI][_subject]==Status.Undefined, "You can only get a POAV");
         
        countPOAVOf[POAVURI]++;

        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(_subject, newItemId);
        _balanceFANTokenEmissionsOf[issuerOfPOAV[POAVURI]]=_balanceFANTokenEmissionsOf[issuerOfPOAV[POAVURI]]+(_claimFANToken[POAVURI]);
        _setTokenUri(newItemId, POAVURI);
        statusOfPOAVSubject[POAVURI][_subject] = Status.Active;
        _POAV memory _poav=_POAV(issuerOfPOAV[POAVURI], newItemId, POAVURI, _claimFANToken[POAVURI], block.timestamp, block.number);
        _listPOAVFromAddress[_subject].push(_poav);

        //if (keccak256(abi.encode(DAOOf[POAVURI])) != keccak256(abi.encode("")) && !attendeeOfDAO[_subject][DAOOf[POAVURI]]) {
          //attendeeOfDAO[_subject][DAOOf[POAVURI]] = true; 
          //_balanceOfDAO[_subject]++;
        //}

        _addAttendees(_subject);
        _balanceFANToken [_subject] = _claimFANToken[POAVURI];
        emit Transfer(issuerOfPOAV[POAVURI], _subject, newItemId);
        emit sent(issuerOfPOAV[POAVURI], POAVURI, _subject, validFromOfPOAV[POAVURI]);
        return newItemId;
    }
    function _addAttendees(address _subject) internal {
      bool  notFound;
        notFound=true;
        
        for(uint256 indx = 0; indx < _attendeesOfDAO.length; indx++) {
            if (_attendeesOfDAO[indx]==_subject) {
              notFound=false;
              break;
            }
            
        }
        if (notFound) {
          _attendeesOfDAO.push(_subject);
        }
        
    }
    function totalSupply() external  view returns (uint256) {
      return _tokenIds.current();
    }
    function totalPOAVs() external  view returns (uint256) {
      return POAVURIs;
    }
    function totalAttendees() external  view returns (uint256) {
      return  _attendeesOfDAO.length;
    }

   
    

}       
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"_from","internalType":"address","indexed":true},{"type":"address","name":"_to","internalType":"address","indexed":true},{"type":"uint256","name":"_tokenId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"minted","inputs":[{"type":"address","name":"issuer","internalType":"address","indexed":true},{"type":"string","name":"POAV","internalType":"string","indexed":true},{"type":"uint256","name":"validFrom","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"sent","inputs":[{"type":"address","name":"issuer","internalType":"address","indexed":true},{"type":"string","name":"POAV","internalType":"string","indexed":true},{"type":"address","name":"subject","internalType":"address","indexed":true},{"type":"uint256","name":"validFrom","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"statusChanged","inputs":[{"type":"string","name":"POAV","internalType":"string","indexed":true},{"type":"address","name":"subject","internalType":"address","indexed":true},{"type":"uint8","name":"_status","internalType":"enum POAVToken.Status","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"DAOUri","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addIssuer","inputs":[{"type":"address","name":"newIssuer","internalType":"address"},{"type":"uint8","name":"_maxFUN","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"FANTokens","internalType":"uint256"}],"name":"balanceFANTokenEmissionsOf","inputs":[{"type":"address","name":"_issuer","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"subject","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"POAVs","internalType":"uint256"}],"name":"balancePOAVEmissionsOf","inputs":[{"type":"address","name":"_issuer","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balancePOAVOf","inputs":[{"type":"address","name":"subject","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"baseURI","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"burn","inputs":[{"type":"string","name":"POAVURI","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"changeStatus","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address","name":"_subject","internalType":"address"},{"type":"uint8","name":"_status","internalType":"enum POAVToken.Status"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"claim","inputs":[{"type":"string","name":"POAVURI","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"claimCodeEndorsed","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"bytes32","name":"_credentialHash","internalType":"bytes32"},{"type":"bytes","name":"_signature","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"claimEndorsed","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address","name":"_ZPK","internalType":"address"},{"type":"bytes32","name":"_credentialHash","internalType":"bytes32"},{"type":"bytes","name":"_signature","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"claimFANTokenOf","inputs":[{"type":"string","name":"POAVURI","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"close","inputs":[{"type":"string","name":"POAVURI","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"coordinatorDAO","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"countPOAVOf","inputs":[{"type":"string","name":"","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct POAVToken._POAVMetadata[]","components":[{"type":"address","name":"issuer","internalType":"address"},{"type":"string","name":"uri","internalType":"string"},{"type":"uint8","name":"FANToken","internalType":"uint8"},{"type":"uint256","name":"validFrom","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bool","name":"isFreeClaim","internalType":"bool"}]}],"name":"getAllPOAVListOf","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getAttendeesList","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getIssuerPOAVOf","inputs":[{"type":"string","name":"POAVURI","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct POAVToken._POAVMetadata[]","components":[{"type":"address","name":"issuer","internalType":"address"},{"type":"string","name":"uri","internalType":"string"},{"type":"uint8","name":"FANToken","internalType":"uint8"},{"type":"uint256","name":"validFrom","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bool","name":"isFreeClaim","internalType":"bool"}]}],"name":"getPOAVListIssuedOf","inputs":[{"type":"address","name":"_issuer","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct POAVToken._POAV[]","components":[{"type":"address","name":"issuer","internalType":"address"},{"type":"uint256","name":"id","internalType":"uint256"},{"type":"string","name":"uri","internalType":"string"},{"type":"uint8","name":"FANToken","internalType":"uint8"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"blockNumber","internalType":"uint256"}]}],"name":"getPOAVListOf","inputs":[{"type":"address","name":"subject","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"enum POAVToken.Status"}],"name":"getStatusPOAVOf","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address","name":"_subject","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getValidFromPOAVOf","inputs":[{"type":"string","name":"POAVURI","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"hashForSigned","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address","name":"_subject","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"maxFANTokenIssuer","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"mint","inputs":[{"type":"string","name":"POAVUri","internalType":"string"},{"type":"uint8","name":"_FANToken","internalType":"uint8"},{"type":"bool","name":"_freeClaim","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"mintEndorsed","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"bytes32","name":"_credentialHash","internalType":"bytes32"},{"type":"bytes","name":"_signature","internalType":"bytes"},{"type":"uint8","name":"_FANToken","internalType":"uint8"},{"type":"bool","name":"_freeClaim","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"_owner","internalType":"address"}],"name":"ownerOf","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceCoordinatorship","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sendTo","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address","name":"_subject","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"sendToBatch","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address[]","name":"_subjects","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"sendToBatchEndorsed","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address[]","name":"_subjects","internalType":"address[]"},{"type":"bytes32","name":"_credentialHash","internalType":"bytes32"},{"type":"bytes","name":"_signature","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sendToEndorsed","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address","name":"_subject","internalType":"address"},{"type":"bytes32","name":"_credentialHash","internalType":"bytes32"},{"type":"bytes","name":"_signature","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBaseURI","inputs":[{"type":"string","name":"_uri","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"_interfaceID","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"tokenURI","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalAttendees","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalPOAVs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"issuer","internalType":"address"},{"type":"bytes32","name":"hashKeccak256","internalType":"bytes32"}],"name":"validateSignature","inputs":[{"type":"string","name":"POAVURI","internalType":"string"},{"type":"address","name":"_subject","internalType":"address"},{"type":"bytes32","name":"_credentialHash","internalType":"bytes32"},{"type":"bytes","name":"_signature","internalType":"bytes"}]}]
            

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106102955760003560e01c80638da5cb5b11610167578063c1596fc9116100ce578063e5fd4ee211610087578063e5fd4ee214610658578063eb11a7b414610660578063f2fde38b14610675578063f3fe12c914610688578063fa085ee31461069b578063fa0fbeca146106ae57600080fd5b8063c1596fc9146105f1578063c87b56dd14610604578063ce3014b914610617578063d539012b1461062a578063dafa1d2d14610632578063e00705421461064557600080fd5b80639bc50cb1116101205780639bc50cb1146105655780639d869eac1461056d5780639e376c11146105805780639e74a957146105885780639e9101c5146105b1578063bdd3539d146105d157600080fd5b80638da5cb5b146105005780638f32d59b146105115780639061f2571461052457806392202f6e1461053757806395218dcd1461054a57806395d89b411461055d57600080fd5b8063329264b21161020b57806370a08231116101c457806370a082311461046d57806370c88a6514610496578063715018a6146104a9578063724a7bbf146104b15780638b1382fd146104da5780638c53abf2146104ed57600080fd5b8063329264b2146103bf57806340ff34ab146103f45780634ffb98d21461040757806355f804b3146104275780636352211e1461043a5780636c0360eb1461046557600080fd5b806318160ddd1161025d57806318160ddd14610348578063240bc71214610350578063281a885c1461037b57806328632acd1461038e5780632955643c146103a3578063313ce567146103b657600080fd5b806301ffc9a71461029a57806306fdde03146102dc5780630a5d288c146102f15780630dbba7f61461030357806310647e1b14610316575b600080fd5b6102c76102a8366004612c55565b6001600160e01b03191660009081526007602052604090205460ff1690565b60405190151581526020015b60405180910390f35b6102e46106c1565b6040516102d391906133f9565b6016545b6040519081526020016102d3565b6102f5610311366004612cf0565b61074f565b610329610324366004612d68565b610777565b604080516001600160a01b0390931683526020830191909152016102d3565b6102f5610837565b6102f561035e366004612cf0565b805160208183018101805160108252928201919093012091525481565b6102f5610389366004612f08565b610847565b6103a161039c366004612c22565b61093f565b005b6102f56103b1366004612d24565b6109b6565b6102f5600c5481565b6103e26103cd366004612c07565b60186020526000908152604090205460ff1681565b60405160ff90911681526020016102d3565b6102c7610402366004612f74565b610a19565b61041a610415366004612d24565b610aba565b6040516102d391906133d1565b6103a1610435366004612c7f565b610afe565b61044d61044836600461305f565b610b26565b6040516001600160a01b0390911681526020016102d3565b6102e4610b84565b6102f561047b366004612c07565b6001600160a01b031660009081526001602052604090205490565b6102f56104a4366004612cf0565b610c16565b6103a1610c41565b6102f56104bf366004612c07565b6001600160a01b03166000908152601b602052604090205490565b6102f56104e8366004612d24565b610ca2565b6102f56104fb366004612d68565b610d01565b6003546001600160a01b031661044d565b6003546001600160a01b031633146102c7565b6102f5610532366004612d68565b610deb565b6102c7610545366004612de5565b610ee4565b61044d610558366004612cf0565b611094565b6102e46110c5565b6103a16110d2565b6102c761057b366004612cf0565b61110e565b6012546102f5565b6102f5610596366004612c07565b6001600160a01b03166000908152601a602052604090205490565b6105c46105bf366004612c07565b6111a9565b6040516102d39190613232565b6105e46105df366004612c07565b611306565b6040516102d391906132eb565b6102c76105ff366004612ead565b611449565b6102e461061236600461305f565b61156e565b6102c7610625366004612e4a565b611631565b6102e46116c2565b6102c7610640366004612cf0565b6116cf565b6102f5610653366004612c07565b611777565b6105c46117df565b610668611926565b6040516102d391906131e5565b6103a1610683366004612c07565b611987565b6102f5610696366004612cf0565b6119aa565b6102c76106a9366004613002565b611a65565b60155461044d906001600160a01b031681565b600a80546106ce9061351c565b80601f01602080910402602001604051908101604052809291908181526020018280546106fa9061351c565b80156107475780601f1061071c57610100808354040283529160200191610747565b820191906000526020600020905b81548152906001019060200180831161072a57829003601f168201915b505050505081565b6000600f82604051610761919061313e565b9081526020016040518091039020549050919050565b6000806107848484611a7f565b61080487600e89604051610798919061313e565b908152604051908190036020018120546001600160a01b0316908990600f906107c2908d9061313e565b908152602001604051809103902054600f8c6040516107e1919061313e565b908152602001604051809103902054630f0c85506107ff91906134d8565b611b2b565b604051602001610814919061316f565b604051602081830303815290604052805190602001209150915094509492505050565b6000610842600d5490565b905090565b6000806001600160a01b0316600e85604051610863919061313e565b908152604051908190036020019020546001600160a01b0316148015906108c3575061088f8383611a7f565b6001600160a01b0316600e856040516108a8919061313e565b908152604051908190036020019020546001600160a01b0316145b6108e85760405162461bcd60e51b81526004016108df9061347a565b60405180910390fd5b82846040516020016108fa91906131a0565b604051602081830303815290604052805190602001201461092d5760405162461bcd60e51b81526004016108df9061340c565b6109378433611b7f565b949350505050565b6015546001600160a01b031633148061096157506015546001600160a01b0316155b61097d5760405162461bcd60e51b81526004016108df9061347a565b601d5460ff8083169116106109b2576001600160a01b0382166000908152601860205260409020805460ff191660ff83161790555b5050565b6000336001600160a01b0316600e846040516109d2919061313e565b908152604051908190036020019020546001600160a01b031614610a085760405162461bcd60e51b81526004016108df9061347a565b610a128383611b7f565b9392505050565b600080610a268686611a7f565b905085610a338883610ca2565b604051602001610a43919061316f565b6040516020818303038152906040528051906020012014610a765760405162461bcd60e51b81526004016108df9061340c565b6001600160a01b038116331415610a9f5760405162461bcd60e51b81526004016108df90613433565b610aac8782428787612048565b506001979650505050505050565b6000601183604051610acc919061313e565b908152604080519182900360209081019092206001600160a01b0385166000908152925290205460ff16905092915050565b6003546001600160a01b03163314610b1557600080fd5b610b21600983836129c2565b505050565b600081815260056020908152604091829020548251808401909352600683526518181998181960d11b918301919091526001600160a01b03169081610b7e5760405162461bcd60e51b81526004016108df91906133f9565b50919050565b606060098054610b939061351c565b80601f0160208091040260200160405190810160405280929190818152602001828054610bbf9061351c565b8015610c0c5780601f10610be157610100808354040283529160200191610c0c565b820191906000526020600020905b815481529060010190602001808311610bef57829003601f168201915b5050505050905090565b6000600282604051610c28919061313e565b9081526040519081900360200190205460ff1692915050565b6003546001600160a01b03163314610c5857600080fd5b6003546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600380546001600160a01b0319169055565b6000610a1283600e85604051610cb8919061313e565b908152604051908190036020018120546001600160a01b0316908590600f90610ce290899061313e565b908152602001604051809103902054600f886040516107e1919061313e565b600080610d0e8484611a7f565b905083610d1b8787610ca2565b604051602001610d2b919061316f565b6040516020818303038152906040528051906020012014610d5e5760405162461bcd60e51b81526004016108df9061340c565b6001600160a01b038116331415610d875760405162461bcd60e51b81526004016108df90613433565b806001600160a01b0316600e87604051610da1919061313e565b908152604051908190036020019020546001600160a01b031614610dd75760405162461bcd60e51b81526004016108df9061347a565b610de18686611b7f565b9695505050505050565b6000806001600160a01b0316600e86604051610e07919061313e565b908152604051908190036020019020546001600160a01b031614801590610e675750610e338383611a7f565b6001600160a01b0316600e86604051610e4c919061313e565b908152604051908190036020019020546001600160a01b0316145b610e835760405162461bcd60e51b81526004016108df9061347a565b82610e8e8686610ca2565b604051602001610e9e919061316f565b6040516020818303038152906040528051906020012014610ed15760405162461bcd60e51b81526004016108df9061340c565b610edb8533611b7f565b95945050505050565b6000336001600160a01b0316600e85604051610f00919061313e565b908152604051908190036020019020546001600160a01b031614610f365760405162461bcd60e51b81526004016108df9061347a565b816004811115610f4857610f48613582565b601185604051610f58919061313e565b90815260408051602092819003830190206001600160a01b0387166000908152925290205460ff166004811115610f9157610f91613582565b1415610fdf5760405162461bcd60e51b815260206004820152601b60248201527f5468657265206973206e6f206368616e6765206f66207374617465000000000060448201526064016108df565b81601185604051610ff0919061313e565b90815260408051602092819003830190206001600160a01b038716600090815292529020805460ff1916600183600481111561102e5761102e613582565b0217905550826001600160a01b03168460405161104b919061313e565b60405180910390207f36efafdb01a886e44d0a5755bb3f08d4f5759cdc36f9c33c7c86ba6e89f59ba38460405161108291906133d1565b60405180910390a35060019392505050565b6000600e826040516110a6919061313e565b908152604051908190036020019020546001600160a01b031692915050565b600b80546106ce9061351c565b6015546001600160a01b031633146110fc5760405162461bcd60e51b81526004016108df9061347a565b601580546001600160a01b0319169055565b6000336001600160a01b0316600e8360405161112a919061313e565b908152604051908190036020019020546001600160a01b0316146111605760405162461bcd60e51b81526004016108df9061347a565b6000600e83604051611172919061313e565b90815260405190819003602001902080546001600160a01b03929092166001600160a01b0319909216919091179055506001919050565b6001600160a01b0381166000908152601960209081526040808320805482518185028101850190935280835260609492939192909184015b828210156112fb5760008481526020908190206040805160e081019091526007850290910180546001600160a01b03168252600181018054929391929184019161122a9061351c565b80601f01602080910402602001604051908101604052809291908181526020018280546112569061351c565b80156112a35780601f10611278576101008083540402835291602001916112a3565b820191906000526020600020905b81548152906001019060200180831161128657829003601f168201915b5050509183525050600282015460ff90811660208084019190915260038401546040840152600484015460608401526005840154608084015260069093015416151560a09091015290825260019290920191016111e1565b505050509050919050565b6001600160a01b0381166000908152601360209081526040808320805482518185028101850190935280835260609492939192909184015b828210156112fb5760008481526020908190206040805160c0810182526006860290920180546001600160a01b03168352600181015493830193909352600283018054929392918401916113919061351c565b80601f01602080910402602001604051908101604052809291908181526020018280546113bd9061351c565b801561140a5780601f106113df5761010080835404028352916020019161140a565b820191906000526020600020905b8154815290600101906020018083116113ed57829003601f168201915b5050509183525050600382015460ff1660208083019190915260048301546040830152600590920154606090910152908252600192909201910161133e565b6000806114568484611a7f565b9050836114638783610ca2565b604051602001611473919061316f565b60405160208183030381529060405280519060200120146114a65760405162461bcd60e51b81526004016108df9061340c565b6001600160a01b0381163314156114cf5760405162461bcd60e51b81526004016108df90613433565b806001600160a01b0316600e876040516114e9919061313e565b908152604051908190036020019020546001600160a01b03161461151f5760405162461bcd60e51b81526004016108df9061347a565b60005b85518110156115615761154e8787838151811061154157611541613598565b6020026020010151611b7f565b508061155981613551565b915050611522565b5060019695505050505050565b600081815260056020908152604091829020548251808401909352600683526518181998181960d11b9183019190915260609183916001600160a01b03166115c95760405162461bcd60e51b81526004016108df91906133f9565b506000600980546115d99061351c565b9050116115f55760405180602001604052806000815250610a12565b60096008600085815260200190815260200160002060405160200161161b92919061315a565b6040516020818303038152906040529392505050565b6000336001600160a01b0316600e8460405161164d919061313e565b908152604051908190036020019020546001600160a01b0316146116835760405162461bcd60e51b81526004016108df9061347a565b60005b82518110156116b8576116a58484838151811061154157611541613598565b50806116b081613551565b915050611686565b5060019392505050565b601480546106ce9061351c565b6000336001600160a01b0316600e836040516116eb919061313e565b908152604051908190036020019020546001600160a01b0316146117215760405162461bcd60e51b81526004016108df9061347a565b600e82604051611731919061313e565b90815260405190819003602001812080546001600160a01b0319169055600f9061175c90849061313e565b90815260200160405180910390206000905560019050919050565b60408051808201909152600681526530303330303160d01b60208201526000906001600160a01b0383166117be5760405162461bcd60e51b81526004016108df91906133f9565b506001600160a01b0382166000908152600660205260409020545b92915050565b60606017805480602002602001604051908101604052809291908181526020016000905b8282101561191d5760008481526020908190206040805160e081019091526007850290910180546001600160a01b03168252600181018054929391929184019161184c9061351c565b80601f01602080910402602001604051908101604052809291908181526020018280546118789061351c565b80156118c55780601f1061189a576101008083540402835291602001916118c5565b820191906000526020600020905b8154815290600101906020018083116118a857829003601f168201915b5050509183525050600282015460ff90811660208084019190915260038401546040840152600484015460608401526005840154608084015260069093015416151560a0909101529082526001929092019101611803565b50505050905090565b60606016805480602002602001604051908101604052809291908181526020018280548015610c0c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611960575050505050905090565b6003546001600160a01b0316331461199e57600080fd5b6119a78161249e565b50565b6000601c826040516119bc919061313e565b90815260200160405180910390206000600e846040516119dc919061313e565b90815260408051918290036020908101909220546001600160a01b0316835290820192909252016000205460ff161515600114611a5b5760405162461bcd60e51b815260206004820152601d60248201527f5375626a6563743a20446f6573206e6f7420686176652061636365737300000060448201526064016108df565b6117d98233611b7f565b6000611a748433428686612048565b506001949350505050565b600080600080845160411415611aa95750505060208201516040830151606084015160001a611b1f565b845160401415611ad75750505060408201516020830151906001600160ff1b0381169060ff1c601b01611b1f565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108df565b610de18682858561250d565b600080600054611b3e87878a88886126ad565b60405161190160f01b60208201526022810192909252604282015260620160408051808303601f190181529190528051602090910120979650505050505050565b6000816001600160a01b0316600e84604051611b9b919061313e565b908152604051908190036020019020546001600160a01b03161415611bf75760405162461bcd60e51b815260206004820152601260248201527143616e27742073656c662d6365727469667960701b60448201526064016108df565b6000601184604051611c09919061313e565b90815260408051602092819003830190206001600160a01b0386166000908152925290205460ff166004811115611c4257611c42613582565b14611c8f5760405162461bcd60e51b815260206004820152601760248201527f596f752063616e206f6e6c7920676574206120504f415600000000000000000060448201526064016108df565b601083604051611c9f919061313e565b9081526040519081900360200190208054906000611cbc83613551565b9190505550611ccb600d61270b565b6000611cd6600d5490565b9050611ce28382612728565b600284604051611cf2919061313e565b9081526040519081900360200181205460ff1690601a90600090600e90611d1a90899061313e565b9081526040805160209281900383019020546001600160a01b03168352908201929092520160002054611d4d91906134d8565b601a6000600e87604051611d61919061313e565b9081526040805160209281900383019020546001600160a01b03168352908201929092520160002055611d9481856127cf565b6001601185604051611da6919061313e565b90815260408051602092819003830190206001600160a01b038716600090815292529020805460ff19166001836004811115611de457611de4613582565b021790555060006040518060c00160405280600e87604051611e06919061313e565b908152602001604051809103902060009054906101000a90046001600160a01b03166001600160a01b03168152602001838152602001868152602001600287604051611e52919061313e565b90815260408051602092819003830190205460ff168352428383015243928101929092526001600160a01b0387811660009081526013835283812080546001808201835591835291849020865160069093020180546001600160a01b0319169290931691909117825584830151908201559183015180519394508493611ede9260028501920190612a46565b50606082015160038201805460ff191660ff9092169190911790556080820151600482015560a090910151600590910155611f188461284e565b600285604051611f28919061313e565b908152604080519182900360209081018320546001600160a01b038816600081815260019093529290912060ff90911690558391600e90611f6a90899061313e565b908152604051908190036020018120546001600160a01b0316907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90600090a4836001600160a01b031685604051611fc2919061313e565b6040518091039020600e87604051611fda919061313e565b908152604051908190036020018120546001600160a01b0316907f4b98d906844996984a06bb80d2c9292334aef00635c0f2944189b0f96c037cfe90600f90612024908b9061313e565b908152604051602091819003820181205481520160405180910390a4509392505050565b6000806001600160a01b0316600e87604051612064919061313e565b908152604051908190036020019020546001600160a01b0316146120c05760405162461bcd60e51b8152602060048201526013602482015272504f415620616c72656164792065786973747360681b60448201526064016108df565b6001600160a01b03851660009081526018602052604090205460ff8085169116101561215e5760405162461bcd60e51b815260206004820152604160248201527f4578636565647320746865204d415846554e20616c6c6f77656420696e20746860448201527f652044414f206f72207468652073656e64657220686173206e6f2061636365736064820152607360f81b608482015260a4016108df565b6001600160a01b0385166000908152601b6020526040812080549161218283613551565b919050555084600e87604051612198919061313e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081601c876040516121db919061313e565b908152604080516020928190038301812033600090815293529120805460ff1916921515929092179091558490600f9061221690899061313e565b908152604051908190036020019020556012805490600061223683613551565b90915550506040805160e0810182526001600160a01b0387811680835260208084018b815260ff891685870152606085018a90524260808601524360a086015287151560c086015260009283526019825294822080546001808201835591845292829020855160079094020180546001600160a01b0319169390941692909217835593518051939485946122d09385019290910190612a46565b50604082015160028201805460ff90921660ff19928316179055606083015160038301556080830151600483015560a0830151600583015560c090920151600690910180549115159190921617905560178054600181018255600091909152815160079091027fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c15810180546001600160a01b039093166001600160a01b031990931692909217825560208084015180518594936123b3937fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c16909101920190612a46565b506040828101516002808401805460ff90931660ff19938416179055606085015160038501556080850151600485015560a0850151600585015560c09094015160069093018054931515939091169290921790915551859190612417908a9061313e565b908152604051908190036020018120805460ff9390931660ff199093169290921790915561244690889061313e565b6040518091039020866001600160a01b03167fda5ca9645ac66535277ac302564105069251e4b09b5800f5d7978689645f2ab58760405161248991815260200190565b60405180910390a35060019695505050505050565b6001600160a01b0381166124b157600080fd5b6003546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561258a5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016108df565b8360ff16601b148061259f57508360ff16601c145b6125f65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016108df565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa15801561264a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610edb5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108df565b60007f78d766495a639e39ac46a0c4f7226dc41014051e6a16f1f2191196167c335d4a86868686866040516020016126ea9695949392919061338a565b60405160208183030381529060405280519060200120905095945050505050565b600181600001600082825461272091906134d8565b909155505050565b60408051808201909152600681526530303330303160d01b60208201526001600160a01b03831661276c5760405162461bcd60e51b81526004016108df91906133f9565b50600081815260056020908152604091829020548251808401909352600683526518181998181b60d11b918301919091526001600160a01b0316156127c45760405162461bcd60e51b81526004016108df91906133f9565b506109b28282612908565b600082815260056020908152604091829020548251808401909352600683526518181998181960d11b918301919091528391906001600160a01b03166128285760405162461bcd60e51b81526004016108df91906133f9565b506000838152600860209081526040909120835161284892850190612a46565b50505050565b600160005b6016548110156128b057826001600160a01b03166016828154811061287a5761287a613598565b6000918252602090912001546001600160a01b0316141561289e57600091506128b0565b806128a881613551565b915050612853565b5080156109b257601680546001810182556000919091527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b51242890180546001600160a01b0384166001600160a01b03199091161790555050565b600081815260056020908152604091829020548251808401909352600683526518181998181b60d11b918301919091526001600160a01b03161561295f5760405162461bcd60e51b81526004016108df91906133f9565b50600081815260056020908152604080832080546001600160a01b0319166001600160a01b038716908117909155835260069091529020546129a29060016134d8565b6001600160a01b0390921660009081526006602052604090209190915550565b8280546129ce9061351c565b90600052602060002090601f0160209004810192826129f05760008555612a36565b82601f10612a095782800160ff19823516178555612a36565b82800160010185558215612a36579182015b82811115612a36578235825591602001919060010190612a1b565b50612a42929150612aba565b5090565b828054612a529061351c565b90600052602060002090601f016020900481019282612a745760008555612a36565b82601f10612a8d57805160ff1916838001178555612a36565b82800160010185558215612a36579182015b82811115612a36578251825591602001919060010190612a9f565b5b80821115612a425760008155600101612abb565b80356001600160a01b0381168114612ae657600080fd5b919050565b600082601f830112612afc57600080fd5b813560206001600160401b03821115612b1757612b176135ae565b8160051b612b268282016134a8565b838152828101908684018388018501891015612b4157600080fd5b600093505b85841015612b6b57612b5781612acf565b835260019390930192918401918401612b46565b50979650505050505050565b80358015158114612ae657600080fd5b600082601f830112612b9857600080fd5b81356001600160401b03811115612bb157612bb16135ae565b612bc4601f8201601f19166020016134a8565b818152846020838601011115612bd957600080fd5b816020850160208301376000918101602001919091529392505050565b803560ff81168114612ae657600080fd5b600060208284031215612c1957600080fd5b610a1282612acf565b60008060408385031215612c3557600080fd5b612c3e83612acf565b9150612c4c60208401612bf6565b90509250929050565b600060208284031215612c6757600080fd5b81356001600160e01b031981168114610a1257600080fd5b60008060208385031215612c9257600080fd5b82356001600160401b0380821115612ca957600080fd5b818501915085601f830112612cbd57600080fd5b813581811115612ccc57600080fd5b866020828501011115612cde57600080fd5b60209290920196919550909350505050565b600060208284031215612d0257600080fd5b81356001600160401b03811115612d1857600080fd5b61093784828501612b87565b60008060408385031215612d3757600080fd5b82356001600160401b03811115612d4d57600080fd5b612d5985828601612b87565b925050612c4c60208401612acf565b60008060008060808587031215612d7e57600080fd5b84356001600160401b0380821115612d9557600080fd5b612da188838901612b87565b9550612daf60208801612acf565b9450604087013593506060870135915080821115612dcc57600080fd5b50612dd987828801612b87565b91505092959194509250565b600080600060608486031215612dfa57600080fd5b83356001600160401b03811115612e1057600080fd5b612e1c86828701612b87565b935050612e2b60208501612acf565b9150604084013560058110612e3f57600080fd5b809150509250925092565b60008060408385031215612e5d57600080fd5b82356001600160401b0380821115612e7457600080fd5b612e8086838701612b87565b93506020850135915080821115612e9657600080fd5b50612ea385828601612aeb565b9150509250929050565b60008060008060808587031215612ec357600080fd5b84356001600160401b0380821115612eda57600080fd5b612ee688838901612b87565b95506020870135915080821115612efc57600080fd5b612daf88838901612aeb565b600080600060608486031215612f1d57600080fd5b83356001600160401b0380821115612f3457600080fd5b612f4087838801612b87565b9450602086013593506040860135915080821115612f5d57600080fd5b50612f6a86828701612b87565b9150509250925092565b600080600080600060a08688031215612f8c57600080fd5b85356001600160401b0380821115612fa357600080fd5b612faf89838a01612b87565b9650602088013595506040880135915080821115612fcc57600080fd5b50612fd988828901612b87565b935050612fe860608701612bf6565b9150612ff660808701612b77565b90509295509295909350565b60008060006060848603121561301757600080fd5b83356001600160401b0381111561302d57600080fd5b61303986828701612b87565b93505061304860208501612bf6565b915061305660408501612b77565b90509250925092565b60006020828403121561307157600080fd5b5035919050565b600081518084526130908160208601602086016134f0565b601f01601f19169290920160200192915050565b8054600090600181811c90808316806130be57607f831692505b60208084108214156130e057634e487b7160e01b600052602260045260246000fd5b8180156130f4576001811461310557613132565b60ff19861689528489019650613132565b60008881526020902060005b8681101561312a5781548b820152908501908301613111565b505084890196505b50505050505092915050565b600082516131508184602087016134f0565b9190910192915050565b600061093761316983866130a4565b846130a4565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152600082516131d881601c8501602087016134f0565b91909101601c0192915050565b6020808252825182820181905260009190848201906040850190845b818110156132265783516001600160a01b031683529284019291840191600101613201565b50909695505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156132dd57888303603f19018552815180516001600160a01b031684528781015160e08986018190529061329282870182613078565b838a015160ff16878b0152606080850151908801526080808501519088015260a0808501519088015260c0938401511515939096019290925250509386019390860190600101613259565b509098975050505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156132dd57888303603f19018552815180516001600160a01b0316845287810151888501528681015160c08886018190529061335382870182613078565b60608481015160ff16908801526080808501519088015260a093840151939096019290925250509386019390860190600101613312565b8681526001600160a01b0386811660208301528516604082015260c0606082018190526000906133bc90830186613078565b60808301949094525060a00152949350505050565b60208101600583106133f357634e487b7160e01b600052602160045260246000fd5b91905290565b602081526000610a126020830184613078565b6020808252600d908201526c2932b532b1ba32b2102827a0ab60991b604082015260600190565b60208082526027908201527f596f752063616e6e6f7420656e646f7273652066726f6d207468652073616d65604082015266081dd85b1b195d60ca1b606082015260800190565b602080825260149082015273446f6573206e6f7420686176652061636365737360601b604082015260600190565b604051601f8201601f191681016001600160401b03811182821017156134d0576134d06135ae565b604052919050565b600082198211156134eb576134eb61356c565b500190565b60005b8381101561350b5781810151838201526020016134f3565b838111156128485750506000910152565b600181811c9082168061353057607f821691505b60208210811415610b7e57634e487b7160e01b600052602260045260246000fd5b60006000198214156135655761356561356c565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea26469706673582212203d45f502f33c3858ee95b220ed049b56b12b56d82123520a42657ee4c328813f64736f6c63430008070033