Address Contract Partially Verified
Address
0x5536B6aAdd29eAf0DB112Bb28046A5FaD3761bD4
Balance
0 ETH
Nonce
1
Code Size
20939 bytes
Creator
0x9f2fedFf...dd37 at tx 0x09c63b0b...ed17d6
Indexed Transactions
0
Contract Bytecode
20939 bytes
0x6080604052600436106102375763ffffffff60e060020a60003504166301ffc9a7811461023c578063062401c21461027257806306fdde03146102f0578063081812fc1461037a57806308702682146103ae578063095ea7b3146103e157806318160ddd1461040757806319fa8f501461041c57806323b872dd1461044e57806326a50862146104785780632f745c59146104995780633a663c80146104bd57806342842e0e146104f15780634aeabcb61461051b5780634f558e791461053f5780634f6ccce7146105575780634fc092751461056f57806350ff9a5b1461059357806357643118146105c15780635835068114610632578063589a174314610659578063602c4f051461067157806361d9db2d146106985780636352211e146106ad5780636bb2a9a8146106c55780636e9960c31461074a57806370a082311461075f57806375d28011146107805780638a153c28146107a557806395d89b41146107c65780639e5f4dbd146107db5780639fee49ba146107fc578063a05d821b14610820578063a22cb46514610841578063a28835b614610867578063ace8116d14610888578063ad7321541461089d578063b09afec1146108be578063b2f42210146108d6578063b88d4fde1461092f578063c7778baa1461099e578063c82a94a1146109b6578063c87b56dd14610a17578063d4aa25cc14610a2f578063d694f10914610a50578063e2b3190314610a71578063e8545f1b14610be9578063e985e9c514610c27578063fb825e5f14610c4e575b600080fd5b34801561024857600080fd5b5061025e600160e060020a031960043516610c63565b604080519115158252519081900360200190f35b34801561027e57600080fd5b506102936001604060020a0360043516610c86565b604080519788526001604060020a0396871660208901529490951686850152600160a060020a03928316606087015291166080850152600160c060020a03191660a084015263ffffffff90911660c0830152519081900360e00190f35b3480156102fc57600080fd5b50610305610dbe565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561033f578181015183820152602001610327565b50505050905090810190601f16801561036c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561038657600080fd5b50610392600435610df6565b60408051600160a060020a039092168252519081900360200190f35b3480156103ba57600080fd5b506103cf600160a060020a0360043516610ebc565b60408051918252519081900360200190f35b3480156103ed57600080fd5b50610405600160a060020a0360043516602435610f2a565b005b34801561041357600080fd5b506103cf611107565b34801561042857600080fd5b5061043161110d565b60408051600160e060020a03199092168252519081900360200190f35b34801561045a57600080fd5b50610405600160a060020a0360043581169060243516604435611131565b34801561048457600080fd5b506103cf6001604060020a0360043516611302565b3480156104a557600080fd5b506103cf600160a060020a03600435166024356113c5565b3480156104c957600080fd5b506104d5600435611506565b604080516001604060020a039092168252519081900360200190f35b3480156104fd57600080fd5b50610405600160a060020a03600435811690602435166044356115c7565b34801561052757600080fd5b506103cf6001604060020a03600435166024356115e8565b34801561054b57600080fd5b5061025e600435611726565b34801561056357600080fd5b506103cf60043561178f565b34801561057b57600080fd5b506103cf600160a060020a0360043516602435611804565b34801561059f57600080fd5b506104d56001604060020a0360043516600160c060020a0319602435166118ed565b3480156105cd57600080fd5b506105e2600160a060020a0360043516611ba7565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561061e578181015183820152602001610606565b505050509050019250505060405180910390f35b34801561063e57600080fd5b506105e26001604060020a0360043581169060243516611c95565b34801561066557600080fd5b50610392600435611ec2565b34801561067d57600080fd5b506105e26001604060020a0360043581169060243516611fb1565b3480156106a457600080fd5b506103cf6121d1565b3480156106b957600080fd5b506103926004356121d7565b3480156106d157600080fd5b506106e66001604060020a0360043516612286565b60408051600160c060020a031984168152602080820183815284519383019390935283519192916060840191858101910280838360005b8381101561073557818101518382015260200161071d565b50505050905001935050505060405180910390f35b34801561075657600080fd5b5061039261240b565b34801561076b57600080fd5b506103cf600160a060020a036004351661241a565b34801561078c57600080fd5b506104d5600435600160c060020a031960243516612488565b3480156107b157600080fd5b5061025e6001604060020a0360043516612615565b3480156107d257600080fd5b506103056126d9565b3480156107e757600080fd5b50610405600160a060020a0360043516612710565b6104d5600160a060020a0360043516602435600160c060020a0319604435166127c7565b34801561082c57600080fd5b506104d56001604060020a0360043516612bac565b34801561084d57600080fd5b50610405600160a060020a03600435166024351515612e76565b34801561087357600080fd5b50610405600160a060020a0360043516612f95565b34801561089457600080fd5b506105e2613057565b3480156108a957600080fd5b506105e26001604060020a03600435166130df565b3480156108ca57600080fd5b506102936004356131a2565b3480156108e257600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261040594369492936024939284019190819084018382808284375094975061331d9650505050505050565b34801561093b57600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261040594600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506133b89650505050505050565b3480156109aa57600080fd5b506103cf60043561342b565b3480156109c257600080fd5b50604080516020600480358082013583810280860185019096528085526104d59536959394602494938501929182918501908490808284375094975050509235600160c060020a031916935061352e92505050565b348015610a2357600080fd5b5061030560043561395c565b348015610a3b57600080fd5b506105e2600160a060020a0360043516613d47565b348015610a5c57600080fd5b5061025e6001604060020a0360043516613e0a565b348015610a7d57600080fd5b5060408051602060048035808201358381028086018501909652808552610ac695369593946024949385019291829185019084908082843750949750613e769650505050505050565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b83811015610b12578181015183820152602001610afa565b50505050905001858103845288818151815260200191508051906020019060200280838360005b83811015610b51578181015183820152602001610b39565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610b90578181015183820152602001610b78565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610bcf578181015183820152602001610bb7565b505050509050019850505050505050505060405180910390f35b348015610bf557600080fd5b50610c0a6001604060020a036004351661414a565b60408051600160c060020a03199092168252519081900360200190f35b348015610c3357600080fd5b5061025e600160a060020a0360043581169060243516614235565b348015610c5a57600080fd5b506105e2614306565b600160e060020a0319811660009081526020819052604090205460ff165b919050565b6000806000806000806000806000610c9c611107565b6001604060020a038b1610610ce9576040805160e560020a62461bcd02815260206004820152601f60248201526000805160206150c0833981519152604482015290519081900360640190fd5b600880546001604060020a038c16908110610d0057fe5b600091825260208083206002909202909101805480845260039092526040909220805460018401546009805495975092955092936001604060020a0360a060020a80840482169590810490911693600160a060020a03938416939091169185908110610d6857fe5b90600052602060002090600491828204019190066008029054906101000a900460c060020a0287600101601c9054906101000a900463ffffffff1698509850985098509850985098505050919395979092949650565b60408051808201909152600981527f506978656c436f6e73000000000000000000000000000000000000000000000060208201525b90565b60008082801515610e3f576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b600084815260036020526040902054600160a060020a03169150811515610e9e576040805160e560020a62461bcd0281526020600482015260176024820152600080516020615180833981519152604482015290519081900360640190fd5b505050600090815260066020526040902054600160a060020a031690565b600081600160a060020a0381161515610f0d576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b5050600160a060020a031660009081526005602052604090205490565b600081801515610f72576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b600083815260036020526040902054600160a060020a0390811692508416821415610fe7576040805160e560020a62461bcd02815260206004820152601d60248201527f43616e6e6f7420617070726f766520506978656c436f6e206f776e6572000000604482015290519081900360640190fd5b33600160a060020a03831614806110215750600160a060020a038216600090815260076020908152604080832033845290915290205460ff165b151561109d576040805160e560020a62461bcd02815260206004820152603260248201527f53656e64657220646f6573206e6f742068617665207065726d697373696f6e2060448201527f746f20617070726f766520616464726573730000000000000000000000000000606482015290519081900360840190fd5b600083815260066020526040808220805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0388811691821790925591518693918616917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b60085490565b7f01ffc9a70000000000000000000000000000000000000000000000000000000081565b82600160a060020a0381161515611180576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b82600160a060020a03811615156111cf576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b82801515611215576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b61121f338561436d565b151561129b576040805160e560020a62461bcd02815260206004820152603460248201527f53656e64657220646f6573206e6f742068617665207065726d697373696f6e2060448201527f746f207472616e7366657220506978656c436f6e000000000000000000000000606482015290519081900360840190fd5b6112a5868561443b565b6112af86856144f5565b6112b9858561472f565b8385600160a060020a031687600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050505050565b6000816001604060020a0381161515611353576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b61135b6121d1565b6001604060020a038416106113a8576040805160e560020a62461bcd0281526020600482015260196024820152600080516020615140833981519152604482015290519081900360640190fd5b50506001604060020a03166000908152600a602052604090205490565b60008083600160a060020a0381161515611417576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b600160a060020a0385166000908152600460205260409020548410611486576040805160e560020a62461bcd02815260206004820152601660248201527f496e646578206973206f7574206f6620626f756e647300000000000000000000604482015290519081900360640190fd5b600160a060020a0385166000908152600460205260409020805460089190869081106114ae57fe5b90600052602060002090600491828204019190066008029054906101000a90046001604060020a03166001604060020a03168154811015156114ec57fe5b600091825260209091206002909102015495945050505050565b6000808280151561154f576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b60008481526003602052604090208054909250600160a060020a031615156115af576040805160e560020a62461bcd0281526020600482015260176024820152600080516020615180833981519152604482015290519081900360640190fd5b505460a060020a90046001604060020a031692915050565b6115e383838360206040519081016040528060008152506133b8565b505050565b600080836001604060020a038116151561163a576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b6116426121d1565b6001604060020a0386161061168f576040805160e560020a62461bcd0281526020600482015260196024820152600080516020615140833981519152604482015290519081900360640190fd5b6001604060020a0385166000908152600a602052604090205484106116fe576040805160e560020a62461bcd02815260206004820152601660248201527f496e646578206973206f7574206f6620626f756e647300000000000000000000604482015290519081900360640190fd5b6001604060020a0385166000908152600a60205260409020805460089190869081106114ae57fe5b6000808280151561176f576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b505050600090815260036020526040902054600160a060020a0316151590565b6000611799611107565b82106117dd576040805160e560020a62461bcd02815260206004820152601f60248201526000805160206150c0833981519152604482015290519081900360640190fd5b60088054839081106117eb57fe5b9060005260206000209060020201600001549050919050565b60008083600160a060020a0381161515611856576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b600160a060020a03851660009081526005602052604090205484106118c5576040805160e560020a62461bcd02815260206004820152601660248201527f496e646578206973206f7574206f6620626f756e647300000000000000000000604482015290519081900360640190fd5b600160a060020a0385166000908152600560205260409020805460089190869081106114ae57fe5b6000808080856001604060020a0381161515611941576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b6119496121d1565b6001604060020a03881610611996576040805160e560020a62461bcd0281526020600482015260196024820152600080516020615140833981519152604482015290519081900360640190fd5b6001604060020a0387166000908152600a60205260408120805490955011611a08576040805160e560020a62461bcd02815260206004820152601b60248201527f436f6c6c656374696f6e20686173206265656e20636c65617265640000000000604482015290519081900360640190fd5b600092505b8354831015611af75760088484815481101515611a2657fe5b90600052602060002090600491828204019190066008029054906101000a90046001604060020a03166001604060020a0316815481101515611a6457fe5b90600052602060002090600202019150611a82338360000154614903565b1515611aec576040805160e560020a62461bcd028152602060048201526034602482015260008051602061510083398151915260448201527f6e6572206f662074686520506978656c436f6e73000000000000000000000000606482015290519081900360840190fd5b600190920191611a0d565b85600b886001604060020a0316815481101515611b1057fe5b90600052602060002090600491828204019190066008026101000a8154816001604060020a03021916908360c060020a90040217905550866001604060020a03167f7a2598b6ea001b660b6a3a5220b528a1837bdfe8e7937b151843c9814e7a25f6876040518082600160c060020a031916600160c060020a031916815260200191505060405180910390a2509495945050505050565b606081600160a060020a0381161515611bf8576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b600160a060020a03831660009081526004602090815260409182902080548351818402810184019094528084529091830182828015611c8857602002820191906000526020600020906000905b82829054906101000a90046001604060020a03166001604060020a031681526020019060080190602082600701049283019260010382029150808411611c455790505b5050505050915050919050565b6060600060606000611ca5611107565b6001604060020a0387161115611d05576040805160e560020a62461bcd02815260206004820152601c60248201527f537461727420696e646578206973206f7574206f6620626f756e647300000000604482015290519081900360640190fd5b611d0d611107565b6001604060020a0386161115611d6d576040805160e560020a62461bcd02815260206004820152601a60248201527f456e6420696e646578206973206f7574206f6620626f756e6473000000000000604482015290519081900360640190fd5b6001604060020a038086169087161115611df7576040805160e560020a62461bcd02815260206004820152602660248201527f456e6420696e646578206973206c657373207468616e2074686520737461727460448201527f20696e6465780000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b8585039250826001604060020a0316604051908082528060200260200182016040528015611e2f578160200160208202803883390190505b509150600090505b826001604060020a0316811015611eb557600980546001604060020a0388168301908110611e6157fe5b90600052602060002090600491828204019190066008029054906101000a900460c060020a028282815181101515611e9557fe5b600160c060020a0319909216602092830290910190910152600101611e37565b8193505b50505092915050565b60008082801515611f0b576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b60008481526003602052604090208054909250600160a060020a03161515611f6b576040805160e560020a62461bcd0281526020600482015260176024820152600080516020615180833981519152604482015290519081900360640190fd5b815460088054909160a060020a90046001604060020a0316908110611f8c57fe5b6000918252602090912060029091020160010154600160a060020a0316949350505050565b6060600060606000611fc16121d1565b6001604060020a0387161115612021576040805160e560020a62461bcd02815260206004820152601c60248201527f537461727420696e646578206973206f7574206f6620626f756e647300000000604482015290519081900360640190fd5b6120296121d1565b6001604060020a0386161115612089576040805160e560020a62461bcd02815260206004820152601a60248201527f456e6420696e646578206973206f7574206f6620626f756e6473000000000000604482015290519081900360640190fd5b6001604060020a038086169087161115612113576040805160e560020a62461bcd02815260206004820152602660248201527f456e6420696e646578206973206c657373207468616e2074686520737461727460448201527f20696e6465780000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b8585039250826001604060020a031660405190808252806020026020018201604052801561214b578160200160208202803883390190505b509150600090505b826001604060020a0316811015611eb557600b80546001604060020a038816830190811061217d57fe5b90600052602060002090600491828204019190066008029054906101000a900460c060020a0282828151811015156121b157fe5b600160c060020a0319909216602092830290910190910152600101612153565b600b5490565b60008082801515612220576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b600084815260036020526040902054600160a060020a0316915081151561227f576040805160e560020a62461bcd0281526020600482015260176024820152600080516020615180833981519152604482015290519081900360640190fd5b5092915050565b60006060826001604060020a03811615156122d9576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b6122e16121d1565b6001604060020a0385161061232e576040805160e560020a62461bcd0281526020600482015260196024820152600080516020615140833981519152604482015290519081900360640190fd5b600b80546001604060020a03861690811061234557fe5b600091825260208083206004830401546001604060020a0388168452600a8252604093849020805485518185028101850190965280865260039094166008026101000a90910460c060020a0293909290918391908301828280156123fa57602002820191906000526020600020906000905b82829054906101000a90046001604060020a03166001604060020a0316815260200190600801906020826007010492830192600103820291508084116123b75790505b505050505090509250925050915091565b600154600160a060020a031690565b600081600160a060020a038116151561246b576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b5050600160a060020a031660009081526004602052604090205490565b600080838015156124d1576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b6124db3386614903565b1515612545576040805160e560020a62461bcd028152602060048201526023602482015260008051602061510083398151915260448201527f6e65720000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60008581526003602052604090208054600980549294508692909160a060020a90046001604060020a031690811061257957fe5b90600052602060002090600491828204019190066008026101000a8154816001604060020a03021916908360c060020a90040217905550847fd3d90f94542b3ca93f1a474e55393834e376ebbac7df618dcf7f9327c57d6c5e856040518082600160c060020a031916600160c060020a031916815260200191505060405180910390a2505460a060020a90046001604060020a03169392505050565b6000816001604060020a0381161515612666576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b61266e6121d1565b6001604060020a038416106126bb576040805160e560020a62461bcd0281526020600482015260196024820152600080516020615140833981519152604482015290519081900360640190fd5b50506001604060020a03166000908152600a60205260409020541590565b60408051808201909152600481527f5058434e00000000000000000000000000000000000000000000000000000000602082015290565b600154600160a060020a03163314612798576040805160e560020a62461bcd02815260206004820152602560248201527f4f6e6c79207468652061646d696e2063616e2063616c6c20746869732066756e60448201527f6374696f6e000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600080808080808089600160a060020a038116151561281e576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b89801515612864576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b60008b81526003602052604090206008549098506001604060020a03116128fb576040805160e560020a62461bcd02815260206004820152602860248201527f4d6178206e756d626572206f6620506978656c436f6e7320686173206265656e60448201527f2072656163686564000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b8754600160a060020a03161561295b576040805160e560020a62461bcd02815260206004820152601760248201527f506978656c436f6e20616c726561647920657869737473000000000000000000604482015290519081900360640190fd5b60009650640100000000421015612970574296505b6008805489547bffffffffffffffff0000000000000000000000000000000000000000191660a060020a6001604060020a03831602178a558154909750906129bb9060018301614f7f565b5060098054906129ce9060018301614fab565b50600880546001604060020a0388169081106129e657fe5b600091825260209091206002909102018b81556001810180543373ffffffffffffffffffffffffffffffffffffffff19909116177bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e060020a63ffffffff8b1602179055600980549196508b916001604060020a038916908110612a6457fe5b60009182526020808320600483040180546001604060020a0360039094166008026101000a938402191660c060020a909504929092029390931790553381526005909152604090208054909450925082612ac18560018301614fab565b50858484815481101515612ad157fe5b90600052602060002090600491828204019190066008026101000a8154816001604060020a0302191690836001604060020a03160217905550612b148c8c61472f565b604080516001604060020a0388168152600160a060020a038e166020820152815133928e927f5ada7cc76c691909522f79b403dee86482e43a5064fb2d5849c685ab7d40be20929081900390910190a36040518b90600160a060020a038e16906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450939a9950505050505050505050565b6000808080846001604060020a0381161515612c00576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b612c086121d1565b6001604060020a03871610612c55576040805160e560020a62461bcd0281526020600482015260196024820152600080516020615140833981519152604482015290519081900360640190fd5b6001604060020a0386166000908152600a60205260408120805490955011612cc7576040805160e560020a62461bcd02815260206004820152601d60248201527f436f6c6c656374696f6e20697320616c726561647920636c6561726564000000604482015290519081900360640190fd5b600092505b8354831015612ddd5760088484815481101515612ce557fe5b90600052602060002090600491828204019190066008029054906101000a90046001604060020a03166001604060020a0316815481101515612d2357fe5b90600052602060002090600202019150612d41338360000154614903565b1515612dab576040805160e560020a62461bcd028152602060048201526034602482015260008051602061510083398151915260448201527f6e6572206f662074686520506978656c436f6e73000000000000000000000000606482015290519081900360840190fd5b600180830180547bffffffffffffffff0000000000000000000000000000000000000000191690559290920191612ccc565b600b80546001604060020a038816908110612df457fe5b60009182526020808320600483040180546001604060020a0360086003909516949094026101000a8402191690559088168252600a905260408120612e3891614fdf565b6040516001604060020a038716907fde081b46744cc92faa6c6d642ed219cefffea3d48bb6886384897031160b9a6190600090a25093949350505050565b81600160a060020a0381161515612ec5576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b600160a060020a038316331415612f26576040805160e560020a62461bcd02815260206004820152601360248201527f43616e6e6f7420617070726f76652073656c6600000000000000000000000000604482015290519081900360640190fd5b336000818152600760209081526040808320600160a060020a03881680855290835292819020805460ff1916871515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a3505050565b600154600160a060020a0316331461301d576040805160e560020a62461bcd02815260206004820152602560248201527f4f6e6c79207468652061646d696e2063616e2063616c6c20746869732066756e60448201527f6374696f6e000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b604051600160a060020a03821690303180156108fc02916000818181858888f19350505050158015613053573d6000803e3d6000fd5b5050565b6060600b8054806020026020016040519081016040528092919081815260200182805480156130d557602002820191906000526020600020906000905b82829054906101000a900460c060020a02600160c060020a031916815260200190600801906020826007010492830192600103820291508084116130945790505b5050505050905090565b6060816001604060020a0381161515613130576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b6001604060020a0383166000908152600a602090815260409182902080548351818402810184019094528084529091830182828015611c8857600091825260209182902080546001604060020a03168452908202830192909160089101808411611c4557509498975050505050505050565b60008080808080808080898015156131f2576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b60008b81526003602052604090208054909350600160a060020a03161515613252576040805160e560020a62461bcd0281526020600482015260176024820152600080516020615180833981519152604482015290519081900360640190fd5b825460088054909160a060020a90046001604060020a031690811061327357fe5b6000918252602090912060029091020180548454600183015460098054949650929360a060020a8084046001604060020a03908116959184041693600160a060020a03908116931691859081106132c657fe5b90600052602060002090600491828204019190066008029054906101000a900460c060020a0287600101601c9054906101000a900463ffffffff169950995099509950995099509950505050919395979092949650565b600154600160a060020a031633146133a5576040805160e560020a62461bcd02815260206004820152602560248201527f4f6e6c79207468652061646d696e2063616e2063616c6c20746869732066756e60448201527f6374696f6e000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b8051613053906002906020840190615007565b6133c3848484611131565b6133cf8484848461498d565b1515613425576040805160e560020a62461bcd02815260206004820152601560248201527f5472616e7366657220776173206e6f7420736166650000000000000000000000604482015290519081900360640190fd5b50505050565b60008082801515613474576040805160e560020a62461bcd02815260206004820152600a6024820152600080516020615120833981519152604482015290519081900360640190fd5b60008481526003602052604090208054909250600160a060020a031615156134d4576040805160e560020a62461bcd0281526020600482015260176024820152600080516020615180833981519152604482015290519081900360640190fd5b60008481526003602052604090205460088054909160a060020a90046001604060020a031690811061350257fe5b600091825260209091206002909102016001015460a060020a90046001604060020a0316949350505050565b60008060008060008060016801000000000000000003600b805490501015156135c7576040805160e560020a62461bcd02815260206004820152602a60248201527f4d6178206e756d626572206f6620636f6c6c656374696f6e732068617320626560448201527f656e207265616368656400000000000000000000000000000000000000000000606482015290519081900360840190fd5b8751600110613646576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6c6c656374696f6e206d75737420636f6e7461696e206d6f72652074686160448201527f6e206f6e6520506978656c436f6e000000000000000000000000000000000000606482015290519081900360840190fd5b600b546001604060020a0381166000908152600a60205260409020895191965094506136728582614fab565b50600092505b87518310156138ad57878381518110151561368f57fe5b9060200190602002015191506136a3611107565b6001604060020a038316106136f0576040805160e560020a62461bcd02815260206004820152601f60248201526000805160206150c0833981519152604482015290519081900360640190fd5b600880546001604060020a03841690811061370757fe5b90600052602060002090600202019050613725338260000154614903565b151561378f576040805160e560020a62461bcd028152602060048201526034602482015260008051602061510083398151915260448201527f6e6572206f662074686520506978656c436f6e73000000000000000000000000606482015290519081900360840190fd5b600181015460a060020a90046001604060020a03161561381f576040805160e560020a62461bcd02815260206004820152602360248201527f506978656c436f6e20697320616c726561647920696e206120636f6c6c65637460448201527f696f6e0000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b6001810180547bffffffffffffffff0000000000000000000000000000000000000000191660a060020a6001604060020a038816021790558354829085908590811061386757fe5b90600052602060002090600491828204019190066008026101000a8154816001604060020a0302191690836001604060020a031602179055508280600101935050613678565b600b8054906138bf9060018301614fab565b5086600b866001604060020a03168154811015156138d957fe5b90600052602060002090600491828204019190066008026101000a8154816001604060020a03021916908360c060020a90040217905550846001604060020a031633600160a060020a03167f19c41bfdfa6988beb6f4ed9b9b4bc922dfe576b16b8299b466350ebb8f8ff0cd60405160405180910390a350929695505050505050565b600081815260036020526040812080546060929081908490600160a060020a031615156139c1576040805160e560020a62461bcd0281526020600482015260176024820152600080516020615180833981519152604482015290519081900360640190fd5b835460088054909160a060020a90046001604060020a03169081106139e257fe5b9060005260206000209060020201925060098460000160149054906101000a90046001604060020a03166001604060020a0316815481101515613a2157fe5b90600052602060002090600491828204019190066008029054906101000a900460c060020a02915060028054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613adf5780601f10613ab457610100808354040283529160200191613adf565b820191906000526020600020905b815481529060010190602001808311613ac257829003601f168201915b50505050509050613b30816040805190810160405280600981526020017f3c746f6b656e49643e0000000000000000000000000000000000000000000000815250613b2b896020614afa565b614c9a565b60408051808201909152600c81527f3c746f6b656e496e6465783e000000000000000000000000000000000000000060208201528554919250613b8b91839190613b2b9060a060020a90046001604060020a03166008614afa565b9050613bd9816040805190810160405280600681526020017f3c6e616d653e0000000000000000000000000000000000000000000000000000815250613b2b8560c060020a90046008614afa565b60408051808201909152600781527f3c6f776e65723e0000000000000000000000000000000000000000000000000060208201528554919250613c2d91839190613b2b90600160a060020a03166014614afa565b60408051808201909152600981527f3c63726561746f723e000000000000000000000000000000000000000000000060208201526001850154919250613c8491839190613b2b90600160a060020a03166014614afa565b60408051808201909152600d81527f3c64617465437265617465643e0000000000000000000000000000000000000060208201526001850154919250613cdf91839190613b2b9060e060020a900463ffffffff166008614afa565b60408051808201909152601181527f3c636f6c6c656374696f6e496e6465783e00000000000000000000000000000060208201526001850154919250613d3d91839190613b2b9060a060020a90046001604060020a03166008614afa565b9695505050505050565b606081600160a060020a0381161515613d98576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b600160a060020a03831660009081526005602090815260409182902080548351818402810184019094528084529091830182828015611c8857600091825260209182902080546001604060020a03168452908202830192909160089101808411611c4557509498975050505050505050565b6000816001604060020a0381161515613e5b576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b613e636121d1565b836001604060020a031610915050919050565b6060806060806060806060806000808a51604051908082528060200260200182016040528015613eb0578160200160208202803883390190505b5095508a51604051908082528060200260200182016040528015613ede578160200160208202803883390190505b5094508a51604051908082528060200260200182016040528015613f0c578160200160208202803883390190505b5093508a51604051908082528060200260200182016040528015613f3a578160200160208202803883390190505b509250600091505b8a51821015614139578a82815181101515613f5957fe5b906020019060200201519050613f6d611107565b6001604060020a03821610613fba576040805160e560020a62461bcd02815260206004820152601f60248201526000805160206150c0833981519152604482015290519081900360640190fd5b600880546001604060020a038316908110613fd157fe5b9060005260206000209060020201600001548683815181101515613ff157fe5b60209081029091010152600980546001604060020a03831690811061401257fe5b90600052602060002090600491828204019190066008029054906101000a900460c060020a02858381518110151561404657fe5b600160c060020a0319909216602092830290910190910152600880546003916000916001604060020a03851690811061407b57fe5b6000918252602080832060029092029091015483528201929092526040019020548451600160a060020a03909116908590849081106140b657fe5b600160a060020a03909216602092830290910190910152600880546001604060020a0383169081106140e457fe5b906000526020600020906002020160010160149054906101000a90046001604060020a0316838381518110151561411757fe5b6001604060020a03909216602092830290910190910152600190910190613f42565b509399929850909650945092505050565b6000816001604060020a038116151561419b576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020615160833981519152604482015290519081900360640190fd5b6141a36121d1565b6001604060020a038416106141f0576040805160e560020a62461bcd0281526020600482015260196024820152600080516020615140833981519152604482015290519081900360640190fd5b600b80546001604060020a03851690811061420757fe5b90600052602060002090600491828204019190066008029054906101000a900460c060020a02915050919050565b600082600160a060020a0381161515614286576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b82600160a060020a03811615156142d5576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206150e0833981519152604482015290519081900360640190fd5b505050600160a060020a03918216600090815260076020908152604080832093909416825291909152205460ff1690565b606060098054806020026020016040519081016040528092919081815260200182805480156130d5576000918252602091829020805460c060020a02600160c060020a03191684529082028301929091600891018084116130945790505050505050905090565b600081815260036020526040812054600160a060020a03168015156143ca576040805160e560020a62461bcd0281526020600482015260176024820152600080516020615180833981519152604482015290519081900360640190fd5b80600160a060020a031684600160a060020a031614806144035750600083815260066020526040902054600160a060020a038581169116145b806144335750600160a060020a0380821660009081526007602090815260408083209388168352929052205460ff165b949350505050565b600081815260036020526040902054600160a060020a038381169116146144ac576040805160e560020a62461bcd02815260206004820152601860248201527f496e636f727265637420506978656c436f6e206f776e65720000000000000000604482015290519081900360640190fd5b600081815260066020526040902054600160a060020a031615613053576000908152600660205260409020805473ffffffffffffffffffffffffffffffffffffffff1916905550565b600160a060020a03808316600081815260046020908152604080832086845260039092528220805491949093911614614578576040805160e560020a62461bcd02815260206004820152601960248201527f46726f6d206164647265737320697320696e636f727265637400000000000000604482015290519081900360640190fd5b815473ffffffffffffffffffffffffffffffffffffffff191682558254839060001981019081106145a557fe5b90600052602060002090600491828204019190066008029054906101000a90046001604060020a031690508260018480549050038154811015156145e557fe5b90600052602060002090600491828204019190066008026101000a8154906001604060020a030219169055828054809190600190036146249190614fab565b508254825460e060020a900463ffffffff16101561470757815483548291859160e060020a90910463ffffffff1690811061465b57fe5b90600052602060002090600491828204019190066008026101000a8154816001604060020a0302191690836001604060020a0316021790555081600001601c9054906101000a900463ffffffff16600360006008846001604060020a03168154811015156146c557fe5b9060005260206000209060020201600001548152602001908152602001600020600001601c6101000a81548163ffffffff021916908363ffffffff1602179055505b5080547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169055505050565b600160a060020a03821660009081526004602090815260408083208484526003909252822081549192909163ffffffff116147da576040805160e560020a62461bcd02815260206004820152603260248201527f4d6178206e756d626572206f6620506978656c436f6e7320706572206f776e6560448201527f7220686173206265656e20726561636865640000000000000000000000000000606482015290519081900360840190fd5b8154600160a060020a03161561483a576040805160e560020a62461bcd02815260206004820152601d60248201527f506978656c436f6e20616c72656164792068617320616e206f776e6572000000604482015290519081900360640190fd5b50805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385161781558154806148718460018301614fab565b5081547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e060020a63ffffffff83160217808355835460a060020a9091046001604060020a0316908490839081106148c357fe5b90600052602060002090600491828204019190066008026101000a8154816001604060020a0302191690836001604060020a031602179055505050505050565b6000818152600360205260408120805460088054600160a060020a0383169285929160a060020a9091046001604060020a031690811061493f57fe5b6000918252602090912060016002909202010154600160a060020a039081169150868116908316148015613d3d575080600160a060020a031686600160a060020a0316149695505050505050565b6000806149a285600160a060020a0316614e2e565b15156149b15760019150614af1565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201818152600160a060020a03898116602485015260448401889052608060648501908152875160848601528751918a169463150b7a0294938c938b938b93909160a490910190602085019080838360005b83811015614a44578181015183820152602001614a2c565b50505050905090810190601f168015614a715780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614a9357600080fd5b505af1158015614aa7573d6000803e3d6000fd5b505050506040513d6020811015614abd57600080fd5b5051600160e060020a031981167f150b7a020000000000000000000000000000000000000000000000000000000014925090505b50949350505050565b606080600080600080866002026002016040519080825280601f01601f191660200182016040528015614b37578160200160208202803883390190505b509450603060f860020a02856000815181101515614b5157fe5b906020010190600160f860020a031916908160001a90535084517f78000000000000000000000000000000000000000000000000000000000000009086906001908110614b9a57fe5b906020010190600160f860020a031916908160001a905350600093505b86841015614c8e5783600188030360080260020a88811515614bd557fe5b0460f860020a02925060108360f860020a900460ff16811515614bf457fe5b0460f860020a0291508160f860020a90046010028360f860020a90040360f860020a029050614c2282614e36565b8585600202600201815181101515614c3657fe5b906020010190600160f860020a031916908160001a905350614c5781614e36565b8585600202600301815181101515614c6b57fe5b906020010190600160f860020a031916908160001a905350600190930192614bb7565b50929695505050505050565b606083838360008481614cad8686614eb2565b92508551831015614e1d5784518451875101036040519080825280601f01601f191660200182016040528015614ced578160200160208202803883390190505b509150600090505b82811015614d4c578581815181101515614d0b57fe5b90602001015160f860020a900460f860020a028282815181101515614d2c57fe5b906020010190600160f860020a031916908160001a905350600101614cf5565b5060005b8351811015614daa578381815181101515614d6757fe5b90602001015160f860020a900460f860020a0282828501815181101515614d8a57fe5b906020010190600160f860020a031916908160001a905350600101614d50565b5060005b84518301865103811015614e155785818651850101815181101515614dcf57fe5b90602001015160f860020a900460f860020a0282828651860101815181101515614df557fe5b906020010190600160f860020a031916908160001a905350600101614dae565b819650614e21565b8596505b5050505050509392505050565b6000903b1190565b60007f0a000000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000083161015614e9a578160f860020a900460300160f860020a029050610c81565b8160f860020a900460570160f860020a029050610c81565b60008080805b6001855103865103831015614f7457506001905060005b8451811015614f5b578481815181101515614ee657fe5b90602001015160f860020a900460f860020a02600160f860020a03191686828501815181101515614f1357fe5b60209101015160f860020a90819004027fff000000000000000000000000000000000000000000000000000000000000001614614f535760009150614f5b565b600101614ecf565b8115614f6957829350611eb9565b600190920191614eb8565b505092519392505050565b8154818355818111156115e3576002028160020283600052602060002091820191016115e39190615085565b8154818355818111156115e35760030160049004816003016004900483600052602060002091820191016115e391906150a5565b50805460008255600301600490049060005260206000209081019061500491906150a5565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061504857805160ff1916838001178555615075565b82800160010185558215615075579182015b8281111561507557825182559160200191906001019061505a565b506150819291506150a5565b5090565b610df391905b80821115615081576000808255600182015560020161508b565b610df391905b8082111561508157600081556001016150ab5600506978656c436f6e20696e646578206973206f7574206f6620626f756e647300496e76616c69642061646472657373000000000000000000000000000000000053656e646572206973206e6f74207468652063726561746f7220616e64206f77496e76616c696420494400000000000000000000000000000000000000000000436f6c6c656374696f6e20646f6573206e6f7420657869737400000000000000496e76616c696420696e64657800000000000000000000000000000000000000506978656c436f6e20646f6573206e6f74206578697374000000000000000000a165627a7a7230582077ffeec90901ca8892dfe29369dbc8502d147fb5bb835c420d9b2b4b96eb29620029
Verified Source Code Partial Match
Compiler: v0.4.24+commit.e67f0147
EVM: byzantium
Optimization: Yes (200 runs)
PixelCons.sol 1217 lines
pragma solidity ^0.4.24;
/**
* @title ERC721 Non-Fungible Token Standard Basic Interface
* @dev Based on openzepplin open source ERC721 examples.
* See (https://github.com/OpenZeppelin/openzeppelin-solidity)
*/
contract ERC721 {
/**
* @dev 0x01ffc9a7 ===
* bytes4(keccak256('supportsInterface(bytes4)'))
*/
bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
/**
* @dev 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)'))
*/
bytes4 internal constant InterfaceId_ERC721 = 0x80ac58cd;
/**
* @dev 0x780e9d63 ===
* bytes4(keccak256('totalSupply()')) ^
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
* bytes4(keccak256('tokenByIndex(uint256)'))
*/
bytes4 internal constant InterfaceId_ERC721Enumerable = 0x780e9d63;
/**
* @dev 0x5b5e139f ===
* bytes4(keccak256('name()')) ^
* bytes4(keccak256('symbol()')) ^
* bytes4(keccak256('tokenURI(uint256)'))
*/
bytes4 internal constant InterfaceId_ERC721Metadata = 0x5b5e139f;
/** @dev A mapping of interface id to whether or not it is supported */
mapping(bytes4 => bool) internal supportedInterfaces;
/** @dev Token events */
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);
/** @dev Registers ERC-165, ERC-721, ERC-721 Enumerable and ERC-721 Metadata as supported interfaces */
constructor() public
{
registerInterface(InterfaceId_ERC165);
registerInterface(InterfaceId_ERC721);
registerInterface(InterfaceId_ERC721Enumerable);
registerInterface(InterfaceId_ERC721Metadata);
}
/** @dev Internal function for registering an interface */
function registerInterface(bytes4 _interfaceId) internal
{
require(_interfaceId != 0xffffffff);
supportedInterfaces[_interfaceId] = true;
}
/** @dev ERC-165 interface implementation */
function supportsInterface(bytes4 _interfaceId) external view returns(bool)
{
return supportedInterfaces[_interfaceId];
}
/** @dev ERC-721 interface */
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;
/** @dev ERC-721 Enumerable interface */
function totalSupply() public view returns(uint256 _total);
function tokenByIndex(uint256 _index) public view returns(uint256 _tokenId);
function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns(uint256 _tokenId);
/** @dev ERC-721 Metadata interface */
function name() public view returns(string _name);
function symbol() public view returns(string _symbol);
function tokenURI(uint256 _tokenId) public view returns(string);
}
/**
* @title PixelCons Core
* @notice The purpose of this contract is to provide a shared ecosystem of minimal pixel art tokens for everyone to use. All users are treated
* equally with the exception of an admin user who only controls the ERC721 metadata function which points to the app website. No fees are
* required to interact with this contract beyond base gas fees. Here are a few notes on the basic workings of the contract:
* PixelCons [The core ERC721 token of this contract]
* -Each PixelCon is unique with an ID that encodes all its pixel data
* -PixelCons can be identified by both TokenIDs and TokenIndexes (index requires fewer bits to store)
* -A PixelCon can never be destroyed
* -Total number of PixelCons is limited to 18,446,744,073,709,551,616 (2^64)
* -A single account can only hold 4,294,967,296 PixelCons (2^32)
* Collections [Grouping mechanism for associating PixelCons together]
* -Collections are identified by an index (zero is invalid)
* -Collections can only be created by a user who both created and currently owns all its PixelCons
* -Total number of collections is limited to 18,446,744,073,709,551,616 (2^64)
* For more information about PixelCons, please visit (https://pixelcons.io)
* @dev This contract follows the ERC721 token standard with additional functions for creating, grouping, etc.
* See (https://github.com/OpenZeppelin/openzeppelin-solidity)
* @author PixelCons
*/
contract PixelCons is ERC721 {
using AddressUtils for address;
/** @dev Equal to 'bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))' */
bytes4 private constant ERC721_RECEIVED = 0x150b7a02;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////// Structs ///////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** @dev The main PixelCon struct */
struct PixelCon {
uint256 tokenId;
//// ^256bits ////
address creator;
uint64 collectionIndex;
uint32 dateCreated;
}
/** @dev A struct linking a token owner with its token index */
struct TokenLookup {
address owner;
uint64 tokenIndex;
uint32 ownedIndex;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////// Storage ///////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** @dev The address thats allowed to withdraw volunteered funds sent to this contract */
address internal admin;
/** @dev The URI template for retrieving token metadata */
string internal tokenURITemplate;
////////////////// PixelCon Tokens //////////////////
/** @dev Mapping from token ID to owner/index */
mapping(uint256 => TokenLookup) internal tokenLookup;
/** @dev Mapping from owner to token indexes */
mapping(address => uint64[]) internal ownedTokens;
/** @dev Mapping from creator to token indexes */
mapping(address => uint64[]) internal createdTokens;
/** @dev Mapping from token ID to approved address */
mapping(uint256 => address) internal tokenApprovals;
/** @dev Mapping from owner to operator approvals */
mapping(address => mapping(address => bool)) internal operatorApprovals;
/** @dev An array containing all PixelCons in existence */
PixelCon[] internal pixelcons;
/** @dev An array that mirrors 'pixelcons' in terms of indexing, but stores only name data */
bytes8[] internal pixelconNames;
////////////////// Collections //////////////////
/** @dev Mapping from collection index to token indexes */
mapping(uint64 => uint64[]) internal collectionTokens;
/** @dev An array that mirrors 'collectionTokens' in terms of indexing, but stores only name data */
bytes8[] internal collectionNames;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////// Events ////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** @dev PixelCon token events */
event Create(uint256 indexed _tokenId, address indexed _creator, uint64 _tokenIndex, address _to);
event Rename(uint256 indexed _tokenId, bytes8 _newName);
/** @dev PixelCon collection events */
event CreateCollection(address indexed _creator, uint64 indexed _collectionIndex);
event RenameCollection(uint64 indexed _collectionIndex, bytes8 _newName);
event ClearCollection(uint64 indexed _collectionIndex);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////// Modifiers ///////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** @dev Small validators for quick validation of function parameters */
modifier validIndex(uint64 _index) {
require(_index != uint64(0), "Invalid index");
_;
}
modifier validId(uint256 _id) {
require(_id != uint256(0), "Invalid ID");
_;
}
modifier validAddress(address _address) {
require(_address != address(0), "Invalid address");
_;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////// PixelCons Core ///////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Contract constructor
*/
constructor() public
{
//admin defaults to the contract creator
admin = msg.sender;
//fill zero index pixelcon collection
collectionNames.length++;
}
/**
* @notice Get the current admin
* @return The current admin
*/
function getAdmin() public view returns(address)
{
return admin;
}
/**
* @notice Withdraw all volunteered funds to `(_to)`
* @param _to Address to withdraw the funds to
*/
function adminWithdraw(address _to) public
{
require(msg.sender == admin, "Only the admin can call this function");
_to.transfer(address(this).balance);
}
/**
* @notice Change the admin to `(_to)`
* @param _newAdmin New admin address
*/
function adminChange(address _newAdmin) public
{
require(msg.sender == admin, "Only the admin can call this function");
admin = _newAdmin;
}
/**
* @notice Change the token URI template
* @param _newTokenURITemplate New token URI template
*/
function adminSetTokenURITemplate(string _newTokenURITemplate) public
{
require(msg.sender == admin, "Only the admin can call this function");
tokenURITemplate = _newTokenURITemplate;
}
////////////////// PixelCon Tokens //////////////////
/**
* @notice Create PixelCon `(_tokenId)`
* @dev Throws if the token ID already exists
* @param _to Address that will own the PixelCon
* @param _tokenId ID of the PixelCon to be creates
* @param _name PixelCon name (not required)
* @return The index of the new PixelCon
*/
function create(address _to, uint256 _tokenId, bytes8 _name) public payable validAddress(_to) validId(_tokenId) returns(uint64)
{
TokenLookup storage lookupData = tokenLookup[_tokenId];
require(pixelcons.length < uint256(2 ** 64) - 1, "Max number of PixelCons has been reached");
require(lookupData.owner == address(0), "PixelCon already exists");
//get created timestamp (zero as date indicates null)
uint32 dateCreated = 0;
if (now < uint256(2 ** 32)) dateCreated = uint32(now);
//create PixelCon token and set owner
uint64 index = uint64(pixelcons.length);
lookupData.tokenIndex = index;
pixelcons.length++;
pixelconNames.length++;
PixelCon storage pixelcon = pixelcons[index];
pixelcon.tokenId = _tokenId;
pixelcon.creator = msg.sender;
pixelcon.dateCreated = dateCreated;
pixelconNames[index] = _name;
uint64[] storage createdList = createdTokens[msg.sender];
uint createdListIndex = createdList.length;
createdList.length++;
createdList[createdListIndex] = index;
addTokenTo(_to, _tokenId);
emit Create(_tokenId, msg.sender, index, _to);
emit Transfer(address(0), _to, _tokenId);
return index;
}
/**
* @notice Rename PixelCon `(_tokenId)`
* @dev Throws if the caller is not the owner and creator of the token
* @param _tokenId ID of the PixelCon to rename
* @param _name New name
* @return The index of the PixelCon
*/
function rename(uint256 _tokenId, bytes8 _name) public validId(_tokenId) returns(uint64)
{
require(isCreatorAndOwner(msg.sender, _tokenId), "Sender is not the creator and owner");
//update name
TokenLookup storage lookupData = tokenLookup[_tokenId];
pixelconNames[lookupData.tokenIndex] = _name;
emit Rename(_tokenId, _name);
return lookupData.tokenIndex;
}
/**
* @notice Check if PixelCon `(_tokenId)` exists
* @param _tokenId ID of the PixelCon to query the existence of
* @return True if the PixelCon exists
*/
function exists(uint256 _tokenId) public view validId(_tokenId) returns(bool)
{
address owner = tokenLookup[_tokenId].owner;
return owner != address(0);
}
/**
* @notice Get the creator of PixelCon `(_tokenId)`
* @dev Throws if PixelCon does not exist
* @param _tokenId ID of the PixelCon to query the creator of
* @return Creator address for PixelCon
*/
function creatorOf(uint256 _tokenId) public view validId(_tokenId) returns(address)
{
TokenLookup storage lookupData = tokenLookup[_tokenId];
require(lookupData.owner != address(0), "PixelCon does not exist");
return pixelcons[lookupData.tokenIndex].creator;
}
/**
* @notice Get the total number of PixelCons created by `(_creator)`
* @param _creator Address to query the total of
* @return Total number of PixelCons created by given address
*/
function creatorTotal(address _creator) public view validAddress(_creator) returns(uint256)
{
return createdTokens[_creator].length;
}
/**
* @notice Enumerate PixelCon created by `(_creator)`
* @dev Throws if index is out of bounds
* @param _creator Creator address
* @param _index Counter less than `creatorTotal(_creator)`
* @return PixelCon ID for the `(_index)`th PixelCon created by `(_creator)`
*/
function tokenOfCreatorByIndex(address _creator, uint256 _index) public view validAddress(_creator) returns(uint256)
{
require(_index < createdTokens[_creator].length, "Index is out of bounds");
PixelCon storage pixelcon = pixelcons[createdTokens[_creator][_index]];
return pixelcon.tokenId;
}
/**
* @notice Get all details of PixelCon `(_tokenId)`
* @dev Throws if PixelCon does not exist
* @param _tokenId ID of the PixelCon to get details for
* @return PixelCon details
*/
function getTokenData(uint256 _tokenId) public view validId(_tokenId)
returns(uint256 _tknId, uint64 _tknIdx, uint64 _collectionIdx, address _owner, address _creator, bytes8 _name, uint32 _dateCreated)
{
TokenLookup storage lookupData = tokenLookup[_tokenId];
require(lookupData.owner != address(0), "PixelCon does not exist");
PixelCon storage pixelcon = pixelcons[lookupData.tokenIndex];
return (pixelcon.tokenId, lookupData.tokenIndex, pixelcon.collectionIndex, lookupData.owner,
pixelcon.creator, pixelconNames[lookupData.tokenIndex], pixelcon.dateCreated);
}
/**
* @notice Get all details of PixelCon #`(_tokenIndex)`
* @dev Throws if PixelCon does not exist
* @param _tokenIndex Index of the PixelCon to get details for
* @return PixelCon details
*/
function getTokenDataByIndex(uint64 _tokenIndex) public view
returns(uint256 _tknId, uint64 _tknIdx, uint64 _collectionIdx, address _owner, address _creator, bytes8 _name, uint32 _dateCreated)
{
require(_tokenIndex < totalSupply(), "PixelCon index is out of bounds");
PixelCon storage pixelcon = pixelcons[_tokenIndex];
TokenLookup storage lookupData = tokenLookup[pixelcon.tokenId];
return (pixelcon.tokenId, lookupData.tokenIndex, pixelcon.collectionIndex, lookupData.owner,
pixelcon.creator, pixelconNames[lookupData.tokenIndex], pixelcon.dateCreated);
}
/**
* @notice Get the index of PixelCon `(_tokenId)`
* @dev Throws if PixelCon does not exist
* @param _tokenId ID of the PixelCon to query the index of
* @return Index of the given PixelCon ID
*/
function getTokenIndex(uint256 _tokenId) validId(_tokenId) public view returns(uint64)
{
TokenLookup storage lookupData = tokenLookup[_tokenId];
require(lookupData.owner != address(0), "PixelCon does not exist");
return lookupData.tokenIndex;
}
////////////////// Collections //////////////////
/**
* @notice Create PixelCon collection
* @dev Throws if the message sender is not the owner and creator of the given tokens
* @param _tokenIndexes Token indexes to group together into a collection
* @param _name Name of the collection
* @return Index of the new collection
*/
function createCollection(uint64[] _tokenIndexes, bytes8 _name) public returns(uint64)
{
require(collectionNames.length < uint256(2 ** 64) - 1, "Max number of collections has been reached");
require(_tokenIndexes.length > 1, "Collection must contain more than one PixelCon");
//loop through given indexes to add to collection and check additional requirements
uint64 collectionIndex = uint64(collectionNames.length);
uint64[] storage collection = collectionTokens[collectionIndex];
collection.length = _tokenIndexes.length;
for (uint i = 0; i < _tokenIndexes.length; i++) {
uint64 tokenIndex = _tokenIndexes[i];
require(tokenIndex < totalSupply(), "PixelCon index is out of bounds");
PixelCon storage pixelcon = pixelcons[tokenIndex];
require(isCreatorAndOwner(msg.sender, pixelcon.tokenId), "Sender is not the creator and owner of the PixelCons");
require(pixelcon.collectionIndex == uint64(0), "PixelCon is already in a collection");
pixelcon.collectionIndex = collectionIndex;
collection[i] = tokenIndex;
}
collectionNames.length++;
collectionNames[collectionIndex] = _name;
emit CreateCollection(msg.sender, collectionIndex);
return collectionIndex;
}
/**
* @notice Rename collection #`(_collectionIndex)`
* @dev Throws if the message sender is not the owner and creator of all collection tokens
* @param _collectionIndex Index of the collection to rename
* @param _name New name
* @return Index of the collection
*/
function renameCollection(uint64 _collectionIndex, bytes8 _name) validIndex(_collectionIndex) public returns(uint64)
{
require(_collectionIndex < totalCollections(), "Collection does not exist");
//loop through the collections token indexes and check additional requirements
uint64[] storage collection = collectionTokens[_collectionIndex];
require(collection.length > 0, "Collection has been cleared");
for (uint i = 0; i < collection.length; i++) {
PixelCon storage pixelcon = pixelcons[collection[i]];
require(isCreatorAndOwner(msg.sender, pixelcon.tokenId), "Sender is not the creator and owner of the PixelCons");
}
//update
collectionNames[_collectionIndex] = _name;
emit RenameCollection(_collectionIndex, _name);
return _collectionIndex;
}
/**
* @notice Clear collection #`(_collectionIndex)`
* @dev Throws if the message sender is not the owner and creator of all collection tokens
* @param _collectionIndex Index of the collection to clear out
* @return Index of the collection
*/
function clearCollection(uint64 _collectionIndex) validIndex(_collectionIndex) public returns(uint64)
{
require(_collectionIndex < totalCollections(), "Collection does not exist");
//loop through the collections token indexes and check additional requirements while clearing pixelcon collection index
uint64[] storage collection = collectionTokens[_collectionIndex];
require(collection.length > 0, "Collection is already cleared");
for (uint i = 0; i < collection.length; i++) {
PixelCon storage pixelcon = pixelcons[collection[i]];
require(isCreatorAndOwner(msg.sender, pixelcon.tokenId), "Sender is not the creator and owner of the PixelCons");
pixelcon.collectionIndex = 0;
}
//clear out collection data
delete collectionNames[_collectionIndex];
delete collectionTokens[_collectionIndex];
emit ClearCollection(_collectionIndex);
return _collectionIndex;
}
/**
* @notice Check if collection #`(_collectionIndex)` exists
* @param _collectionIndex Index of the collection to query the existence of
* @return True if collection exists
*/
function collectionExists(uint64 _collectionIndex) public view validIndex(_collectionIndex) returns(bool)
{
return _collectionIndex < totalCollections();
}
/**
* @notice Check if collection #`(_collectionIndex)` has been cleared
* @dev Throws if the collection index is out of bounds
* @param _collectionIndex Index of the collection to query the state of
* @return True if collection has been cleared
*/
function collectionCleared(uint64 _collectionIndex) public view validIndex(_collectionIndex) returns(bool)
{
require(_collectionIndex < totalCollections(), "Collection does not exist");
return collectionTokens[_collectionIndex].length == uint256(0);
}
/**
* @notice Get the total number of collections
* @return Total number of collections
*/
function totalCollections() public view returns(uint256)
{
return collectionNames.length;
}
/**
* @notice Get the collection index of PixelCon `(_tokenId)`
* @dev Throws if the PixelCon does not exist
* @param _tokenId ID of the PixelCon to query the collection of
* @return Collection index of given PixelCon
*/
function collectionOf(uint256 _tokenId) public view validId(_tokenId) returns(uint256)
{
TokenLookup storage lookupData = tokenLookup[_tokenId];
require(lookupData.owner != address(0), "PixelCon does not exist");
return pixelcons[tokenLookup[_tokenId].tokenIndex].collectionIndex;
}
/**
* @notice Get the total number of PixelCons in collection #`(_collectionIndex)`
* @dev Throws if the collection does not exist
* @param _collectionIndex Collection index to query the total of
* @return Total number of PixelCons in the collection
*/
function collectionTotal(uint64 _collectionIndex) public view validIndex(_collectionIndex) returns(uint256)
{
require(_collectionIndex < totalCollections(), "Collection does not exist");
return collectionTokens[_collectionIndex].length;
}
/**
* @notice Get the name of collection #`(_collectionIndex)`
* @dev Throws if the collection does not exist
* @param _collectionIndex Collection index to query the name of
* @return Collection name
*/
function getCollectionName(uint64 _collectionIndex) public view validIndex(_collectionIndex) returns(bytes8)
{
require(_collectionIndex < totalCollections(), "Collection does not exist");
return collectionNames[_collectionIndex];
}
/**
* @notice Enumerate PixelCon in collection #`(_collectionIndex)`
* @dev Throws if the collection does not exist or index is out of bounds
* @param _collectionIndex Collection index
* @param _index Counter less than `collectionTotal(_collection)`
* @return PixelCon ID for the `(_index)`th PixelCon in collection #`(_collectionIndex)`
*/
function tokenOfCollectionByIndex(uint64 _collectionIndex, uint256 _index) public view validIndex(_collectionIndex) returns(uint256)
{
require(_collectionIndex < totalCollections(), "Collection does not exist");
require(_index < collectionTokens[_collectionIndex].length, "Index is out of bounds");
PixelCon storage pixelcon = pixelcons[collectionTokens[_collectionIndex][_index]];
return pixelcon.tokenId;
}
////////////////// Web3 Only //////////////////
/**
* @notice Get the indexes of all PixelCons owned by `(_owner)`
* @dev This function is for web3 calls only, as it returns a dynamic array
* @param _owner Owner address
* @return PixelCon indexes
*/
function getForOwner(address _owner) public view validAddress(_owner) returns(uint64[])
{
return ownedTokens[_owner];
}
/**
* @notice Get the indexes of all PixelCons created by `(_creator)`
* @dev This function is for web3 calls only, as it returns a dynamic array
* @param _creator Creator address
* @return PixelCon indexes
*/
function getForCreator(address _creator) public view validAddress(_creator) returns(uint64[])
{
return createdTokens[_creator];
}
/**
* @notice Get the indexes of all PixelCons in collection #`(_collectionIndex)`
* @dev This function is for web3 calls only, as it returns a dynamic array
* @param _collectionIndex Collection index
* @return PixelCon indexes
*/
function getForCollection(uint64 _collectionIndex) public view validIndex(_collectionIndex) returns(uint64[])
{
return collectionTokens[_collectionIndex];
}
/**
* @notice Get the basic data for the given PixelCon indexes
* @dev This function is for web3 calls only, as it returns a dynamic array
* @param _tokenIndexes List of PixelCon indexes
* @return All PixelCon basic data
*/
function getBasicData(uint64[] _tokenIndexes) public view returns(uint256[], bytes8[], address[], uint64[])
{
uint256[] memory tokenIds = new uint256[](_tokenIndexes.length);
bytes8[] memory names = new bytes8[](_tokenIndexes.length);
address[] memory owners = new address[](_tokenIndexes.length);
uint64[] memory collectionIdxs = new uint64[](_tokenIndexes.length);
for (uint i = 0; i < _tokenIndexes.length; i++) {
uint64 tokenIndex = _tokenIndexes[i];
require(tokenIndex < totalSupply(), "PixelCon index is out of bounds");
tokenIds[i] = pixelcons[tokenIndex].tokenId;
names[i] = pixelconNames[tokenIndex];
owners[i] = tokenLookup[pixelcons[tokenIndex].tokenId].owner;
collectionIdxs[i] = pixelcons[tokenIndex].collectionIndex;
}
return (tokenIds, names, owners, collectionIdxs);
}
/**
* @notice Get the names of all PixelCons
* @dev This function is for web3 calls only, as it returns a dynamic array
* @return The names of all PixelCons in existence
*/
function getAllNames() public view returns(bytes8[])
{
return pixelconNames;
}
/**
* @notice Get the names of all PixelCons from index `(_startIndex)` to `(_endIndex)`
* @dev This function is for web3 calls only, as it returns a dynamic array
* @return The names of the PixelCons in the given range
*/
function getNamesInRange(uint64 _startIndex, uint64 _endIndex) public view returns(bytes8[])
{
require(_startIndex <= totalSupply(), "Start index is out of bounds");
require(_endIndex <= totalSupply(), "End index is out of bounds");
require(_startIndex <= _endIndex, "End index is less than the start index");
uint64 length = _endIndex - _startIndex;
bytes8[] memory names = new bytes8[](length);
for (uint i = 0; i < length; i++) {
names[i] = pixelconNames[_startIndex + i];
}
return names;
}
/**
* @notice Get details of collection #`(_collectionIndex)`
* @dev This function is for web3 calls only, as it returns a dynamic array
* @param _collectionIndex Index of the collection to get the data of
* @return Collection name and included PixelCon indexes
*/
function getCollectionData(uint64 _collectionIndex) public view validIndex(_collectionIndex) returns(bytes8, uint64[])
{
require(_collectionIndex < totalCollections(), "Collection does not exist");
return (collectionNames[_collectionIndex], collectionTokens[_collectionIndex]);
}
/**
* @notice Get the names of all collections
* @dev This function is for web3 calls only, as it returns a dynamic array
* @return The names of all PixelCon collections in existence
*/
function getAllCollectionNames() public view returns(bytes8[])
{
return collectionNames;
}
/**
* @notice Get the names of all collections from index `(_startIndex)` to `(_endIndex)`
* @dev This function is for web3 calls only, as it returns a dynamic array
* @return The names of the collections in the given range
*/
function getCollectionNamesInRange(uint64 _startIndex, uint64 _endIndex) public view returns(bytes8[])
{
require(_startIndex <= totalCollections(), "Start index is out of bounds");
require(_endIndex <= totalCollections(), "End index is out of bounds");
require(_startIndex <= _endIndex, "End index is less than the start index");
uint64 length = _endIndex - _startIndex;
bytes8[] memory names = new bytes8[](length);
for (uint i = 0; i < length; i++) {
names[i] = collectionNames[_startIndex + i];
}
return names;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// ERC-721 Implementation ///////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Get the balance of `(_owner)`
* @param _owner Owner address
* @return Owner balance
*/
function balanceOf(address _owner) public view validAddress(_owner) returns(uint256)
{
return ownedTokens[_owner].length;
}
/**
* @notice Get the owner of PixelCon `(_tokenId)`
* @dev Throws if PixelCon does not exist
* @param _tokenId ID of the token
* @return Owner of the given PixelCon
*/
function ownerOf(uint256 _tokenId) public view validId(_tokenId) returns(address)
{
address owner = tokenLookup[_tokenId].owner;
require(owner != address(0), "PixelCon does not exist");
return owner;
}
/**
* @notice Approve `(_to)` to transfer PixelCon `(_tokenId)` (zero indicates no approved address)
* @dev Throws if not called by the owner or an approved operator
* @param _to Address to be approved
* @param _tokenId ID of the token to be approved
*/
function approve(address _to, uint256 _tokenId) public validId(_tokenId)
{
address owner = tokenLookup[_tokenId].owner;
require(_to != owner, "Cannot approve PixelCon owner");
require(msg.sender == owner || operatorApprovals[owner][msg.sender], "Sender does not have permission to approve address");
tokenApprovals[_tokenId] = _to;
emit Approval(owner, _to, _tokenId);
}
/**
* @notice Get the approved address for PixelCon `(_tokenId)`
* @dev Throws if the PixelCon does not exist
* @param _tokenId ID of the token
* @return Address currently approved for the given PixelCon
*/
function getApproved(uint256 _tokenId) public view validId(_tokenId) returns(address)
{
address owner = tokenLookup[_tokenId].owner;
require(owner != address(0), "PixelCon does not exist");
return tokenApprovals[_tokenId];
}
/**
* @notice Set or unset the approval of operator `(_to)`
* @dev An operator is allowed to transfer all tokens of the sender on their behalf
* @param _to Operator address to set the approval
* @param _approved Flag for setting approval
*/
function setApprovalForAll(address _to, bool _approved) public validAddress(_to)
{
require(_to != msg.sender, "Cannot approve self");
operatorApprovals[msg.sender][_to] = _approved;
emit ApprovalForAll(msg.sender, _to, _approved);
}
/**
* @notice Get if `(_operator)` is an approved operator for owner `(_owner)`
* @param _owner Owner address
* @param _operator Operator address
* @return True if the given operator is approved by the given owner
*/
function isApprovedForAll(address _owner, address _operator) public view validAddress(_owner) validAddress(_operator) returns(bool)
{
return operatorApprovals[_owner][_operator];
}
/**
* @notice Transfer the ownership of PixelCon `(_tokenId)` to `(_to)` (try to use 'safeTransferFrom' instead)
* @dev Throws if the sender is not the owner, approved, or operator
* @param _from Current owner
* @param _to Address to receive the PixelCon
* @param _tokenId ID of the PixelCon to be transferred
*/
function transferFrom(address _from, address _to, uint256 _tokenId) public validAddress(_from) validAddress(_to) validId(_tokenId)
{
require(isApprovedOrOwner(msg.sender, _tokenId), "Sender does not have permission to transfer PixelCon");
clearApproval(_from, _tokenId);
removeTokenFrom(_from, _tokenId);
addTokenTo(_to, _tokenId);
emit Transfer(_from, _to, _tokenId);
}
/**
* @notice Safely transfer the ownership of PixelCon `(_tokenId)` to `(_to)`
* @dev Throws if receiver is a contract that does not respond or the sender is not the owner, approved, or operator
* @param _from Current owner
* @param _to Address to receive the PixelCon
* @param _tokenId ID of the PixelCon to be transferred
*/
function safeTransferFrom(address _from, address _to, uint256 _tokenId) public
{
//requirements are checked in 'transferFrom' function
safeTransferFrom(_from, _to, _tokenId, "");
}
/**
* @notice Safely transfer the ownership of PixelCon `(_tokenId)` to `(_to)`
* @dev Throws if receiver is a contract that does not respond or the sender is not the owner, approved, or operator
* @param _from Current owner
* @param _to Address to receive the PixelCon
* @param _tokenId ID of the PixelCon to be transferred
* @param _data Data to send along with a safe transfer check
*/
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data) public
{
//requirements are checked in 'transferFrom' function
transferFrom(_from, _to, _tokenId);
require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data), "Transfer was not safe");
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////// ERC-721 Enumeration Implementation /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Get the total number of PixelCons in existence
* @return Total number of PixelCons in existence
*/
function totalSupply() public view returns(uint256)
{
return pixelcons.length;
}
/**
* @notice Get the ID of PixelCon #`(_tokenIndex)`
* @dev Throws if index is out of bounds
* @param _tokenIndex Counter less than `totalSupply()`
* @return `_tokenIndex`th PixelCon ID
*/
function tokenByIndex(uint256 _tokenIndex) public view returns(uint256)
{
require(_tokenIndex < totalSupply(), "PixelCon index is out of bounds");
return pixelcons[_tokenIndex].tokenId;
}
/**
* @notice Enumerate PixelCon assigned to owner `(_owner)`
* @dev Throws if the index is out of bounds
* @param _owner Owner address
* @param _index Counter less than `balanceOf(_owner)`
* @return PixelCon ID for the `(_index)`th PixelCon in owned by `(_owner)`
*/
function tokenOfOwnerByIndex(address _owner, uint256 _index) public view validAddress(_owner) returns(uint256)
{
require(_index < ownedTokens[_owner].length, "Index is out of bounds");
PixelCon storage pixelcon = pixelcons[ownedTokens[_owner][_index]];
return pixelcon.tokenId;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////// ERC-721 Metadata Implementation //////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Get the name of this contract token
* @return Contract token name
*/
function name() public view returns(string)
{
return "PixelCons";
}
/**
* @notice Get the symbol for this contract token
* @return Contract token symbol
*/
function symbol() public view returns(string)
{
return "PXCN";
}
/**
* @notice Get a distinct Uniform Resource Identifier (URI) for PixelCon `(_tokenId)`
* @dev Throws if the given PixelCon does not exist
* @return PixelCon URI
*/
function tokenURI(uint256 _tokenId) public view returns(string)
{
TokenLookup storage lookupData = tokenLookup[_tokenId];
require(lookupData.owner != address(0), "PixelCon does not exist");
PixelCon storage pixelcon = pixelcons[lookupData.tokenIndex];
bytes8 pixelconName = pixelconNames[lookupData.tokenIndex];
//Available values: <tokenId>, <tokenIndex>, <name>, <owner>, <creator>, <dateCreated>, <collectionIndex>
//start with the token URI template and replace in the appropriate values
string memory finalTokenURI = tokenURITemplate;
finalTokenURI = StringUtils.replace(finalTokenURI, "<tokenId>", StringUtils.toHexString(_tokenId, 32));
finalTokenURI = StringUtils.replace(finalTokenURI, "<tokenIndex>", StringUtils.toHexString(uint256(lookupData.tokenIndex), 8));
finalTokenURI = StringUtils.replace(finalTokenURI, "<name>", StringUtils.toHexString(uint256(pixelconName), 8));
finalTokenURI = StringUtils.replace(finalTokenURI, "<owner>", StringUtils.toHexString(uint256(lookupData.owner), 20));
finalTokenURI = StringUtils.replace(finalTokenURI, "<creator>", StringUtils.toHexString(uint256(pixelcon.creator), 20));
finalTokenURI = StringUtils.replace(finalTokenURI, "<dateCreated>", StringUtils.toHexString(uint256(pixelcon.dateCreated), 8));
finalTokenURI = StringUtils.replace(finalTokenURI, "<collectionIndex>", StringUtils.toHexString(uint256(pixelcon.collectionIndex), 8));
return finalTokenURI;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////// Utils ////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* @notice Check whether the given editor is the current owner and original creator of a given token ID
* @param _address Address to check for
* @param _tokenId ID of the token to be edited
* @return True if the editor is approved for the given token ID, is an operator of the owner, or is the owner of the token
*/
function isCreatorAndOwner(address _address, uint256 _tokenId) internal view returns(bool)
{
TokenLookup storage lookupData = tokenLookup[_tokenId];
address owner = lookupData.owner;
address creator = pixelcons[lookupData.tokenIndex].creator;
return (_address == owner && _address == creator);
}
/**
* @notice Check whether the given spender can transfer a given token ID
* @dev Throws if the PixelCon does not exist
* @param _address Address of the spender to query
* @param _tokenId ID of the token to be transferred
* @return True if the spender is approved for the given token ID, is an operator of the owner, or is the owner of the token
*/
function isApprovedOrOwner(address _address, uint256 _tokenId) internal view returns(bool)
{
address owner = tokenLookup[_tokenId].owner;
require(owner != address(0), "PixelCon does not exist");
return (_address == owner || tokenApprovals[_tokenId] == _address || operatorApprovals[owner][_address]);
}
/**
* @notice Clear current approval of a given token ID
* @dev Throws if the given address is not indeed the owner of the token
* @param _owner Owner of the token
* @param _tokenId ID of the token to be transferred
*/
function clearApproval(address _owner, uint256 _tokenId) internal
{
require(tokenLookup[_tokenId].owner == _owner, "Incorrect PixelCon owner");
if (tokenApprovals[_tokenId] != address(0)) {
tokenApprovals[_tokenId] = address(0);
}
}
/**
* @notice Add a token ID to the list of a given address
* @dev Throws if the receiver address has hit ownership limit or the PixelCon already has an owner
* @param _to Address representing the new owner of the given token ID
* @param _tokenId ID of the token to be added to the tokens list of the given address
*/
function addTokenTo(address _to, uint256 _tokenId) internal
{
uint64[] storage ownedList = ownedTokens[_to];
TokenLookup storage lookupData = tokenLookup[_tokenId];
require(ownedList.length < uint256(2 ** 32) - 1, "Max number of PixelCons per owner has been reached");
require(lookupData.owner == address(0), "PixelCon already has an owner");
lookupData.owner = _to;
//update ownedTokens references
uint ownedListIndex = ownedList.length;
ownedList.length++;
lookupData.ownedIndex = uint32(ownedListIndex);
ownedList[ownedListIndex] = lookupData.tokenIndex;
}
/**
* @notice Remove a token ID from the list of a given address
* @dev Throws if the given address is not indeed the owner of the token
* @param _from Address representing the previous owner of the given token ID
* @param _tokenId ID of the token to be removed from the tokens list of the given address
*/
function removeTokenFrom(address _from, uint256 _tokenId) internal
{
uint64[] storage ownedList = ownedTokens[_from];
TokenLookup storage lookupData = tokenLookup[_tokenId];
require(lookupData.owner == _from, "From address is incorrect");
lookupData.owner = address(0);
//update ownedTokens references
uint64 replacementTokenIndex = ownedList[ownedList.length - 1];
delete ownedList[ownedList.length - 1];
ownedList.length--;
if (lookupData.ownedIndex < ownedList.length) {
//we just removed the last token index in the array, but if this wasn't the one to remove, then swap it with the one to remove
ownedList[lookupData.ownedIndex] = replacementTokenIndex;
tokenLookup[pixelcons[replacementTokenIndex].tokenId].ownedIndex = lookupData.ownedIndex;
}
lookupData.ownedIndex = 0;
}
/**
* @notice Invoke `onERC721Received` on a target address (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 ID of the token to be transferred
* @param _data Optional data to send along with the call
* @return True if the call correctly returned the expected value
*/
function checkAndCallSafeTransfer(address _from, address _to, uint256 _tokenId, bytes _data) internal returns(bool)
{
if (!_to.isContract()) return true;
bytes4 retval = ERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
return (retval == ERC721_RECEIVED);
}
}
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.
* See (https://github.com/OpenZeppelin/openzeppelin-solidity)
*/
contract ERC721Receiver {
/**
* @dev Magic value to be returned upon successful reception of an NFT.
* Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`,
* which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
*/
bytes4 internal constant ERC721_RECEIVED = 0x150b7a02;
/**
* @notice Handle the receipt of an NFT
* @dev The ERC721 smart contract calls this function on the recipient
* after a `safetransfer`. This function MAY throw to revert and reject the
* transfer. Return of other than the magic value MUST result in the
* transaction being reverted.
* Note: the 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);
}
/**
* @title AddressUtils Library
* @dev Utility library of inline functions on addresses.
* See (https://github.com/OpenZeppelin/openzeppelin-solidity)
*/
library AddressUtils {
/**
* 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.
assembly { size := extcodesize(_account) }
return size > 0;
}
}
/**
* @title StringUtils Library
* @dev Utility library of inline functions on strings.
* These functions are very expensive and are only intended for web3 calls
* @author PixelCons
*/
library StringUtils {
/**
* @dev Replaces the given key with the given value in the given string
* @param _str String to find and replace in
* @param _key Value to search for
* @param _value Value to replace key with
* @return The replaced string
*/
function replace(string _str, string _key, string _value) internal pure returns(string)
{
bytes memory bStr = bytes(_str);
bytes memory bKey = bytes(_key);
bytes memory bValue = bytes(_value);
uint index = indexOf(bStr, bKey);
if (index < bStr.length) {
bytes memory rStr = new bytes((bStr.length + bValue.length) - bKey.length);
uint i;
for (i = 0; i < index; i++) rStr[i] = bStr[i];
for (i = 0; i < bValue.length; i++) rStr[index + i] = bValue[i];
for (i = 0; i < bStr.length - (index + bKey.length); i++) rStr[index + bValue.length + i] = bStr[index + bKey.length + i];
return string(rStr);
}
return string(bStr);
}
/**
* @dev Converts a given number into a string with hex representation
* @param _num Number to convert
* @param _byteSize Size of the number in bytes
* @return The hex representation as string
*/
function toHexString(uint256 _num, uint _byteSize) internal pure returns(string)
{
bytes memory s = new bytes(_byteSize * 2 + 2);
s[0] = 0x30;
s[1] = 0x78;
for (uint i = 0; i < _byteSize; i++) {
byte b = byte(uint8(_num / (2 ** (8 * (_byteSize - 1 - i)))));
byte hi = byte(uint8(b) / 16);
byte lo = byte(uint8(b) - 16 * uint8(hi));
s[2 + 2 * i] = char(hi);
s[3 + 2 * i] = char(lo);
}
return string(s);
}
/**
* @dev Gets the ascii hex character for the given value (0-15)
* @param _b Byte to get ascii code for
* @return The ascii hex character
*/
function char(byte _b) internal pure returns(byte c)
{
if (_b < 10) return byte(uint8(_b) + 0x30);
else return byte(uint8(_b) + 0x57);
}
/**
* @dev Gets the index of the key string in the given string
* @param _str String to search in
* @param _key Value to search for
* @return The index of the key in the string (string length if not found)
*/
function indexOf(bytes _str, bytes _key) internal pure returns(uint)
{
for (uint i = 0; i < _str.length - (_key.length - 1); i++) {
bool matchFound = true;
for (uint j = 0; j < _key.length; j++) {
if (_str[i + j] != _key[j]) {
matchFound = false;
break;
}
}
if (matchFound) {
return i;
}
}
return _str.length;
}
}
Read Contract
InterfaceId_ERC165 0x19fa8f50 → bytes4
balanceOf 0x70a08231 → uint256
collectionCleared 0x8a153c28 → bool
collectionExists 0xd694f109 → bool
collectionOf 0xc7778baa → uint256
collectionTotal 0x26a50862 → uint256
creatorOf 0x589a1743 → address
creatorTotal 0x08702682 → uint256
exists 0x4f558e79 → bool
getAdmin 0x6e9960c3 → address
getAllCollectionNames 0xace8116d → bytes8[]
getAllNames 0xfb825e5f → bytes8[]
getApproved 0x081812fc → address
getBasicData 0xe2b31903 → uint256[], bytes8[], address[], uint64[]
getCollectionData 0x6bb2a9a8 → bytes8, uint64[]
getCollectionName 0xe8545f1b → bytes8
getCollectionNamesInRange 0x602c4f05 → bytes8[]
getForCollection 0xad732154 → uint64[]
getForCreator 0xd4aa25cc → uint64[]
getForOwner 0x57643118 → uint64[]
getNamesInRange 0x58350681 → bytes8[]
getTokenData 0xb09afec1 → uint256, uint64, uint64, address, address, bytes8, uint32
getTokenDataByIndex 0x062401c2 → uint256, uint64, uint64, address, address, bytes8, uint32
getTokenIndex 0x3a663c80 → uint64
isApprovedForAll 0xe985e9c5 → bool
name 0x06fdde03 → string
ownerOf 0x6352211e → address
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenByIndex 0x4f6ccce7 → uint256
tokenOfCollectionByIndex 0x4aeabcb6 → uint256
tokenOfCreatorByIndex 0x4fc09275 → uint256
tokenOfOwnerByIndex 0x2f745c59 → uint256
tokenURI 0xc87b56dd → string
totalCollections 0x61d9db2d → uint256
totalSupply 0x18160ddd → uint256
Write Contract 13 functions
These functions modify contract state and require a wallet transaction to execute.
adminChange 0x9e5f4dbd
address _newAdmin
adminSetTokenURITemplate 0xb2f42210
string _newTokenURITemplate
adminWithdraw 0xa28835b6
address _to
approve 0x095ea7b3
address _to
uint256 _tokenId
clearCollection 0xa05d821b
uint64 _collectionIndex
returns: uint64
create 0x9fee49ba
address _to
uint256 _tokenId
bytes8 _name
returns: uint64
createCollection 0xc82a94a1
uint64[] _tokenIndexes
bytes8 _name
returns: uint64
rename 0x75d28011
uint256 _tokenId
bytes8 _name
returns: uint64
renameCollection 0x50ff9a5b
uint64 _collectionIndex
bytes8 _name
returns: uint64
safeTransferFrom 0x42842e0e
address _from
address _to
uint256 _tokenId
safeTransferFrom 0xb88d4fde
address _from
address _to
uint256 _tokenId
bytes _data
setApprovalForAll 0xa22cb465
address _to
bool _approved
transferFrom 0x23b872dd
address _from
address _to
uint256 _tokenId
Recent Transactions
No transactions found for this address