Latest 25 transactions from a total of 105 transactions

TxHash Age From To Value [TxFee]
0x63ac0f295892fead790cf109590f783369cd688c6bbcb5efb2b51f5ee42d0e5810 days 14 hrs ago0xe7f77784f8950057b1a59278721c3f40dd00d0f4  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.01 Ether0.000103334
0xac736bd2af1e78c3efce5a5ee8d8c6136eb4f17f7839b5ebb21a4f2bdf3a771e10 days 14 hrs ago0xabebc28150fb61c9e59c42930059dc2434e7e0cf  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000058592
0x3d6ec7c468ccaca3e47ec65df19ba93580819d1d220f2e82426c2f8b1d1ebcd410 days 14 hrs ago0xabebc28150fb61c9e59c42930059dc2434e7e0cf  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000058592
0xa26126fb246c3df488c72dc2107b1f3333714aedb5910f27d64c63d3df65725010 days 14 hrs ago0xabebc28150fb61c9e59c42930059dc2434e7e0cf  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000058592
0x22577e99edc9c3c74a8cf235119ec63a772bdff4dcb2c3f0c9ff3f5f86c9697910 days 17 hrs ago0xbbe33f08018f97351f0fe076ec20ce9830e03832  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000059104
0x935197aba6b8e797ce619d3b344644220caca22e8d32627729b11762b39ac18f12 days 11 hrs ago0x999fed035a707726915196a44675c049db14cc1c  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000058976
0x8f5a962ef2a615bc729c0c4615c9a8af0b6197e70c63e87d58944cfb5c9ea88312 days 11 hrs ago0x5cbe9f00693f8c783de8e51f6251312e2f835753  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.00005872
0x3e9e457f0c583fb038128ef9e166cff215fd2440af64a58624c9ba86305b6bfc12 days 11 hrs ago0x8978548c3e715eca32c3df58d0519b4252908135  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30 Ether0.00041796
0x6e6e63190c77e481ef4fdf12596827b9d64f82d228f08ffd7c3bae5e8c453abb27 days 11 hrs ago0xb3d8667870484352818fa4abdfdc51098cb55848  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000028673
0x7b21d6d8390c9b61a527c0351ecef3f7b0a921a7f5b71c3e1b8c23360e188cc928 days 18 hrs ago0xb3d8667870484352818fa4abdfdc51098cb55848  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000029057
0x1afa6eaccfd5ffca917bb9821a81110ec06bfb5125cf9e496c009903265bde1634 days 16 hrs ago0xaf01c787b14771ac6a0f8fc5474aafa2c456b23f  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.001 Ether0.000122534
0x330133b2781e18d4383ceb9e23e22cfd4a194d9fe4ffc6e3f6b85fb3c8b288d534 days 16 hrs ago0xaf01c787b14771ac6a0f8fc5474aafa2c456b23f  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000059104
0xbea42b185e5d3357ee8826d1b9322995b6e17792cfa2d1538bfc7934bcc99b5734 days 16 hrs ago0x8978548c3e715eca32c3df58d0519b4252908135  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30 Ether0.00041796
0x988660e74aac1a64b9b31ddd8ab5ba2d0247fc0737d86ce2a86b087dc5cedb6a35 days 17 hrs ago0xf58964b6e93ff9052bbe513b654d913b789297a6  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30 Ether0.000525245
0x2081e7fc462c782ec3323a155f496279b77c9f594346dd1f9316dbda7fb288d935 days 17 hrs ago0xb3d8667870484352818fa4abdfdc51098cb55848  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000132246
0x6a2ed5e28d5eaba15c4a0307057b5650007c153216f3e9aa11d0553ca20f473e35 days 18 hrs ago0xf58964b6e93ff9052bbe513b654d913b789297a6  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30 Ether0.000055346
0x1aa1b44ca57541df6ce8e35bf379ff8718045b0d22cb108238208e97dfb71f5435 days 18 hrs ago0xb3d8667870484352818fa4abdfdc51098cb55848  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000132246
0x1bcdad1b928d1c6ce6827deb1d48188730f5f86f9259fbf4bbdbe9538ae669c235 days 18 hrs ago0xf58964b6e93ff9052bbe513b654d913b789297a6  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30 Ether0.000070346
0xac0cd15835f631eb3e23eea9b89adb4210d5669113af2f97ca56afff910b2b0135 days 18 hrs ago0xb3d8667870484352818fa4abdfdc51098cb55848  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000147246
0x907b9fafdb84e924f5fe886957f965e8c732718d2e83e8102ae7e2781d2aa9eb35 days 18 hrs ago0xb3d8667870484352818fa4abdfdc51098cb55848  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30 Ether0.000090375
0x9dfdb1abcc451321e60448151e3e206fff223a06d0bd214f7f77f4186a8c050035 days 18 hrs ago0xa6958bf33e8a07fb858be6a5de1a9af6e4acb22f  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30 Ether0.000070346
0x91951e315f39570577f0937c57646325e6da9c7ef75363f10d99225c2812429135 days 18 hrs ago0xb3d8667870484352818fa4abdfdc51098cb55848  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000058848
0x0a3088c897fb1b9cc4b7efdc76670b528e0dce30b56b9342c5d7a84effaf64c036 days 18 hrs ago0xec9d96c6dbd6b49536288bef492475987142b556  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.01 Ether0.000137534
0xd935ee86e44f73a09aaa6f058ccc953be59977c85debf7827f5351babf24933b36 days 18 hrs ago0xec9d96c6dbd6b49536288bef492475987142b556  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30.035 Ether0.000059552
0xdff959ff3d5205b9a4da93a928a4d076d071ee143d36714733ac389cb52355e736 days 19 hrs ago0x8978548c3e715eca32c3df58d0519b4252908135  IN   0x54a2b9b26809df492d4e95ae40cbe053bafc33b30 Ether0.00041796
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
 Latest 25 Internal Txns, Click here To View More View All
ParentTxHash Block Age From To Value
0x63ac0f295892fead790cf109590f783369cd688c6bbcb5efb2b51f5ee42d0e58367899210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xb8f156a49d388c56918b9366f54c88ff163c3a820.0085 Ether
0x63ac0f295892fead790cf109590f783369cd688c6bbcb5efb2b51f5ee42d0e58367899210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.0015 Ether
0x63ac0f295892fead790cf109590f783369cd688c6bbcb5efb2b51f5ee42d0e58367899210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x63ac0f295892fead790cf109590f783369cd688c6bbcb5efb2b51f5ee42d0e58367899210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x63ac0f295892fead790cf109590f783369cd688c6bbcb5efb2b51f5ee42d0e58367899210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0xac736bd2af1e78c3efce5a5ee8d8c6136eb4f17f7839b5ebb21a4f2bdf3a771e367895710 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.035 Ether
0xac736bd2af1e78c3efce5a5ee8d8c6136eb4f17f7839b5ebb21a4f2bdf3a771e367895710 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x3d6ec7c468ccaca3e47ec65df19ba93580819d1d220f2e82426c2f8b1d1ebcd4367895210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.035 Ether
0x3d6ec7c468ccaca3e47ec65df19ba93580819d1d220f2e82426c2f8b1d1ebcd4367895210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0xa26126fb246c3df488c72dc2107b1f3333714aedb5910f27d64c63d3df657250367888210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.035 Ether
0xa26126fb246c3df488c72dc2107b1f3333714aedb5910f27d64c63d3df657250367888210 days 14 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x22577e99edc9c3c74a8cf235119ec63a772bdff4dcb2c3f0c9ff3f5f86c96979367816910 days 17 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.035 Ether
0x22577e99edc9c3c74a8cf235119ec63a772bdff4dcb2c3f0c9ff3f5f86c96979367816910 days 17 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x935197aba6b8e797ce619d3b344644220caca22e8d32627729b11762b39ac18f366815312 days 11 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.035 Ether
0x935197aba6b8e797ce619d3b344644220caca22e8d32627729b11762b39ac18f366815312 days 11 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x8f5a962ef2a615bc729c0c4615c9a8af0b6197e70c63e87d58944cfb5c9ea883366812812 days 11 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.035 Ether
0x8f5a962ef2a615bc729c0c4615c9a8af0b6197e70c63e87d58944cfb5c9ea883366812812 days 11 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x6e6e63190c77e481ef4fdf12596827b9d64f82d228f08ffd7c3bae5e8c453abb358187627 days 11 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x7b21d6d8390c9b61a527c0351ecef3f7b0a921a7f5b71c3e1b8c23360e188cc9357442328 days 18 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x1afa6eaccfd5ffca917bb9821a81110ec06bfb5125cf9e496c009903265bde16354027734 days 16 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xc57177d17c938cc1d1b43af2a2dbf0c28c1da5440.00085 Ether
0x1afa6eaccfd5ffca917bb9821a81110ec06bfb5125cf9e496c009903265bde16354027734 days 16 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.00015 Ether
0x1afa6eaccfd5ffca917bb9821a81110ec06bfb5125cf9e496c009903265bde16354027734 days 16 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x1afa6eaccfd5ffca917bb9821a81110ec06bfb5125cf9e496c009903265bde16354027734 days 16 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x1afa6eaccfd5ffca917bb9821a81110ec06bfb5125cf9e496c009903265bde16354027734 days 16 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30xe94547cbbbe87c70d56e0cb5a641daf554f3cf520 Ether
0x330133b2781e18d4383ceb9e23e22cfd4a194d9fe4ffc6e3f6b85fb3c8b288d5354024634 days 16 hrs ago0x54a2b9b26809df492d4e95ae40cbe053bafc33b30x37f3be05f1ad28ab26286095abb3adcf8bf3005a0.035 Ether
[ Download CSV Export  ] 
Contract Source Code Verified (Similar Match)
Note: Displaying Similar Match Verified Source Code At Contract 0xac20d45c971bbecbf590fb5eac737f533b52cd41(Excluding Constructor Arguments if any)
Contract Name: Iconic
Compiler Text: v0.4.25+commit.59dbf8f1
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity ^0.4.13;

contract GalleriesStorage {
    using Pictures for Pictures.Picture;

    //TODO adjust interface ids
    /// @dev
    bytes4 internal constant INTERFACE_ID_ICONIC_MINT = bytes4(keccak256("Mint interface id"));

    mapping(uint256 => Pictures.Picture) public pictureByHash;

    mapping(uint256 => Pictures.Picture) public pendingPictureByHash;

    mapping(uint256 => int8) public visionApprovals;

    mapping(address => uint256[]) public byAuthor;

    mapping(address => uint) public addedPicturesNumByAuthor;

    IconicMint mint;

    constructor(address _mint) public {
        require(ERC165(_mint).supportsInterface(INTERFACE_ID_ICONIC_MINT));
        mint = IconicMint(_mint);
    }

    modifier pictureExists(uint256 picId){
        require(mint.tokenExists(picId));
        _;
    }

    modifier pictureDoesNotExist(uint256 picId){
        require(!mint.tokenExists(picId), "Picture should not exist" );
        _;
    }

    function _pendingPictureExists(uint256 hash)
    internal view
    returns (bool)
    {
        return pendingPictureByHash[hash].exists();
    }

}

interface IconicMint {
    function mint(address _to, uint256 _tokenId) external;

    function tokenExists(uint256 _tokenId) external view returns (bool);
}

contract PersonalGallery is GalleriesStorage {
    address vault;
    uint pictureAdditionFee;

    constructor(address _mint, uint _pictureAdditionFee, address _vault)
    GalleriesStorage(_mint)
    public
    {
        vault = _vault;
        pictureAdditionFee = _pictureAdditionFee;
    }

    using Pictures for Pictures.PersonalPicture;

    event PersonalPictureAdded(
        uint256 indexed hash,
        bytes32 name,
        address indexed owner);

    mapping(address => mapping(uint256 => Pictures.PersonalPicture)) public personalPictureByHash;

    function _personalPictureExists(address addr, uint256 hash)
    internal view
    returns (bool)
    {
        return personalPictureByHash[addr][hash].exists();
    }


    function addPersonalPicture(
        uint256 hash,
        bytes32 name
    ) public pictureDoesNotExist(hash) payable {
        require(name[0] > 0, "Picture name cannot be empty");
        require(!_personalPictureExists(msg.sender, hash), "A picture with this hash is already submitted");
        require(!_pendingPictureExists(hash), "A picture with this hash is already submitted");
        require(msg.value == pictureAdditionFee, "That'll cost you, pal!");
        personalPictureByHash[msg.sender][hash] = Pictures.PersonalPicture(name);
        vault.transfer(msg.value);
        emit PersonalPictureAdded(hash, name, msg.sender);
    }

    function getPersonalPictureInfo(uint256 hash)
    public view
    returns (uint256 _hash, bytes32 name)
    {
        Pictures.PersonalPicture storage pic = personalPictureByHash[msg.sender][hash];
        require(pic.exists());
        name = pic.name;
        _hash = hash;
    }
}

library ModerationQueue {
    struct Queue {
        uint256[] data;
        uint front;
        uint back;
    }
    /// the number of elements stored in the queue.
    function length(Queue storage q) view internal returns (uint) {
        return q.back - q.front;
    }
    /// the number of elements this queue can hold
    function capacity(Queue storage q) view internal returns (uint) {
        return q.data.length - 1;
    }
    /// push a new element to the back of the queue
    function push(Queue storage q, uint256 data) internal
    {
        if ((q.back + 1) % q.data.length == q.front)
            return; // throw;
        q.data[q.back] = data;
        q.back = (q.back + 1) % q.data.length;
    }
    /// remove and return the element at the front of the queue
    function pop(Queue storage q) internal returns (uint256 r)
    {
        if (q.back == q.front)
            return; // throw;
        r = q.data[q.front];
        delete q.data[q.front];
        q.front = (q.front + 1) % q.data.length;
    }
    /// return the element at the front of the queue
    function peek(Queue storage q) internal view returns (uint256 r)
    {
        if (q.back == q.front)
            return; // throw;
        r = q.data[q.front];
    }

    function byIndex(Queue storage q, uint index) internal view returns (uint256 r)
    {
        if (index >= length(q))
            return; // throw;
        uint i = (q.front + index) % q.data.length;
        r = q.data[i];
    }

    function clear(Queue storage q) internal
    {
        uint l = length(q);
        for (uint i=0; i<l; i++) {
            pop(q);
        }
    }
}

library Pictures {
    uint8 public constant MAX_PICTURE_NAME_LENGTH = 32;

    struct Picture {
        bytes32 name;
        address artist;
        uint128 price;
    }

    struct PictureInit {
        bytes32 name;
        uint128 price;
    }

    struct PersonalPicture {
        bytes32 name;
    }

    function exists(Picture storage picture)
    internal view
    returns (bool)
    {
        return picture.name[0] > 0;
    }

    function exists(PersonalPicture storage personalPicture)
    internal view
    returns (bool)
    {
        return personalPicture.name[0] > 0;
    }
}

contract AdminRole {
  using Roles for Roles.Role;

  event AdminAdded(address indexed account);
  event AdminRemoved(address indexed account);

  Roles.Role private admins;

  constructor() internal {
    _addAdmin(msg.sender);
  }

  modifier onlyAdmin() {
    require(isAdmin(msg.sender));
    _;
  }

  function isAdmin(address account) public view returns (bool) {
    return admins.has(account);
  }

  function addAdmin(address account) public onlyAdmin {
    _addAdmin(account);
  }

  function renounceAdmin() public {
    _removeAdmin(msg.sender);
  }

  function _addAdmin(address account) internal {
    admins.add(account);
    emit AdminAdded(account);
  }

  function _removeAdmin(address account) internal {
    admins.remove(account);
    emit AdminRemoved(account);
  }
}

contract KycRole is AdminRole {
    using Roles for Roles.Role;

    event KycServiceAdded(address indexed account);
    event KycServiceRemoved(address indexed account);

    Roles.Role private kycServices;

    modifier onlyKycService() {
        require(isKycService(msg.sender));
        _;
    }

    function isKycService(address account) public view returns (bool) {
        return kycServices.has(account);
    }

    function addKycService(address account) public onlyAdmin {
        _addKycService(account);
    }

    function _addKycService(address account) internal {
        kycServices.add(account);
        emit KycServiceAdded(account);
    }

    function _removeKycService(address account) internal {
        kycServices.remove(account);
        emit KycServiceRemoved(account);
    }
}

contract ArtistRole is KycRole {
    using Roles for Roles.Role;

    event ArtistAdded(address indexed account);
//    event ArtistRemoved(address indexed account);

    Roles.Role private artists;

    modifier onlyArtist() {
        require(isArtist(msg.sender));
        _;
    }

    modifier nonArtist() {
        require(!isArtist(msg.sender));
        _;
    }

    function isArtist(address account) public view returns (bool) {
        return artists.has(account);
    }

    function addArtist(address account) public onlyKycService {
        _addArtist(account);
    }

    function _addArtist(address account) internal {
        artists.add(account);
        emit ArtistAdded(account);
    }
}

contract BuyerRole is KycRole {
    using Roles for Roles.Role;

    event BuyerAdded(address indexed account);
//    event BuyerRemoved(address indexed account);

    Roles.Role private buyers;

    modifier onlyBuyer() {
        require(isBuyer(msg.sender));
        _;
    }

    function isBuyer(address account) public view returns (bool) {
        return buyers.has(account);
    }

    function addBuyer(address account) public onlyKycService {
        _addBuyer(account);
    }

    function _addBuyer(address account) internal {
        buyers.add(account);
        emit BuyerAdded(account);
    }
}

contract ArtistApproval is BuyerRole, ArtistRole, GalleriesStorage{
    using ModerationQueue for ModerationQueue.Queue;

    struct Application {
        uint256[] hashes;
        bytes32[] names;
        uint128[] prices;
    }

    mapping(address => Application) private artistApplications;
    ModerationQueue.Queue moderationQueue;

    constructor() public {
        moderationQueue.data.length = 100;
    }

    function applyForArtist(uint256[] hashes, bytes32[] names, uint128[] prices)
    public
    onlyBuyer
    nonArtist
    {
        for (uint i = 0; i < hashes.length; i++) {
            require(!mint.tokenExists(hashes[i]), 'Cannot include existing pictures in artist application portfolio');
            require(names[i][0] > 0, 'Artist application portfolio require names');
        }

        artistApplications[msg.sender] = Application(hashes, names, prices);
        uint256 id = uint256(msg.sender);
        moderationQueue.push(id);

        //TODO add checks
        _addArtist(msg.sender);
    }
}

contract ModeratorRole is AdminRole {
    using Roles for Roles.Role;

    event ModeratorAdded(address indexed account);
    event ModeratorRemoved(address indexed account);

    Roles.Role private moderators;

    modifier onlyModerator() {
        require(isModerator(msg.sender));
        _;
    }

    function isModerator(address account) public view returns (bool) {
        return moderators.has(account);
    }

    function addModerator(address account) public onlyAdmin {
        _addModerator(account);
    }

    function _addModerator(address account) internal {
        moderators.add(account);
        emit ModeratorAdded(account);
    }

    function _removeModerator(address account) internal {
        moderators.remove(account);
        emit ModeratorRemoved(account);
    }
}

contract VisionRole is AdminRole{
    using Roles for Roles.Role;

    event VisionServiceAdded(address indexed account);
    event VisionServiceRemoved(address indexed account);

    Roles.Role private visionServices;

    modifier onlyVisionService() {
        require(isVisionService(msg.sender));
        _;
    }

    function isVisionService(address account) public view returns (bool) {
        return visionServices.has(account);
    }

    function addVisionService(address account) public onlyAdmin {
        _addVisionService(account);
    }

    function _addVisionService(address account) internal {
        visionServices.add(account);
        emit VisionServiceAdded(account);
    }

    function _removeVisionService(address account) internal {
        visionServices.remove(account);
        emit VisionServiceRemoved(account);
    }
}

library Roles {
  struct Role {
    mapping (address => bool) bearer;
  }

  /**
   * @dev give an account access to this role
   */
  function add(Role storage role, address account) internal {
    require(account != address(0));
    require(!has(role, account));

    role.bearer[account] = true;
  }

  /**
   * @dev remove an account's access to this role
   */
  function remove(Role storage role, address account) internal {
    require(account != address(0));
    require(has(role, account));

    role.bearer[account] = false;
  }

  /**
   * @dev check if an account has this role
   * @return bool
   */
  function has(Role storage role, address account)
    internal
    view
    returns (bool)
  {
    require(account != address(0));
    return role.bearer[account];
  }
}

interface IERC165 {

  /**
   * @notice Query if a contract implements an interface
   * @param interfaceId The interface identifier, as specified in ERC-165
   * @dev Interface identification is specified in ERC-165. This function
   * uses less than 30,000 gas.
   */
  function supportsInterface(bytes4 interfaceId)
    external
    view
    returns (bool);
}

contract ERC165 is IERC165 {

  bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7;
  /**
   * 0x01ffc9a7 ===
   *   bytes4(keccak256('supportsInterface(bytes4)'))
   */

  /**
   * @dev a mapping of interface id to whether or not it's supported
   */
  mapping(bytes4 => bool) private _supportedInterfaces;

  /**
   * @dev A contract implementing SupportsInterfaceWithLookup
   * implement ERC165 itself
   */
  constructor()
    internal
  {
    _registerInterface(_InterfaceId_ERC165);
  }

  /**
   * @dev implement supportsInterface(bytes4) using a lookup table
   */
  function supportsInterface(bytes4 interfaceId)
    external
    view
    returns (bool)
  {
    return _supportedInterfaces[interfaceId];
  }

  /**
   * @dev internal method for registering an interface
   */
  function _registerInterface(bytes4 interfaceId)
    internal
  {
    require(interfaceId != 0xffffffff);
    _supportedInterfaces[interfaceId] = true;
  }
}

contract Moderation is
ERC165,
AdminRole,
BuyerRole,
ArtistRole,
ModeratorRole,
VisionRole,
PersonalGallery,
ArtistApproval
{
    using Pictures for Pictures.Picture;
    using ModerationQueue for ModerationQueue.Queue;

    int8 constant VISION_APPROVAL_SUCCESS = 1;
    int8 constant VISION_APPROVAL_FAILURE = -1;

    //TODO adjust interface ids
    bytes4 internal constant INTERFACE_ID_ICONIC_MODERATION = bytes4(keccak256("Moderation interface id"));

    event PictureAdded(
        uint256 indexed hash,
        bytes32 name,
        address indexed artist,
        uint initialPrice);

    event PictureApproved(uint256 indexed hash);
    event PictureMadeVisible(uint256 indexed hash);

    uint8 public artistApprovalThreshold;


    ModerationQueue.Queue moderationQueue;

    constructor(address _mint, uint _pictureAdditionFee, address _vault, uint8 _artistApprovalThreshold)
    PersonalGallery(_mint, _pictureAdditionFee, _vault)
    public {
        moderationQueue.data.length = 100;
        artistApprovalThreshold = _artistApprovalThreshold;
    }


    function addPicture(
        uint256 hash,
        bytes32 name,
        uint128 initialPrice
    ) public onlyArtist pictureDoesNotExist(hash) payable {
        require(!_pendingPictureExists(hash) && msg.value == pictureAdditionFee);
        require(name[0] > 0, "Picture name cannot be empty");
        pendingPictureByHash[hash] = Pictures.Picture(name, msg.sender, initialPrice);
        moderationQueue.push(hash);
        addedPicturesNumByAuthor[msg.sender]++;
        vault.transfer(msg.value);
        emit PictureAdded(hash, name, msg.sender, initialPrice);
    }


    /**
    * @dev Returns fees required for the sender address
    *      to add pictures to both private and public galleries
    * @return uint256[] tokens in posession of the holder
    */
    function myPictureAdditionFees() external view returns (uint privateGalleryFee, uint publicGalleryFee) {
        privateGalleryFee = pictureAdditionFee;
        publicGalleryFee = pictureAdditionFee;
    }

    function getPendingPictureInfo(uint256 hash)
    public view
    returns (uint256 _hash, bytes32 name, address artist, uint128 initialPrice, int8 visionApproval)
    {
        Pictures.Picture storage pic = pendingPictureByHash[hash];
        require(pic.artist > 0 && (pic.artist == msg.sender || isModerator(msg.sender)));
        name = pic.name;
        artist = pic.artist;
        initialPrice = pic.price;
        visionApproval = visionApprovals[hash];
        _hash = hash;
    }

    function getNextPendingPictureInfo()
    public view onlyModerator
    returns (uint256 _hash, bytes32 name, address artist, uint128 initialPrice, int8 visionApproval)
    {
        uint256 nextHash = moderationQueue.peek();
        return getPendingPictureInfo(nextHash);
    }

    function moderationQueueSize()
    public view onlyModerator
    returns (uint)
    {
        return moderationQueue.length();
    }

    function getPendingPicturesList(uint16 offset, uint16 limit)
    public view onlyModerator
    returns (uint256[] pendingPictures)
    {
        uint256 totalPics = moderationQueue.length();
        require(offset < totalPics);
        uint resultSize = limit;
        if(totalPics - offset < limit){
            resultSize = totalPics - offset;
        }
        uint256[] memory result = new uint256[](resultSize);

        uint i;
        for (i = 0; i < resultSize; i++) {
            result[i] = moderationQueue.byIndex(i + offset);
        }

        return result;
    }

    function setApprovedStatus(uint256 hash, bool status)
    public onlyModerator
    {
        require(hash == moderationQueue.pop(), "The picture was already removed from the moderation queue");
        delete visionApprovals[hash];

        if (status) {
            address artist = pendingPictureByHash[hash].artist;
            byAuthor[artist].push(hash);
            emit PictureApproved(hash);

            if (artistApproved(artist)) {
                transferPictureFromPending(hash);
            } else if (byAuthor[artist].length == artistApprovalThreshold) {
                approveArtist(artist);
            }
        }
    }

    function approveArtist(address artist)
    public onlyModerator
    {
        for (uint i = 0; i < byAuthor[artist].length; i++) {
            transferPictureFromPending(byAuthor[artist][i]);
        }
    }

    function artistApproved(address artist)
    public view returns (bool)
    {
        return byAuthor[artist].length > artistApprovalThreshold;
    }

    function transferPictureFromPending(uint256 hash)
    internal
    {
        Pictures.Picture storage pending = pendingPictureByHash[hash];
        pictureByHash[hash] = Pictures.Picture(pending.name, pending.artist, pending.price);
        emit PictureMadeVisible(hash);
        mint.mint(pending.artist, uint256(hash));
        delete pendingPictureByHash[hash];
    }

    function supportsInterface(bytes4 _interfaceId)
    external
    view
    returns (bool) {
        return _interfaceId == INTERFACE_ID_ICONIC_MODERATION;
    }

    function clearModerationQueue()
    external
    onlyAdmin
    {
        moderationQueue.clear();
    }

    function setVisionApproval(uint256 hash, bool status) public onlyVisionService {
        require(_pendingPictureExists(hash));
        if (status) {
            visionApprovals[hash] = VISION_APPROVAL_SUCCESS;
        } else {
            visionApprovals[hash] = VISION_APPROVAL_FAILURE;
        }
    }
}

contract Market is BuyerRole, Moderation {

    struct User {
        bytes32 email;
        bytes32 firstName;
        bytes32 lastName;
        string personalUrl;
    }

    using Pictures for Pictures.Picture;
    uint8 commissionPercentage;

    mapping(address => User) public userAt;

    bytes4 internal constant INTERFACE_ID_ERC721 = 0x80ac58cd;
    /* openzeppelin-solidity/contracts/token/ERC721/ERC721Basic.sol:12
     * 0x80ac58cd ===
     *   bytes4(keccak256('balanceOf(address)')) ^
     *   bytes4(keccak256('ownerOf(uint256)')) ^
     *   bytes4(keccak256('approve(address,uint256)')) ^
     *   bytes4(keccak256('getApproved(uint256)')) ^
     *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
     *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
     *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
     *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
     *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
     */

    event PictureSold(address indexed seller, address indexed buyer, uint256 indexed hash, uint256 price);
    event PicturePriceChanged(uint256 indexed hash, uint256 price);

    ERC721Enumerable token;

    constructor(address _token, uint8 _commissionPercentage) internal {
        require(ERC165(_token).supportsInterface(INTERFACE_ID_ERC721));
        require(_commissionPercentage >= 0 && _commissionPercentage < 100);
        commissionPercentage = _commissionPercentage;
        token = ERC721Enumerable(_token);
    }

    modifier mustBeRegistered(address _address){
        require(
            _isRegistered(_address),
                'User must be registered to get his info');
        _;
    }

    modifier mustNotBeRegistered(address _address){
        require(
            ! _isRegistered(_address),
                'Address must be not be already registered to register a new user');
        _;
    }

    function _isRegistered(address _address) internal view returns (bool) {
        return isBuyer(_address) || isArtist(_address) || isModerator(_address);
    }

    modifier onlyPictureOwner(address user, uint256 picId){
        require(msg.sender == token.ownerOf(picId), "Only the owner can edit a picture's price");
        _;
    }

    /// @notice Transfer ownership of a picture to `msg.caller` if all requirements are met.
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for the underlying NFT. Throws if
    ///  `hash` is not a valid NFT.
    /// @param hash The picture to transfer
    //TODO perform role-based check for buyers
    function buy(uint256 hash)
    public
    pictureExists(hash)
    onlyBuyer
    payable
    {
        address currentOwner = token.ownerOf(hash);
        require(msg.sender != currentOwner, "Don't waste your ether buying from yourself");
        //TODO discuss that
        Pictures.Picture storage pic = pictureByHash[hash];
        require(msg.value == pic.price, "Send exactly the amount of ether equal to the picture's price");
        token.transferFrom(currentOwner, msg.sender, hash);
        uint commission = msg.value / 100 * commissionPercentage;
        vault.transfer(commission);
        currentOwner.transfer(msg.value - commission);
        emit PictureSold(currentOwner, msg.sender, hash, pic.price);
    }


    /// @notice Sets a new price for a picture owned by the sender
    /// @dev Throws unless `msg.sender` is the current owner of the picture. Throws if
    ///  `hash` is not a valid NFT.
    /// @param hash The picture to transfer
    function setPrice(uint256 hash, uint88 newPrice)
    external
    onlyBuyer //the presumption here is that every artist is also a buyer
    pictureExists(hash)
    onlyPictureOwner(msg.sender, hash)
    {
        pictureByHash[hash].price = newPrice;
        emit PicturePriceChanged(hash, newPrice);
    }

    /** @dev Getting picture details.
      * Throws if there's no picture with the provided hash.
      * @param hash Picture id - its IPFS hash.
      * @return _hash the same hash as the input argument.
      * @return name The picture name.
      * @return artist The author of the picture.
      * @return owner The current owner.
      * @return price The current price.
      */
    function getPictureInfo(uint256 hash)
    public view
    returns (uint256 _hash, bytes32 name, address artist, address owner, uint price)
    {
        require(mint.tokenExists(hash));
        Pictures.Picture storage pic = pictureByHash[hash];
        name = pic.name;
        artist = pic.artist;
        owner = token.ownerOf(hash);
        price = pic.price;
        _hash = hash;
    }

    /** @dev Getting picture details by index.
      * Throws if there's no picture with the provided index.
      * @param index Picture index to look up.
      * @return _hash the same hash as the input argument.
      * @return name The picture name.
      * @return artist The author of the picture.
      * @return owner The current owner.
      * @return price The current price.
      */
    function getPictureInfoByIndex(uint index)
    external view returns (uint256 _hash, bytes32 name, address artist, address owner, uint price) {
        _hash = token.tokenByIndex(index);
        return getPictureInfo(_hash);
    }
}

contract Iconic is AdminRole, KycRole, Moderation, Market
{
    event UserRegistered(
        address indexed _address,
        bytes32 indexed _email,
        bytes32 _firstName,
        bytes32 indexed _lastName);

    struct Moderator {
        bytes32 email;
        bytes32 firstName;
        bytes32 lastName;
        uint256 profilePhotoHash;
    }

    mapping(address => Moderator) public moderatorAt;

    ERC721 token;

    constructor(address _token, uint _pictureAdditionFee, address _vault, uint8 _artistApprovalThreshold)
    Moderation(_token, _pictureAdditionFee, _vault, _artistApprovalThreshold)
    Market(_token, 15) public {
        require(ERC165(_token).supportsInterface(INTERFACE_ID_ERC721));
        token = ERC721(_token);
    }

    function registerBuyer(
        address _address,
        bytes32 _email,
        bytes32 _firstName,
        bytes32 _lastName,
        string _personalUrl) internal mustNotBeRegistered(_address) {

        require(_email[0] > 0, 'Email is mandatory for artist registration');
        require(_firstName[0] > 0, 'First name is mandatory for artist registration');
        require(_lastName[0] > 0, 'Last name is mandatory for artist registration');

        addBuyer(_address);
        //TODO promote buyers to artists elsewhere
        userAt[_address] = User({
            email : _email,
            firstName : _firstName,
            lastName : _lastName,
            personalUrl : _personalUrl
            });
        emit UserRegistered(_address, _email, _firstName, _lastName);
        //        token.setApprovalForAll(this, true);
    }

    function buyerKYCRegister(
        address _address,
        bytes32 _email,
        bytes32 _firstName,
        bytes32 _lastName,
        string _personalUrl) public onlyKycService {
        registerBuyer(_address, _email, _firstName, _lastName, _personalUrl);
    }

    function registerModerator(
        address moderator,
        bytes32 email,
        bytes32 firstName,
        bytes32 lastName,
        uint256 profilePhotoHash
    ) public onlyAdmin {

        require(email[0] > 0, 'Email is mandatory for artist registration');
        require(firstName[0] > 0, 'First name is mandatory for artist registration');
        require(lastName[0] > 0, 'Last name is mandatory for artist registration');

        addModerator(moderator);
        moderatorAt[moderator] = Moderator({
            email : email,
            firstName : firstName,
            lastName : lastName,
            profilePhotoHash : profilePhotoHash
            });
    }

    function getModeratorInfo(address moderator) public view returns (
        bytes32 email,
        bytes32 firstName,
        bytes32 lastName,
        uint256 profilePhotoHash
    ){
        require(moderatorAt[moderator].email[0] > 0, 'Moderator must be registered to get his info');
        return (
        moderatorAt[moderator].email,
        moderatorAt[moderator].firstName,
        moderatorAt[moderator].lastName,
        moderatorAt[moderator].profilePhotoHash
        );
    }

    function getUserData(address user) public mustBeRegistered(user) view returns (
        bytes32 email,
        bytes32 firstName,
        bytes32 lastName,
        string personalUrl,
        uint256 profilePhotoHash,
        string role
    )
    {
        role = "anonymous";

        if (isAdmin(user)) {
            role = "administrator";
        } else if (isModerator(user)) {
            role = "moderator";
            profilePhotoHash = moderatorAt[user].profilePhotoHash;
            email = moderatorAt[user].email;
            firstName = moderatorAt[user].firstName;
            lastName = moderatorAt[user].lastName;
        } else {
            if (isArtist(user)) {
                role = "artist";
            } else if (isBuyer(user)) {
                role = "buyer";
            }
            personalUrl = userAt[user].personalUrl;
            email = userAt[user].email;
            firstName = userAt[user].firstName;
            lastName = userAt[user].lastName;
        }
    }
}

library SafeMath {

  /**
  * @dev Multiplies two numbers, reverts on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b);

    return c;
  }

  /**
  * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b > 0); // Solidity only automatically asserts when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
  * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a);
    uint256 c = a - b;

    return c;
  }

  /**
  * @dev Adds two numbers, reverts on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a);

    return c;
  }

  /**
  * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
  * reverts when dividing by zero.
  */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0);
    return a % b;
  }
}

contract IERC721 is IERC165 {

  event Transfer(
    address indexed from,
    address indexed to,
    uint256 indexed tokenId
  );
  event Approval(
    address indexed owner,
    address indexed approved,
    uint256 indexed tokenId
  );
  event ApprovalForAll(
    address indexed owner,
    address indexed operator,
    bool approved
  );

  function balanceOf(address owner) public view returns (uint256 balance);
  function ownerOf(uint256 tokenId) public view returns (address owner);

  function approve(address to, uint256 tokenId) public;
  function getApproved(uint256 tokenId)
    public view returns (address operator);

  function setApprovalForAll(address operator, bool _approved) public;
  function isApprovedForAll(address owner, address operator)
    public view returns (bool);

  function transferFrom(address from, address to, uint256 tokenId) public;
  function safeTransferFrom(address from, address to, uint256 tokenId)
    public;

  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes data
  )
    public;
}

contract ERC721 is ERC165, IERC721 {

  using SafeMath for uint256;
  using Address for address;

  // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
  // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
  bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

  // Mapping from token ID to owner
  mapping (uint256 => address) private _tokenOwner;

  // Mapping from token ID to approved address
  mapping (uint256 => address) private _tokenApprovals;

  // Mapping from owner to number of owned token
  mapping (address => uint256) private _ownedTokensCount;

  // Mapping from owner to operator approvals
  mapping (address => mapping (address => bool)) private _operatorApprovals;

  bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd;
  /*
   * 0x80ac58cd ===
   *   bytes4(keccak256('balanceOf(address)')) ^
   *   bytes4(keccak256('ownerOf(uint256)')) ^
   *   bytes4(keccak256('approve(address,uint256)')) ^
   *   bytes4(keccak256('getApproved(uint256)')) ^
   *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
   *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
   *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
   *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
   *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
   */

  constructor()
    public
  {
    // register the supported interfaces to conform to ERC721 via ERC165
    _registerInterface(_InterfaceId_ERC721);
  }

  /**
   * @dev Gets the balance of the specified address
   * @param owner address to query the balance of
   * @return uint256 representing the amount owned by the passed address
   */
  function balanceOf(address owner) public view returns (uint256) {
    require(owner != address(0));
    return _ownedTokensCount[owner];
  }

  /**
   * @dev Gets the owner of the specified token ID
   * @param tokenId uint256 ID of the token to query the owner of
   * @return owner address currently marked as the owner of the given token ID
   */
  function ownerOf(uint256 tokenId) public view returns (address) {
    address owner = _tokenOwner[tokenId];
    require(owner != address(0));
    return owner;
  }

  /**
   * @dev Approves another address to transfer the given token ID
   * The zero address indicates there is no approved address.
   * There can only be one approved address per token at a given time.
   * Can only be called by the token owner or an approved operator.
   * @param to address to be approved for the given token ID
   * @param tokenId uint256 ID of the token to be approved
   */
  function approve(address to, uint256 tokenId) public {
    address owner = ownerOf(tokenId);
    require(to != owner);
    require(msg.sender == owner || isApprovedForAll(owner, msg.sender));

    _tokenApprovals[tokenId] = to;
    emit Approval(owner, to, tokenId);
  }

  /**
   * @dev Gets the approved address for a token ID, or zero if no address set
   * Reverts if the token ID does not exist.
   * @param tokenId uint256 ID of the token to query the approval of
   * @return address currently approved for the given token ID
   */
  function getApproved(uint256 tokenId) public view returns (address) {
    require(_exists(tokenId));
    return _tokenApprovals[tokenId];
  }

  /**
   * @dev Sets or unsets the approval of a given operator
   * An operator is allowed to transfer all tokens of the sender on their behalf
   * @param to operator address to set the approval
   * @param approved representing the status of the approval to be set
   */
  function setApprovalForAll(address to, bool approved) public {
    require(to != msg.sender);
    _operatorApprovals[msg.sender][to] = approved;
    emit ApprovalForAll(msg.sender, to, approved);
  }

  /**
   * @dev Tells whether an operator is approved by a given owner
   * @param owner owner address which you want to query the approval of
   * @param operator operator address which you want to query the approval of
   * @return bool whether the given operator is approved by the given owner
   */
  function isApprovedForAll(
    address owner,
    address operator
  )
    public
    view
    returns (bool)
  {
    return _operatorApprovals[owner][operator];
  }

  /**
   * @dev Transfers the ownership of a given token ID to another address
   * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
   * Requires the msg sender to be the owner, approved, or operator
   * @param from current owner of the token
   * @param to address to receive the ownership of the given token ID
   * @param tokenId uint256 ID of the token to be transferred
  */
  function transferFrom(
    address from,
    address to,
    uint256 tokenId
  )
    public
  {
    require(_isApprovedOrOwner(msg.sender, tokenId));
    require(to != address(0));

    _clearApproval(from, tokenId);
    _removeTokenFrom(from, tokenId);
    _addTokenTo(to, tokenId);

    emit Transfer(from, to, tokenId);
  }

  /**
   * @dev Safely transfers the ownership of a given token ID to another address
   * If the target address is a contract, it must implement `onERC721Received`,
   * which is called upon a safe transfer, and return the magic value
   * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
   * the transfer is reverted.
   *
   * Requires the msg sender to be the owner, approved, or operator
   * @param from current owner of the token
   * @param to address to receive the ownership of the given token ID
   * @param tokenId uint256 ID of the token to be transferred
  */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId
  )
    public
  {
    // solium-disable-next-line arg-overflow
    safeTransferFrom(from, to, tokenId, "");
  }

  /**
   * @dev Safely transfers the ownership of a given token ID to another address
   * If the target address is a contract, it must implement `onERC721Received`,
   * which is called upon a safe transfer, and return the magic value
   * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
   * the transfer is reverted.
   * Requires the msg sender to be the owner, approved, or operator
   * @param from current owner of the token
   * @param to address to receive the ownership of the given token ID
   * @param tokenId uint256 ID of the token to be transferred
   * @param _data bytes data to send along with a safe transfer check
   */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes _data
  )
    public
  {
    transferFrom(from, to, tokenId);
    // solium-disable-next-line arg-overflow
    require(_checkOnERC721Received(from, to, tokenId, _data));
  }

  /**
   * @dev Returns whether the specified token exists
   * @param tokenId uint256 ID of the token to query the existence of
   * @return whether the token exists
   */
  function _exists(uint256 tokenId) internal view returns (bool) {
    address owner = _tokenOwner[tokenId];
    return owner != address(0);
  }

  /**
   * @dev Returns whether the given spender can transfer a given token ID
   * @param spender address of the spender to query
   * @param tokenId uint256 ID of the token to be transferred
   * @return bool whether the msg.sender is approved for the given token ID,
   *  is an operator of the owner, or is the owner of the token
   */
  function _isApprovedOrOwner(
    address spender,
    uint256 tokenId
  )
    internal
    view
    returns (bool)
  {
    address owner = ownerOf(tokenId);
    // Disable solium check because of
    // https://github.com/duaraghav8/Solium/issues/175
    // solium-disable-next-line operator-whitespace
    return (
      spender == owner ||
      getApproved(tokenId) == spender ||
      isApprovedForAll(owner, spender)
    );
  }

  /**
   * @dev Internal function to mint a new token
   * Reverts if the given token ID already exists
   * @param to The address that will own the minted token
   * @param tokenId uint256 ID of the token to be minted by the msg.sender
   */
  function _mint(address to, uint256 tokenId) internal {
    require(to != address(0));
    _addTokenTo(to, tokenId);
    emit Transfer(address(0), to, tokenId);
  }

  /**
   * @dev Internal function to burn a specific token
   * Reverts if the token does not exist
   * @param tokenId uint256 ID of the token being burned by the msg.sender
   */
  function _burn(address owner, uint256 tokenId) internal {
    _clearApproval(owner, tokenId);
    _removeTokenFrom(owner, tokenId);
    emit Transfer(owner, address(0), tokenId);
  }

  /**
   * @dev Internal function to add a token ID to the list of a given address
   * Note that this function is left internal to make ERC721Enumerable possible, but is not
   * intended to be called by custom derived contracts: in particular, it emits no Transfer event.
   * @param to address representing the new owner of the given token ID
   * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
   */
  function _addTokenTo(address to, uint256 tokenId) internal {
    require(_tokenOwner[tokenId] == address(0));
    _tokenOwner[tokenId] = to;
    _ownedTokensCount[to] = _ownedTokensCount[to].add(1);
  }

  /**
   * @dev Internal function to remove a token ID from the list of a given address
   * Note that this function is left internal to make ERC721Enumerable possible, but is not
   * intended to be called by custom derived contracts: in particular, it emits no Transfer event,
   * and doesn't clear approvals.
   * @param from address representing the previous owner of the given token ID
   * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
   */
  function _removeTokenFrom(address from, uint256 tokenId) internal {
    require(ownerOf(tokenId) == from);
    _ownedTokensCount[from] = _ownedTokensCount[from].sub(1);
    _tokenOwner[tokenId] = address(0);
  }

  /**
   * @dev Internal function to invoke `onERC721Received` on a target address
   * The call is not executed if the target address is not a contract
   * @param from address representing the previous owner of the given token ID
   * @param to target address that will receive the tokens
   * @param tokenId uint256 ID of the token to be transferred
   * @param _data bytes optional data to send along with the call
   * @return whether the call correctly returned the expected magic value
   */
  function _checkOnERC721Received(
    address from,
    address to,
    uint256 tokenId,
    bytes _data
  )
    internal
    returns (bool)
  {
    if (!to.isContract()) {
      return true;
    }
    bytes4 retval = IERC721Receiver(to).onERC721Received(
      msg.sender, from, tokenId, _data);
    return (retval == _ERC721_RECEIVED);
  }

  /**
   * @dev Private function to clear current approval of a given token ID
   * Reverts if the given address is not indeed the owner of the token
   * @param owner owner of the token
   * @param tokenId uint256 ID of the token to be transferred
   */
  function _clearApproval(address owner, uint256 tokenId) private {
    require(ownerOf(tokenId) == owner);
    if (_tokenApprovals[tokenId] != address(0)) {
      _tokenApprovals[tokenId] = address(0);
    }
  }
}

contract IERC721Enumerable is IERC721 {
  function totalSupply() public view returns (uint256);
  function tokenOfOwnerByIndex(
    address owner,
    uint256 index
  )
    public
    view
    returns (uint256 tokenId);

  function tokenByIndex(uint256 index) public view returns (uint256);
}

contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable {
  // Mapping from owner to list of owned token IDs
  mapping(address => uint256[]) private _ownedTokens;

  // Mapping from token ID to index of the owner tokens list
  mapping(uint256 => uint256) private _ownedTokensIndex;

  // Array with all token ids, used for enumeration
  uint256[] private _allTokens;

  // Mapping from token id to position in the allTokens array
  mapping(uint256 => uint256) private _allTokensIndex;

  bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63;
  /**
   * 0x780e9d63 ===
   *   bytes4(keccak256('totalSupply()')) ^
   *   bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
   *   bytes4(keccak256('tokenByIndex(uint256)'))
   */

  /**
   * @dev Constructor function
   */
  constructor() public {
    // register the supported interface to conform to ERC721 via ERC165
    _registerInterface(_InterfaceId_ERC721Enumerable);
  }

  /**
   * @dev Gets the token ID at a given index of the tokens list of the requested owner
   * @param owner address owning the tokens list to be accessed
   * @param index uint256 representing the index to be accessed of the requested tokens list
   * @return uint256 token ID at the given index of the tokens list owned by the requested address
   */
  function tokenOfOwnerByIndex(
    address owner,
    uint256 index
  )
    public
    view
    returns (uint256)
  {
    require(index < balanceOf(owner));
    return _ownedTokens[owner][index];
  }

  /**
   * @dev Gets the total amount of tokens stored by the contract
   * @return uint256 representing the total amount of tokens
   */
  function totalSupply() public view returns (uint256) {
    return _allTokens.length;
  }

  /**
   * @dev Gets the token ID at a given index of all the tokens in this contract
   * Reverts if the index is greater or equal to the total number of tokens
   * @param index uint256 representing the index to be accessed of the tokens list
   * @return uint256 token ID at the given index of the tokens list
   */
  function tokenByIndex(uint256 index) public view returns (uint256) {
    require(index < totalSupply());
    return _allTokens[index];
  }

  /**
   * @dev Internal function to add a token ID to the list of a given address
   * This function is internal due to language limitations, see the note in ERC721.sol.
   * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event.
   * @param to address representing the new owner of the given token ID
   * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
   */
  function _addTokenTo(address to, uint256 tokenId) internal {
    super._addTokenTo(to, tokenId);
    uint256 length = _ownedTokens[to].length;
    _ownedTokens[to].push(tokenId);
    _ownedTokensIndex[tokenId] = length;
  }

  /**
   * @dev Internal function to remove a token ID from the list of a given address
   * This function is internal due to language limitations, see the note in ERC721.sol.
   * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event,
   * and doesn't clear approvals.
   * @param from address representing the previous owner of the given token ID
   * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
   */
  function _removeTokenFrom(address from, uint256 tokenId) internal {
    super._removeTokenFrom(from, tokenId);

    // To prevent a gap in the array, we store the last token in the index of the token to delete, and
    // then delete the last slot.
    uint256 tokenIndex = _ownedTokensIndex[tokenId];
    uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
    uint256 lastToken = _ownedTokens[from][lastTokenIndex];

    _ownedTokens[from][tokenIndex] = lastToken;
    // This also deletes the contents at the last position of the array
    _ownedTokens[from].length--;

    // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
    // be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping
    // the lastToken to the first position, and then dropping the element placed in the last position of the list

    _ownedTokensIndex[tokenId] = 0;
    _ownedTokensIndex[lastToken] = tokenIndex;
  }

  /**
   * @dev Internal function to mint a new token
   * Reverts if the given token ID already exists
   * @param to address the beneficiary that will own the minted token
   * @param tokenId uint256 ID of the token to be minted by the msg.sender
   */
  function _mint(address to, uint256 tokenId) internal {
    super._mint(to, tokenId);

    _allTokensIndex[tokenId] = _allTokens.length;
    _allTokens.push(tokenId);
  }

  /**
   * @dev Internal function to burn a specific token
   * Reverts if the token does not exist
   * @param owner owner of the token to burn
   * @param tokenId uint256 ID of the token being burned by the msg.sender
   */
  function _burn(address owner, uint256 tokenId) internal {
    super._burn(owner, tokenId);

    // Reorg all tokens array
    uint256 tokenIndex = _allTokensIndex[tokenId];
    uint256 lastTokenIndex = _allTokens.length.sub(1);
    uint256 lastToken = _allTokens[lastTokenIndex];

    _allTokens[tokenIndex] = lastToken;
    _allTokens[lastTokenIndex] = 0;

    _allTokens.length--;
    _allTokensIndex[tokenId] = 0;
    _allTokensIndex[lastToken] = tokenIndex;
  }
}

contract IERC721Receiver {
  /**
   * @notice Handle the receipt of an NFT
   * @dev The ERC721 smart contract calls this function on the recipient
   * after a `safeTransfer`. This function MUST return the function selector,
   * otherwise the caller will revert the transaction. The selector to be
   * returned can be obtained as `this.onERC721Received.selector`. This
   * function MAY throw to revert and reject the transfer.
   * Note: the ERC721 contract address is always the message sender.
   * @param operator The address which called `safeTransferFrom` function
   * @param from The address which previously owned the token
   * @param tokenId The NFT identifier which is being transferred
   * @param data Additional data with no specified format
   * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
   */
  function onERC721Received(
    address operator,
    address from,
    uint256 tokenId,
    bytes data
  )
    public
    returns(bytes4);
}

library Address {

  /**
   * Returns whether the target address is a contract
   * @dev This function will return false if invoked during the constructor of a contract,
   * as the code is not actually created until after the constructor finishes.
   * @param account address of the account to check
   * @return whether the target address is a contract
   */
  function isContract(address account) internal view returns (bool) {
    uint256 size;
    // XXX Currently there is no better way to check if there is a contract in an address
    // than to check the size of the code at that address.
    // See https://ethereum.stackexchange.com/a/14016/36603
    // for more details about how this works.
    // TODO Check this again before the Serenity release, because all addresses will be
    // contracts then.
    // solium-disable-next-line security/no-inline-assembly
    assembly { size := extcodesize(account) }
    return size > 0;
  }

}

    Contract ABI  
[{"constant":true,"inputs":[{"name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"offset","type":"uint16"},{"name":"limit","type":"uint16"}],"name":"getPendingPicturesList","outputs":[{"name":"pendingPictures","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"moderatorAt","outputs":[{"name":"email","type":"bytes32"},{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"profilePhotoHash","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isVisionService","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"index","type":"uint256"}],"name":"getPictureInfoByIndex","outputs":[{"name":"_hash","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"artist","type":"address"},{"name":"owner","type":"address"},{"name":"price","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isAdmin","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addKycService","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"moderationQueueSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isBuyer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"userAt","outputs":[{"name":"email","type":"bytes32"},{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"personalUrl","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"clearModerationQueue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"uint256"},{"name":"status","type":"bool"}],"name":"setVisionApproval","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addArtist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"personalPictureByHash","outputs":[{"name":"name","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"artist","type":"address"}],"name":"approveArtist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"byAuthor","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"visionApprovals","outputs":[{"name":"","type":"int8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isArtist","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"uint256"},{"name":"status","type":"bool"}],"name":"setApprovedStatus","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"artistApprovalThreshold","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isKycService","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pendingPictureByHash","outputs":[{"name":"name","type":"bytes32"},{"name":"artist","type":"address"},{"name":"price","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"},{"name":"_email","type":"bytes32"},{"name":"_firstName","type":"bytes32"},{"name":"_lastName","type":"bytes32"},{"name":"_personalUrl","type":"string"}],"name":"buyerKYCRegister","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"uint256"},{"name":"newPrice","type":"uint88"}],"name":"setPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pictureByHash","outputs":[{"name":"name","type":"bytes32"},{"name":"artist","type":"address"},{"name":"price","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addVisionService","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"addedPicturesNumByAuthor","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addModerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addBuyer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"artist","type":"address"}],"name":"artistApproved","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"myPictureAdditionFees","outputs":[{"name":"privateGalleryFee","type":"uint256"},{"name":"publicGalleryFee","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"initialPrice","type":"uint128"}],"name":"addPicture","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getNextPendingPictureInfo","outputs":[{"name":"_hash","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"artist","type":"address"},{"name":"initialPrice","type":"uint128"},{"name":"visionApproval","type":"int8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"hashes","type":"uint256[]"},{"name":"names","type":"bytes32[]"},{"name":"prices","type":"uint128[]"}],"name":"applyForArtist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"moderator","type":"address"}],"name":"getModeratorInfo","outputs":[{"name":"email","type":"bytes32"},{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"profilePhotoHash","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"uint256"}],"name":"buy","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"uint256"},{"name":"name","type":"bytes32"}],"name":"addPersonalPicture","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"uint256"}],"name":"getPictureInfo","outputs":[{"name":"_hash","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"artist","type":"address"},{"name":"owner","type":"address"},{"name":"price","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"uint256"}],"name":"getPersonalPictureInfo","outputs":[{"name":"_hash","type":"uint256"},{"name":"name","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"moderator","type":"address"},{"name":"email","type":"bytes32"},{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"profilePhotoHash","type":"uint256"}],"name":"registerModerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isModerator","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"uint256"}],"name":"getPendingPictureInfo","outputs":[{"name":"_hash","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"artist","type":"address"},{"name":"initialPrice","type":"uint128"},{"name":"visionApproval","type":"int8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"user","type":"address"}],"name":"getUserData","outputs":[{"name":"email","type":"bytes32"},{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"personalUrl","type":"string"},{"name":"profilePhotoHash","type":"uint256"},{"name":"role","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_token","type":"address"},{"name":"_pictureAdditionFee","type":"uint256"},{"name":"_vault","type":"address"},{"name":"_artistApprovalThreshold","type":"uint8"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_address","type":"address"},{"indexed":true,"name":"_email","type":"bytes32"},{"indexed":false,"name":"_firstName","type":"bytes32"},{"indexed":true,"name":"_lastName","type":"bytes32"}],"name":"UserRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"seller","type":"address"},{"indexed":true,"name":"buyer","type":"address"},{"indexed":true,"name":"hash","type":"uint256"},{"indexed":false,"name":"price","type":"uint256"}],"name":"PictureSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"uint256"},{"indexed":false,"name":"price","type":"uint256"}],"name":"PicturePriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"uint256"},{"indexed":false,"name":"name","type":"bytes32"},{"indexed":true,"name":"artist","type":"address"},{"indexed":false,"name":"initialPrice","type":"uint256"}],"name":"PictureAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"uint256"}],"name":"PictureApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"uint256"}],"name":"PictureMadeVisible","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"uint256"},{"indexed":false,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"PersonalPictureAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"VisionServiceAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"VisionServiceRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"ModeratorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"ModeratorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"ArtistAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"BuyerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"KycServiceAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"KycServiceRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"AdminRemoved","type":"event"}]

  Contract Creation Code Switch To Opcodes View
60806040523480156200001157600080fd5b5060405160808062003b6a833981016040908152815160208301519183015160609093015190929083600f8185858583838382620000787f01ffc9a700000000000000000000000000000000000000000000000000000000640100000000620003d2810204565b6200008c336401000000006200043f810204565b604080517f4d696e7420696e74657266616365206964000000000000000000000000000000815281519081900360110181207f01ffc9a70000000000000000000000000000000000000000000000000000000082527fffffffff000000000000000000000000000000000000000000000000000000001660048201529051600160a060020a038316916301ffc9a79160248083019260209291908290030181600087803b1580156200013d57600080fd5b505af115801562000152573d6000803e3d6000fd5b505050506040513d60208110156200016957600080fd5b505115156200017757600080fd5b600c8054600160a060020a03928316600160a060020a031991821617909155600d8054939092169216919091179055600e55506064620001b960118262000524565b506064620001c960158262000524565b506014805460ff191660ff929092169190911790555050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f80ac58cd0000000000000000000000000000000000000000000000000000000060048201529051600160a060020a03851692506301ffc9a7916024808201926020929091908290030181600087803b1580156200026457600080fd5b505af115801562000279573d6000803e3d6000fd5b505050506040513d60208110156200029057600080fd5b505115156200029e57600080fd5b60008160ff1610158015620002b6575060648160ff16105b1515620002c257600080fd5b6018805460ff191660ff92909216919091179055601a8054600160a060020a031916600160a060020a03928316179055604080517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f80ac58cd0000000000000000000000000000000000000000000000000000000060048201529051918616916301ffc9a7916024808201926020929091908290030181600087803b1580156200036e57600080fd5b505af115801562000383573d6000803e3d6000fd5b505050506040513d60208110156200039a57600080fd5b50511515620003a857600080fd5b5050601c8054600160a060020a031916600160a060020a0393909316929092179091555062000574565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200040257600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b6200045a600182640100000000620033306200049182021704565b604051600160a060020a038216907f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e33990600090a250565b600160a060020a0381161515620004a757600080fd5b620004bc8282640100000000620004ec810204565b15620004c757600080fd5b600160a060020a0316600090815260209190915260409020805460ff19166001179055565b6000600160a060020a03821615156200050457600080fd5b50600160a060020a03166000908152602091909152604090205460ff1690565b8154818355818111156200054b576000838152602090206200054b91810190830162000550565b505050565b6200057191905b808211156200056d576000815560010162000557565b5090565b90565b6135e680620005846000396000f30060806040526004361061020b5763ffffffff60e060020a60003504166301ffc9a7811461021057806303f2a6341461025b5780630b69b4c6146102cd578063165178e4146103145780631cd522511461033557806324d7806c146103825780632574c241146103a357806327cb288a146103c65780632a55feec146103ed5780632bb02be61461040e578063401bfe19146104c05780634920dfbe146104d55780634d287f2b146104f257806356e946f61461051357806359424b78146105375780635f56293b146105585780635f89d62c1461057c5780636b2f65b0146105ad57806370480275146105ce5780637227d83c146105ef57806386277e4a1461060c57806388ba6b83146106375780638bad0c0a1461065857806390ae80e61461066d57806390c1385a146106b4578063a1f2b12b14610728578063a404eb7f14610750578063a5695b8914610768578063b1de676d14610789578063b532e4cb146107aa578063bbf89803146107cb578063bf0ba169146107ec578063c7e954e61461080d578063d1255ea31461083b578063d15efe3414610855578063d608e05b146108ad578063d8b1b81b14610974578063d96a094a14610995578063e7127be6146109a0578063e7fde985146109ae578063eb691044146109c6578063f5180f06146109de578063fa6f393614610a0b578063fdb2554414610a2c578063ffc9896b14610a44575b600080fd5b34801561021c57600080fd5b506102477bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1960043516610b66565b604080519115158252519081900360200190f35b34801561026757600080fd5b5061027d61ffff60043581169060243516610bc2565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102b95781810151838201526020016102a1565b505050509050019250505060405180910390f35b3480156102d957600080fd5b506102ee600160a060020a0360043516610c93565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561032057600080fd5b50610247600160a060020a0360043516610cba565b34801561034157600080fd5b5061034d600435610cd3565b604080519586526020860194909452600160a060020a0392831685850152911660608401526080830152519081900360a00190f35b34801561038e57600080fd5b50610247600160a060020a0360043516610d82565b3480156103af57600080fd5b506103c4600160a060020a0360043516610d95565b005b3480156103d257600080fd5b506103db610db5565b60408051918252519081900360200190f35b3480156103f957600080fd5b50610247600160a060020a0360043516610ddb565b34801561041a57600080fd5b5061042f600160a060020a0360043516610dee565b60408051858152602080820186905291810184905260806060820181815284519183019190915283519192909160a084019185019080838360005b8381101561048257818101518382015260200161046a565b50505050905090810190601f1680156104af5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b3480156104cc57600080fd5b506103c4610eb6565b3480156104e157600080fd5b506103c46004356024351515610ed6565b3480156104fe57600080fd5b506103c4600160a060020a0360043516610f40565b34801561051f57600080fd5b506103db600160a060020a0360043516602435610f5d565b34801561054357600080fd5b506103c4600160a060020a0360043516610f7a565b34801561056457600080fd5b506103db600160a060020a0360043516602435610ff5565b34801561058857600080fd5b50610594600435611025565b60408051600092830b90920b8252519081900360200190f35b3480156105b957600080fd5b50610247600160a060020a0360043516611039565b3480156105da57600080fd5b506103c4600160a060020a036004351661104c565b3480156105fb57600080fd5b506103c46004356024351515611069565b34801561061857600080fd5b506106216111d6565b6040805160ff9092168252519081900360200190f35b34801561064357600080fd5b50610247600160a060020a03600435166111df565b34801561066457600080fd5b506103c46111f2565b34801561067957600080fd5b506106856004356111fb565b60408051938452600160a060020a0390921660208401526001608060020a031682820152519081900360600190f35b3480156106c057600080fd5b50604080516020601f6084356004818101359283018490048402850184019095528184526103c494600160a060020a03813516946024803595604435956064359536959460a494909391019190819084018382808284375094975061122e9650505050505050565b34801561073457600080fd5b506103c46004356affffffffffffffffffffff60243516611256565b34801561075c57600080fd5b50610685600435611482565b34801561077457600080fd5b506103c4600160a060020a03600435166114b5565b34801561079557600080fd5b506103db600160a060020a03600435166114d2565b3480156107b657600080fd5b506103c4600160a060020a03600435166114e4565b3480156107d757600080fd5b506103c4600160a060020a0360043516611501565b3480156107f857600080fd5b50610247600160a060020a036004351661151e565b34801561081957600080fd5b50610822611545565b6040805192835260208301919091528051918290030190f35b6103c46004356024356001608060020a036044351661154d565b34801561086157600080fd5b5061086a6117f1565b604080519586526020860194909452600160a060020a03909216848401526001608060020a03166060840152600090810b900b6080830152519081900360a00190f35b3480156108b957600080fd5b50604080516020600480358082013583810280860185019096528085526103c495369593946024949385019291829185019084908082843750506040805187358901803560208181028481018201909552818452989b9a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989b9a9989019892975090820195509350839250850190849080828437509497506118359650505050505050565b34801561098057600080fd5b506102ee600160a060020a0360043516611adc565b6103c4600435611bd9565b6103c4600435602435611f94565b3480156109ba57600080fd5b5061034d6004356122cf565b3480156109d257600080fd5b5061082260043561243c565b3480156109ea57600080fd5b506103c4600160a060020a0360043516602435604435606435608435612474565b348015610a1757600080fd5b50610247600160a060020a0360043516612696565b348015610a3857600080fd5b5061086a6004356126a9565b348015610a5057600080fd5b50610a65600160a060020a0360043516612745565b6040805187815260208082018890529181018690526080810184905260c06060820181815286519183019190915285519192909160a084019160e08501919088019080838360005b83811015610ac5578181015183820152602001610aad565b50505050905090810190601f168015610af25780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610b25578181015183820152602001610b0d565b50505050905090810190601f168015610b525780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b604080517f4d6f6465726174696f6e20696e74657266616365206964000000000000000000815290519081900360170190207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff198281169116145b919050565b606060008060606000610bd433612696565b1515610bdf57600080fd5b610be96015612a44565b935061ffff87168411610bfb57600080fd5b61ffff808716935087168403831115610c18578661ffff16840392505b82604051908082528060200260200182016040528015610c42578160200160208202803883390190505b509150600090505b82811015610c8957610c69601561ffff8916830163ffffffff612a5316565b8282815181101515610c7757fe5b60209081029091010152600101610c4a565b5095945050505050565b601b6020526000908152604090208054600182015460028301546003909301549192909184565b6000610ccd60068363ffffffff612aa516565b92915050565b6000806000806000601a60009054906101000a9004600160a060020a0316600160a060020a0316634f6ccce7876040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b158015610d3957600080fd5b505af1158015610d4d573d6000803e3d6000fd5b505050506040513d6020811015610d6357600080fd5b50519450610d70856122cf565b939a9299509097509550909350915050565b6000610ccd60018363ffffffff612aa516565b610d9e33610d82565b1515610da957600080fd5b610db281612adc565b50565b6000610dc033612696565b1515610dcb57600080fd5b610dd56015612a44565b90505b90565b6000610ccd60038363ffffffff612aa516565b6019602052806000526040600020600091509050806000015490806001015490806002015490806003018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610eac5780601f10610e8157610100808354040283529160200191610eac565b820191906000526020600020905b815481529060010190602001808311610e8f57829003601f168201915b5050505050905084565b610ebf33610d82565b1515610eca57600080fd5b610ed46015612b24565b565b610edf33610cba565b1515610eea57600080fd5b610ef382612b51565b1515610efe57600080fd5b8015610f22576000828152600960205260409020805460ff19166001179055610f3c565b6000828152600960205260409020805460ff191660ff1790555b5050565b610f49336111df565b1515610f5457600080fd5b610db281612b68565b600f60209081526000928352604080842090915290825290205481565b6000610f8533612696565b1515610f9057600080fd5b5060005b600160a060020a0382166000908152600a6020526040902054811015610f3c57600160a060020a0382166000908152600a602052604090208054610fed919083908110610fdd57fe5b9060005260206000200154612bb0565b600101610f94565b600a6020528160005260406000208181548110151561101057fe5b90600052602060002001600091509150505481565b600960205260009081526040812054900b81565b6000610ccd60048363ffffffff612aa516565b61105533610d82565b151561106057600080fd5b610db281612d55565b600061107433612696565b151561107f57600080fd5b6110896015612d9d565b8314611105576040805160e560020a62461bcd02815260206004820152603960248201527f54686520706963747572652077617320616c72656164792072656d6f7665642060448201527f66726f6d20746865206d6f6465726174696f6e20717565756500000000000000606482015290519081900360840190fd5b6000838152600960205260409020805460ff1916905581156111d157506000828152600860209081526040808320600190810154600160a060020a0316808552600a84528285208054928301815585529284200185905551909184917fa146da761f7e6932205379d86cd086cc6b7f0324d34e44453388c7ec95206c4d9190a261118e8161151e565b156111a15761119c83612bb0565b6111d1565b601454600160a060020a0382166000908152600a602052604090205460ff90911614156111d1576111d181610f7a565b505050565b60145460ff1681565b6000610ccd60028363ffffffff612aa516565b610ed433612e10565b6008602052600090815260409020805460018201546002909201549091600160a060020a0316906001608060020a031683565b611237336111df565b151561124257600080fd5b61124f8585858585612e58565b5050505050565b61125f33610ddb565b151561126a57600080fd5b600c546040805160e160020a62491fcf0281526004810185905290518492600160a060020a03169162923f9e9160248083019260209291908290030181600087803b1580156112b857600080fd5b505af11580156112cc573d6000803e3d6000fd5b505050506040513d60208110156112e257600080fd5b505115156112ef57600080fd5b601a54604080517f6352211e00000000000000000000000000000000000000000000000000000000815260048101869052905133928692600160a060020a0390911691636352211e916024808201926020929091908290030181600087803b15801561135a57600080fd5b505af115801561136e573d6000803e3d6000fd5b505050506040513d602081101561138457600080fd5b5051600160a060020a0316331461140b576040805160e560020a62461bcd02815260206004820152602960248201527f4f6e6c7920746865206f776e65722063616e206564697420612070696374757260448201527f6527732070726963650000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60008581526007602090815260409182902060020180546fffffffffffffffffffffffffffffffff19166affffffffffffffffffffff88169081179091558251908152915187927fcb77ef345afc04a4384f0ec7962e06afca66b897fcd0da5f94c5a359f0a5de4892908290030190a25050505050565b6007602052600090815260409020805460018201546002909201549091600160a060020a0316906001608060020a031683565b6114be33610d82565b15156114c957600080fd5b610db281613144565b600b6020526000908152604090205481565b6114ed33610d82565b15156114f857600080fd5b610db28161318c565b61150a336111df565b151561151557600080fd5b610db2816131d4565b601454600160a060020a0382166000908152600a602052604090205460ff90911610919050565b600e54908190565b61155633611039565b151561156157600080fd5b600c546040805160e160020a62491fcf0281526004810186905290518592600160a060020a03169162923f9e9160248083019260209291908290030181600087803b1580156115af57600080fd5b505af11580156115c3573d6000803e3d6000fd5b505050506040513d60208110156115d957600080fd5b505115611630576040805160e560020a62461bcd02815260206004820152601860248201527f506963747572652073686f756c64206e6f742065786973740000000000000000604482015290519081900360640190fd5b61163984612b51565b1580156116475750600e5434145b151561165257600080fd5b6000600160f860020a031960f860020a85831a0216116116bc576040805160e560020a62461bcd02815260206004820152601c60248201527f50696374757265206e616d652063616e6e6f7420626520656d70747900000000604482015290519081900360640190fd5b604080516060810182528481523360208083019182526001608060020a0386811684860190815260008a815260089093529490912092518355905160018301805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790559151600290910180546fffffffffffffffffffffffffffffffff19169190921617905561175360158561321c565b336000908152600b602052604080822080546001019055600d549051600160a060020a0391909116913480156108fc02929091818181858888f193505050501580156117a3573d6000803e3d6000fd5b50604080518481526001608060020a03841660208201528151339287927fe4c033c220b9796694620acffa25e4ce743e93eadf199d3ef6cb474f128bcc68929081900390910190a350505050565b60008060008060008061180333612696565b151561180e57600080fd5b611818601561327f565b9050611823816126a9565b95509550955095509550509091929394565b60008061184133610ddb565b151561184c57600080fd5b61185533611039565b1561185f57600080fd5b600091505b8451821015611a4757600c548551600160a060020a039091169062923f9e9087908590811061188f57fe5b906020019060200201516040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b1580156118d257600080fd5b505af11580156118e6573d6000803e3d6000fd5b505050506040513d60208110156118fc57600080fd5b505115611979576040805160e560020a62461bcd02815260206004820152602481018290527f43616e6e6f7420696e636c756465206578697374696e6720706963747572657360448201527f20696e20617274697374206170706c69636174696f6e20706f7274666f6c696f606482015290519081900360840190fd5b835160009085908490811061198a57fe5b6020908102909101015160001a60f860020a027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916111515611a3c576040805160e560020a62461bcd02815260206004820152602a60248201527f417274697374206170706c69636174696f6e20706f7274666f6c696f2072657160448201527f75697265206e616d657300000000000000000000000000000000000000000000606482015290519081900360840190fd5b600190910190611864565b60408051606081018252868152602080820187905281830186905233600090815260108252929092208151805192939192611a8592849201906133ca565b506020828101518051611a9e9260018501920190613415565b5060408201518051611aba916002840191602090910190613452565b50339250611ad39150601190508263ffffffff61321c16565b61124f33612b68565b600160a060020a0381166000908152601b60205260408120548190819081908190811a60f860020a027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916111515611ba4576040805160e560020a62461bcd02815260206004820152602c60248201527f4d6f64657261746f72206d757374206265207265676973746572656420746f2060448201527f6765742068697320696e666f0000000000000000000000000000000000000000606482015290519081900360840190fd5b50505050600160a060020a03166000908152601b60205260409020805460018201546002830154600390930154919390929190565b600c546040805160e160020a62491fcf028152600481018490529051600092839283928692600160a060020a03169162923f9e91602480830192602092919082900301818887803b158015611c2d57600080fd5b505af1158015611c41573d6000803e3d6000fd5b505050506040513d6020811015611c5757600080fd5b50511515611c6457600080fd5b611c6d33610ddb565b1515611c7857600080fd5b601a54604080517f6352211e000000000000000000000000000000000000000000000000000000008152600481018890529051600160a060020a0390921691636352211e916024808201926020929091908290030181600087803b158015611cdf57600080fd5b505af1158015611cf3573d6000803e3d6000fd5b505050506040513d6020811015611d0957600080fd5b5051935033600160a060020a0385161415611d94576040805160e560020a62461bcd02815260206004820152602b60248201527f446f6e277420776173746520796f757220657468657220627579696e6720667260448201527f6f6d20796f757273656c66000000000000000000000000000000000000000000606482015290519081900360840190fd5b600085815260076020526040902060028101549093506001608060020a03163414611e2f576040805160e560020a62461bcd02815260206004820152603d60248201527f53656e642065786163746c792074686520616d6f756e74206f6620657468657260448201527f20657175616c20746f2074686520706963747572652773207072696365000000606482015290519081900360840190fd5b601a54604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a03878116600483015233602483015260448201899052915191909216916323b872dd91606480830192600092919082900301818387803b158015611ea357600080fd5b505af1158015611eb7573d6000803e3d6000fd5b5050601854600d5460405160ff90921660643404029550600160a060020a0316925084156108fc02915084906000818181858888f19350505050158015611f02573d6000803e3d6000fd5b50604051600160a060020a038516903484900380156108fc02916000818181858888f19350505050158015611f3b573d6000803e3d6000fd5b506002830154604080516001608060020a0390921682525186913391600160a060020a038816917f43a6c19578e1b7aaa2815829bec05b14eb8b38b02a169cc87d3b2afd709c1208919081900360200190a45050505050565b600c546040805160e160020a62491fcf0281526004810185905290518492600160a060020a03169162923f9e9160248083019260209291908290030181600087803b158015611fe257600080fd5b505af1158015611ff6573d6000803e3d6000fd5b505050506040513d602081101561200c57600080fd5b505115612063576040805160e560020a62461bcd02815260206004820152601860248201527f506963747572652073686f756c64206e6f742065786973740000000000000000604482015290519081900360640190fd5b6000600160f860020a031960f860020a84831a0216116120cd576040805160e560020a62461bcd02815260206004820152601c60248201527f50696374757265206e616d652063616e6e6f7420626520656d70747900000000604482015290519081900360640190fd5b6120d733846132ba565b15612152576040805160e560020a62461bcd02815260206004820152602d60248201527f41207069637475726520776974682074686973206861736820697320616c726560448201527f616479207375626d697474656400000000000000000000000000000000000000606482015290519081900360840190fd5b61215b83612b51565b156121d6576040805160e560020a62461bcd02815260206004820152602d60248201527f41207069637475726520776974682074686973206861736820697320616c726560448201527f616479207375626d697474656400000000000000000000000000000000000000606482015290519081900360840190fd5b600e54341461222f576040805160e560020a62461bcd02815260206004820152601660248201527f54686174276c6c20636f737420796f752c2070616c2100000000000000000000604482015290519081900360640190fd5b6040805160208181018352848252336000908152600f82528381208782529091528281209151909155600d549151600160a060020a0392909216913480156108fc0292909190818181858888f19350505050158015612292573d6000803e3d6000fd5b50604080518381529051339185917f2c6ad2a5ae82a47e12d4596ed64b63c59708769331292d3a2e4bff5d7e8532229181900360200190a3505050565b600080600080600080600c60009054906101000a9004600160a060020a0316600160a060020a031662923f9e886040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561233557600080fd5b505af1158015612349573d6000803e3d6000fd5b505050506040513d602081101561235f57600080fd5b5051151561236c57600080fd5b50600086815260076020908152604080832080546001820154601a5484517f6352211e000000000000000000000000000000000000000000000000000000008152600481018e90529451929a50600160a060020a0391821699509295921693636352211e93602480820194929392918390030190829087803b1580156123f157600080fd5b505af1158015612405573d6000803e3d6000fd5b505050506040513d602081101561241b57600080fd5b505160029091015496979496939550936001608060020a0390931692915050565b336000908152600f6020908152604080832084845290915281208190612461816132ed565b151561246c57600080fd5b549293915050565b61247d33610d82565b151561248857600080fd5b6000600160f860020a031960f860020a86831a021611612518576040805160e560020a62461bcd02815260206004820152602a60248201527f456d61696c206973206d616e6461746f727920666f722061727469737420726560448201527f67697374726174696f6e00000000000000000000000000000000000000000000606482015290519081900360840190fd5b6000600160f860020a031960f860020a85831a0216116125a8576040805160e560020a62461bcd02815260206004820152602f60248201527f4669727374206e616d65206973206d616e6461746f727920666f72206172746960448201527f737420726567697374726174696f6e0000000000000000000000000000000000606482015290519081900360840190fd5b6000600160f860020a031960f860020a84831a021611612638576040805160e560020a62461bcd02815260206004820152602e60248201527f4c617374206e616d65206973206d616e6461746f727920666f7220617274697360448201527f7420726567697374726174696f6e000000000000000000000000000000000000606482015290519081900360840190fd5b612641856114e4565b60408051608081018252948552602080860194855285820193845260608601928352600160a060020a039096166000908152601b90965290942092518355905160018301555160028201559051600390910155565b6000610ccd60058363ffffffff612aa516565b600081815260086020526040812060018101548291829182918291600160a060020a0316821080156126f557506001810154600160a060020a03163314806126f557506126f533612696565b151561270057600080fd5b80546001820154600290920154600089815260096020526040812054999a9299600160a060020a0390941698506001608060020a0390911696509190910b9350915050565b60008060006060600060608661275a81613307565b15156127d6576040805160e560020a62461bcd02815260206004820152602760248201527f55736572206d757374206265207265676973746572656420746f20676574206860448201527f697320696e666f00000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60408051808201909152600981527f616e6f6e796d6f757300000000000000000000000000000000000000000000006020820152915061281588610d82565b156128555760408051808201909152600d81527f61646d696e6973747261746f720000000000000000000000000000000000000060208201529150612a3a565b61285e88612696565b156128d657604080518082018252600981527f6d6f64657261746f720000000000000000000000000000000000000000000000602080830191909152600160a060020a038b166000908152601b90915291909120600381015481546001830154600290930154909a5091985090965093509150612a3a565b6128df88611039565b1561291f5760408051808201909152600681527f617274697374000000000000000000000000000000000000000000000000000060208201529150612964565b61292888610ddb565b156129645760408051808201909152600581527f6275796572000000000000000000000000000000000000000000000000000000602082015291505b600160a060020a03881660009081526019602090815260409182902060030180548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015612a045780601f106129d957610100808354040283529160200191612a04565b820191906000526020600020905b8154815290600101906020018083116129e757829003601f168201915b505050600160a060020a038b16600090815260196020526040902080546001820154600290920154909b50909950975091955050505b5091939550919395565b60018101546002909101540390565b600080612a5f84612a44565b8310612a6a57612a9e565b835460018501548401811515612a7c57fe5b0690508360000181815481101515612a9057fe5b906000526020600020015491505b5092915050565b6000600160a060020a0382161515612abc57600080fd5b50600160a060020a03166000908152602091909152604090205460ff1690565b612aed60028263ffffffff61333016565b604051600160a060020a038216907fc133a9f058feb2470efce78abf48ccdf86e67ca294092a485e87fa813f0d724d90600090a250565b600080612b3083612a44565b9150600090505b818110156111d157612b4883612d9d565b50600101612b37565b6000818152600860205260408120610ccd906132ed565b612b7960048263ffffffff61333016565b604051600160a060020a038216907fcbfc96fa35f269722f7abab67c3e11fbfd63618e2e593bdf481f2818e8e8304290600090a250565b6000818152600860209081526040808320815160608101835281548152600180830154600160a060020a039081168387019081526002808601546001608060020a039081168689019081528b8b526007909952878a20955186559151938501805473ffffffffffffffffffffffffffffffffffffffff191694909316939093179091559451910180546fffffffffffffffffffffffffffffffff1916919094161790925551909183917fb94989d3edc466ac0bba0788b4b2c28a3eb0c4da628da20d0fef9d704c6e32b49190a2600c546001820154604080517f40c10f19000000000000000000000000000000000000000000000000000000008152600160a060020a03928316600482015260248101869052905191909216916340c10f1991604480830192600092919082900301818387803b158015612cf057600080fd5b505af1158015612d04573d6000803e3d6000fd5b5050506000928352505060086020526040812090815560018101805473ffffffffffffffffffffffffffffffffffffffff1916905560020180546fffffffffffffffffffffffffffffffff19169055565b612d6660018263ffffffff61333016565b604051600160a060020a038216907f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e33990600090a250565b6000816001015482600201541415612db457610bbd565b600182015482548391908110612dc657fe5b90600052602060002001549050816000018260010154815481101515612de857fe5b6000918252602082200155815460018084015401811515612e0557fe5b066001830155919050565b612e2160018263ffffffff61337e16565b604051600160a060020a038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f90600090a250565b84612e6281613307565b15612edd576040805160e560020a62461bcd02815260206004820152602481018290527f41646472657373206d757374206265206e6f7420626520616c7265616479207260448201527f65676973746572656420746f2072656769737465722061206e65772075736572606482015290519081900360840190fd5b6000600160f860020a031960f860020a87831a021611612f6d576040805160e560020a62461bcd02815260206004820152602a60248201527f456d61696c206973206d616e6461746f727920666f722061727469737420726560448201527f67697374726174696f6e00000000000000000000000000000000000000000000606482015290519081900360840190fd5b6000600160f860020a031960f860020a86831a021611612ffd576040805160e560020a62461bcd02815260206004820152602f60248201527f4669727374206e616d65206973206d616e6461746f727920666f72206172746960448201527f737420726567697374726174696f6e0000000000000000000000000000000000606482015290519081900360840190fd5b6000600160f860020a031960f860020a85831a02161161308d576040805160e560020a62461bcd02815260206004820152602e60248201527f4c617374206e616d65206973206d616e6461746f727920666f7220617274697360448201527f7420726567697374726174696f6e000000000000000000000000000000000000606482015290519081900360840190fd5b61309686611501565b60408051608081018252868152602080820187815282840187815260608401878152600160a060020a038c16600090815260198552959095208451815591516001830155516002820155925180519293926130f79260038501920190613506565b50506040805186815290518592508791600160a060020a038a16917f5066495791dcc2990fd8aa6b0182eb2345ca0b02c662b26da9d3ccf2be8f35159181900360200190a4505050505050565b61315560068263ffffffff61333016565b604051600160a060020a038216907fe571a46fdcd0bfea6b4e4fe65d33adad16eebc89d1990df0650485b1e0c8110f90600090a250565b61319d60058263ffffffff61333016565b604051600160a060020a038216907fd378ad41c1a753fd1ba9ec0fcd7970526c175b68545b4a02d6d15e7606fe359690600090a250565b6131e560038263ffffffff61333016565b604051600160a060020a038216907f6599d9dd7f97ccdc3d99ab507544f9f6ebfca20c63a7e3c018da49eeaefb164a90600090a250565b60018083015483546002850154919290910181151561323757fe5b06141561324357610f3c565b6002820154825482918491811061325657fe5b6000918252602090912001558154600283015460010181151561327557fe5b0660028301555050565b600081600101548260020154141561329657610bbd565b6001820154825483919081106132a857fe5b90600052602060002001549050919050565b600160a060020a0382166000908152600f6020908152604080832084845290915281206132e6906132ed565b9392505050565b54600090811a60f860020a02600160f860020a0319161190565b600061331282610ddb565b80613321575061332182611039565b80610ccd5750610ccd82612696565b600160a060020a038116151561334557600080fd5b61334f8282612aa5565b1561335957600080fd5b600160a060020a0316600090815260209190915260409020805460ff19166001179055565b600160a060020a038116151561339357600080fd5b61339d8282612aa5565b15156133a857600080fd5b600160a060020a0316600090815260209190915260409020805460ff19169055565b828054828255906000526020600020908101928215613405579160200282015b828111156134055782518255916020019190600101906133ea565b50613411929150613573565b5090565b828054828255906000526020600020908101928215613405579160200282015b828111156134055782518255602090920191600190910190613435565b828054828255906000526020600020906001016002900481019282156134fa5791602002820160005b838211156134c557835183826101000a8154816001608060020a0302191690836001608060020a031602179055509260200192601001602081600f0104928301926001030261347b565b80156134f85782816101000a8154906001608060020a030219169055601001602081600f010492830192600103026134c5565b505b5061341192915061358d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061354757805160ff1916838001178555613405565b8280016001018555821561340557918201828111156134055782518255916020019190600101906133ea565b610dd891905b808211156134115760008155600101613579565b610dd891905b808211156134115780546fffffffffffffffffffffffffffffffff191681556001016135935600a165627a7a72305820d0ac03e91589cec10ca1d2a9987d7145a6862fe534e34d7609c4a10bf892d6c40029000000000000000000000000e94547cbbbe87c70d56e0cb5a641daf554f3cf52000000000000000000000000000000000000000000000000007c58508723800000000000000000000000000037f3be05f1ad28ab26286095abb3adcf8bf3005a0000000000000000000000000000000000000000000000000000000000000003

   Swarm Source:
bzzr://d0ac03e91589cec10ca1d2a9987d7145a6862fe534e34d7609c4a10bf892d6c4

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward