Diff
checker
Text
Text
Bilder
Dokumente
Excel
Ordner
Legal
Enterprise
Desktop-App
Preise
Einloggen
Diffchecker Desktop herunterladen
Texte vergleichen
Finde den Unterschied zwischen zwei Textdateien
Werkzeuge
Verlauf
Live-Editor
Leerzeichen ausblenden
Gleiches ausblenden
Zeilenumbruch aus
Ansicht
Zweispaltig
Einspaltig
Vergleichsgenauigkeit
Intelligent
Wort
Zeichen
Textstile
Darstellung ändern
Syntaxhervorhebung
Syntax auswählen
Ignorieren
Text umwandeln
Zur ersten Änderung
Eingabe bearbeiten
Diffchecker Desktop
Der sicherste Weg, Diffchecker zu nutzen. Hol dir die Desktop-App: Deine Diffs verlassen nie deinen Computer!
Desktop holen
CryptoPunks v1 vs CryptoPhunks
Erstellt
vor 4 Jahren
Diff läuft nie ab
Löschen
Exportieren
Teilen
Erklären
125 Entfernungen
Zeilen
Gesamt
Entfernt
Zeichen
Gesamt
Entfernt
Um diese Funktion weiterhin zu nutzen, aktualisiere auf
Diff
checker
Pro
Preise anzeigen
140 Zeilen
Kopieren
288 Hinzufügungen
Zeilen
Gesamt
Hinzugefügt
Zeichen
Gesamt
Hinzugefügt
Um diese Funktion weiterhin zu nutzen, aktualisiere auf
Diff
checker
Pro
Preise anzeigen
314 Zeilen
Kopieren
Kopieren
Kopiert
Kopieren
Kopiert
/**
// SPDX-License-Identifier: UNLICENSE
*Submitted for verification at Etherscan.io on 2017-06-17
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
contract CryptoPhunksV2 is Ownable, ERC721Enumerable, ReentrancyGuard {
using Counters for Counters.Counter;
using Strings for uint256;
// You can use this hash to verify the image file containing all the phunks
string public constant imageHash =
"122dab9670c21ad538dafdbb87191c4d7114c389af616c42c54556aa2211b899";
constructor() ERC721("CryptoPhunksV2", "PHUNK") {}
bool public isSaleOn = false;
bool public saleHasBeenStarted = false;
uint256 public constant MAX_MINTABLE_AT_ONCE = 50;
uint256[10000] private _availableTokens;
uint256 private _numAvailableTokens = 10000;
uint256 private _numFreeRollsGiven = 0;
mapping(address => uint256) public freeRollPhunks;
uint256 private _lastTokenIdMintedInInitialSet = 10000;
function numTotalPhunks() public view virtual returns (uint256) {
return 10000;
}
function freeRollMint() public nonReentrant() {
uint256 toMint = freeRollPhunks[msg.sender];
freeRollPhunks[msg.sender] = 0;
uint256 remaining = numTotalPhunks() - totalSupply();
if (toMint > remaining) {
toMint = remaining;
}
_mint(toMint);
}
function getNumFreeRollPhunks(address owner) public view returns (uint256) {
return freeRollPhunks[owner];
}
function mint(uint256 _numToMint) public payable nonReentrant() {
require(isSaleOn, "Sale hasn't started.");
uint256 totalSupply = totalSupply();
require(
totalSupply + _numToMint <= numTotalPhunks(),
"There aren't this many phunks left."
);
uint256 costForMintingPhunks = getCostForMintingPhunks(_numToMint);
require(
msg.value >= costForMintingPhunks,
"Too little sent, please send more eth."
);
if (msg.value > costForMintingPhunks) {
payable(msg.sender).transfer(msg.value - costForMintingPhunks);
}
_mint(_numToMint);
}
// internal minting function
function _mint(uint256 _numToMint) internal {
require(_numToMint <= MAX_MINTABLE_AT_ONCE, "Minting too many at once.");
uint256 updatedNumAvailableTokens = _numAvailableTokens;
for (uint256 i = 0; i < _numToMint; i++) {
uint256 newTokenId = useRandomAvailableToken(_numToMint, i);
_safeMint(msg.sender, newTokenId);
updatedNumAvailableTokens--;
}
_numAvailableTokens = updatedNumAvailableTokens;
}
function useRandomAvailableToken(uint256 _numToFetch, uint256 _i)
internal
returns (uint256)
{
uint256 randomNum =
uint256(
keccak256(
abi.encode(
msg.sender,
tx.gasprice,
block.number,
block.timestamp,
blockhash(block.number - 1),
_numToFetch,
_i
)
)
);
uint256 randomIndex = randomNum % _numAvailableTokens;
return useAvailableTokenAtIndex(randomIndex);
}
function useAvailableTokenAtIndex(uint256 indexToUse)
internal
returns (uint256)
{
uint256 valAtIndex = _availableTokens[indexToUse];
uint256 result;
if (valAtIndex == 0) {
// This means the index itself is still an available token
result = indexToUse;
} else {
// This means the index itself is not an available token, but the val at that index is.
result = valAtIndex;
}
uint256 lastIndex = _numAvailableTokens - 1;
if (indexToUse != lastIndex) {
// Replace the value at indexToUse, now that it's been used.
// Replace it with the data from the last index in the array, since we are going to decrease the array size afterwards.
uint256 lastValInArray = _availableTokens[lastIndex];
if (lastValInArray == 0) {
// This means the index itself is still an available token
_availableTokens[indexToUse] = lastIndex;
} else {
// This means the index itself is not an available token, but the val at that index is.
_availableTokens[indexToUse] = lastValInArray;
}
}
_numAvailableTokens--;
return result;
}
function getCostForMintingPhunks(uint256 _numToMint)
public
view
returns (uint256)
{
require(
totalSupply() + _numToMint <= numTotalPhunks(),
"There aren't this many phunks left."
);
if (_numToMint == 1) {
return 0.02 ether;
} else if (_numToMint == 3) {
return 0.05 ether;
} else if (_numToMint == 5) {
return 0.07 ether;
} else if (_numToMint == 10) {
return 0.10 ether;
} else {
revert("Unsupported mint amount");
}
}
function getPhunksBelongingToOwner(address _owner)
external
view
returns (uint256[] memory)
{
uint256 numPhunks = balanceOf(_owner);
if (numPhunks == 0) {
return new uint256[](0);
} else {
uint256[] memory result = new uint256[](numPhunks);
for (uint256 i = 0; i < numPhunks; i++) {
result[i] = tokenOfOwnerByIndex(_owner, i);
}
return result;
}
}
/*
* Dev stuff.
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
pragma solidity ^0.4.8;
// metadata URI
contract CryptoPunks {
string private _baseTokenURI;
// You can use this hash to verify the image file containing all the punks
string public imageHash = "ac39af4793119ee46bbff351d8cb6b5f23da60222126add4268e261199a2921b";
address owner;
string public standard = 'CryptoPunks';
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
uint public nextPunkIndexToAssign = 0;
//bool public allPunksAssigned = false;
uint public punksRemainingToAssign = 0;
uint public numberOfPunksToReserve;
uint public numberOfPunksReserved = 0;
//mapping (address => uint) public addressToPunkIndex;
mapping (uint => address) public punkIndexToAddress;
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
Kopieren
Kopiert
Kopieren
Kopiert
struct Offer {
function _baseURI() internal view virtual override returns (string memory) {
bool isForSale;
return _baseTokenURI;
uint punkIndex;
address seller;
uint minValue; // in ether
address onlySellTo; // specify to sell only to a specific person
}
}
Kopieren
Kopiert
Kopieren
Kopiert
// A record of punks that are offered for sale at a specific minimum value, and perhaps to a specific person
function tokenURI(uint256 _tokenId)
mapping (uint => Offer) public punksOfferedForSale;
public
view
mapping (address => uint)
public
pendingWithdrawals;
override
returns (string memory)
event Assign(address indexed to, uint256 punkIndex);
{
event Transfer(address indexed from, address indexed to, uint256 value);
string memory base = _baseURI();
event PunkTransfer(address indexed from, address indexed to, uint256 punkIndex);
string memory _tokenURI = Strings.toString(_tokenId);
event PunkOffered(uint indexed punkIndex, uint minValue, address indexed toAddress);
event PunkBought(uint indexed punkIndex, uint value, address indexed fromAddress, address indexed toAddress);
event PunkNoLongerForSale(uint indexed punkIndex);
Kopieren
Kopiert
Kopieren
Kopiert
/* Initializes contract with initial supply tokens to the creator of the contract */
// If there is no base URI, return the token URI.
function CryptoPunks() payable {
if (bytes(base).length == 0) {
// balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
return _tokenURI;
owner = msg.sender;
totalSupply = 10000; // Update total supply
punksRemainingToAssign = totalSupply;
numberOfPunksToReserve = 1000;
name = "CRYPTOPUNKS"; // Set the name for display purposes
symbol = "Ͼ"; // Set the symbol for display purposes
decimals = 0; // Amount of decimals for display purposes
}
}
Kopieren
Kopiert
Kopieren
Kopiert
function reservePunksForOwner(uint maxForThisRun) {
return string(abi.encodePacked(base, _tokenURI));
if (msg.sender != owner) throw;
if (numberOfPunksReserved >= numberOfPunksToReserve) throw;
uint numberPunksReservedThisRun = 0;
while (numberOfPunksReserved < numberOfPunksToReserve && numberPunksReservedThisRun < maxForThisRun) {
punkIndexToAddress[nextPunkIndexToAssign] = msg.sender;
Assign(msg.sender, nextPunkIndexToAssign);
numberPunksReservedThisRun++;
nextPunkIndexToAssign++;
}
}
punksRemainingToAssign -= numberPunksReservedThisRun;
numberOfPunksReserved += numberPunksReservedThisRun;
// contract metadata URI for opensea
balanceOf[msg.sender] += numberPunksReservedThisRun;
string public contractURI;
/*
* Owner stuff
*/
function startSale() public onlyOwner {
isSaleOn = true;
saleHasBeenStarted = true;
}
}
Kopieren
Kopiert
Kopieren
Kopiert
function
getPunk(uint punkIndex)
{
function
endSale() public onlyOwner
{
if (punksRemainingToAssign == 0) throw;
isSaleOn = false;
if (punkIndexToAddress[punkIndex] != 0x0) throw;
punkIndexToAddress[punkIndex] = msg.sender;
balanceOf[msg.sender]++;
punksRemainingToAssign--;
Assign(msg.sender, punkIndex);
}
}
Kopieren
Kopiert
Kopieren
Kopiert
// Transfer ownership of a punk to another user without requiring payment
function giveFreeRoll(address receiver) public onlyOwner {
function transferPunk(address to, uint punkIndex) {
// max number of free mints we can give to the community for promotions/marketing
if (punkIndexToAddress[punkIndex] != msg.sender) throw;
require(_numFreeRollsGiven < 200, "already given max number of free rolls");
punkIndexToAddress[punkIndex] = to;
uint256 freeRolls = freeRollPhunks[receiver];
balanceOf[msg.sender]--;
freeRollPhunks[receiver] = freeRolls + 1;
balanceOf[to]++;
_numFreeRollsGiven = _numFreeRollsGiven + 1;
Transfer(msg.sender, to, 1);
PunkTransfer(msg.sender, to, punkIndex);
}
}
Kopieren
Kopiert
Kopieren
Kopiert
function punkNoLongerForSale(uint punkIndex) {
// for handing out free rolls to v1 phunk owners
if (punkIndexToAddress[punkIndex] != msg.sender) throw;
// details on seeding info here: https://gist.github.com/cryptophunks/7f542feaee510e12464da3bb2a922713
punksOfferedForSale[punkIndex] = Offer(false, punkIndex, msg.sender, 0, 0x0);
function seedFreeRolls(
PunkNoLongerForSale(punkIndex);
address[] memory tokenOwners,
uint256[] memory numOfFreeRolls
) public onlyOwner {
require(
!saleHasBeenStarted,
"cannot seed free rolls after sale has started"
);
require(
tokenOwners.length == numOfFreeRolls.length,
"tokenOwners does not match numOfFreeRolls length"
);
// light check to make sure the proper values are being passed
require(numOfFreeRolls[0] <= 3, "cannot give more than 3 free rolls");
for (uint256 i = 0; i < tokenOwners.length; i++) {
freeRollPhunks[tokenOwners[i]] = numOfFreeRolls[i];
}
}
Kopieren
Kopiert
Kopieren
Kopiert
function offerPunkForSale(uint punkIndex, uint minSalePriceInWei) {
if (punkIndexToAddress[punkIndex] != msg.sender) throw;
punksOfferedForSale[punkIndex] = Offer(true, punkIndex, msg.sender, minSalePriceInWei, 0x0);
PunkOffered(punkIndex, minSalePriceInWei, 0x0);
Kopieren
Kopiert
Kopieren
Kopiert
}
}
Kopieren
Kopiert
Kopieren
Kopiert
function offerPunkForSaleToAddress(uint punkIndex, uint minSalePriceInWei, address toAddress) {
// for seeding the v2 contract with v1 state
if (punkIndexToAddress[punkIndex] != msg.sender) throw;
// details on seeding info here: https://gist.github.com/cryptophunks/7f542feaee510e12464da3bb2a922713
punksOfferedForSale[punkIndex] = Offer(true, punkIndex, msg.sender, minSalePriceInWei, toAddress);
function seedInitialContractState(
PunkOffered(punkIndex, minSalePriceInWei, toAddress);
address[] memory tokenOwners,
uint256[] memory tokens
) public onlyOwner {
require(
!saleHasBeenStarted,
"cannot initial phunk mint if sale has started"
);
require(
tokenOwners.length == tokens.length,
"tokenOwners does not match tokens length"
);
uint256 lastTokenIdMintedInInitialSetCopy = _lastTokenIdMintedInInitialSet;
for (uint256 i = 0; i < tokenOwners.length; i++) {
uint256 token = tokens[i];
require(
lastTokenIdMintedInInitialSetCopy > token,
"initial phunk mints must be in decreasing order for our availableToken index to work"
);
lastTokenIdMintedInInitialSetCopy = token;
useAvailableTokenAtIndex(token);
_safeMint(tokenOwners[i], token);
}
}
Kopieren
Kopiert
Kopieren
Kopiert
_lastTokenIdMintedInInitialSet = lastTokenIdMintedInInitialSetCopy;
}
Kopieren
Kopiert
Kopieren
Kopiert
function buyPunk(uint punkIndex) payable {
// URIs
Offer offer = punksOfferedForSale[punkIndex];
function setBaseURI(string memory baseURI) external onlyOwner {
if (!offer.isForSale) throw; // punk not actually for sale
_baseTokenURI = baseURI;
if (offer.onlySellTo != 0x0 && offer.onlySellTo != msg.sender) throw; // punk not supposed to be sold to this user
}
if (msg.value < offer.minValue) throw; // Didn't send enough ETH
if (offer.seller != punkIndexToAddress[punkIndex]) throw; // Seller no longer owner of punk
Kopieren
Kopiert
Kopieren
Kopiert
punkIndexToAddress[punkIndex] = msg.sender;
function setContractURI(string memory _contractURI) external onlyOwner {
balanceOf[offer.seller]--;
contractURI = _contractURI;
balanceOf[msg.sender]++;
}
Transfer(offer.seller, msg.sender, 1);
Kopieren
Kopiert
Kopieren
Kopiert
punkNoLongerForSale(punkIndex);
function withdrawMoney() public payable onlyOwner {
pendingWithdrawals[offer.seller] += msg.value;
(bool success, ) = msg.sender.call{value: address(this).balance}("");
PunkBought(punkIndex, msg.value, offer.seller, msg.sender);
require(success, "Transfer failed.");
}
}
Kopieren
Kopiert
Kopieren
Kopiert
function withdraw() {
function _beforeTokenTransfer(
uint amount = pendingWithdrawals[msg.sender];
address from,
// Remember to zero the pending refund before
address to,
// sending to prevent re-entrancy attacks
uint256 tokenId
pendingWithdrawals[msg.sender] = 0;
) internal virtual override(ERC721Enumerable) {
msg.sender.transfer(amount);
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
}
}
Gespeicherte Diffs
Originaltext
Datei öffnen
/** *Submitted for verification at Etherscan.io on 2017-06-17 */ pragma solidity ^0.4.8; contract CryptoPunks { // You can use this hash to verify the image file containing all the punks string public imageHash = "ac39af4793119ee46bbff351d8cb6b5f23da60222126add4268e261199a2921b"; address owner; string public standard = 'CryptoPunks'; string public name; string public symbol; uint8 public decimals; uint256 public totalSupply; uint public nextPunkIndexToAssign = 0; //bool public allPunksAssigned = false; uint public punksRemainingToAssign = 0; uint public numberOfPunksToReserve; uint public numberOfPunksReserved = 0; //mapping (address => uint) public addressToPunkIndex; mapping (uint => address) public punkIndexToAddress; /* This creates an array with all balances */ mapping (address => uint256) public balanceOf; struct Offer { bool isForSale; uint punkIndex; address seller; uint minValue; // in ether address onlySellTo; // specify to sell only to a specific person } // A record of punks that are offered for sale at a specific minimum value, and perhaps to a specific person mapping (uint => Offer) public punksOfferedForSale; mapping (address => uint) public pendingWithdrawals; event Assign(address indexed to, uint256 punkIndex); event Transfer(address indexed from, address indexed to, uint256 value); event PunkTransfer(address indexed from, address indexed to, uint256 punkIndex); event PunkOffered(uint indexed punkIndex, uint minValue, address indexed toAddress); event PunkBought(uint indexed punkIndex, uint value, address indexed fromAddress, address indexed toAddress); event PunkNoLongerForSale(uint indexed punkIndex); /* Initializes contract with initial supply tokens to the creator of the contract */ function CryptoPunks() payable { // balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens owner = msg.sender; totalSupply = 10000; // Update total supply punksRemainingToAssign = totalSupply; numberOfPunksToReserve = 1000; name = "CRYPTOPUNKS"; // Set the name for display purposes symbol = "Ͼ"; // Set the symbol for display purposes decimals = 0; // Amount of decimals for display purposes } function reservePunksForOwner(uint maxForThisRun) { if (msg.sender != owner) throw; if (numberOfPunksReserved >= numberOfPunksToReserve) throw; uint numberPunksReservedThisRun = 0; while (numberOfPunksReserved < numberOfPunksToReserve && numberPunksReservedThisRun < maxForThisRun) { punkIndexToAddress[nextPunkIndexToAssign] = msg.sender; Assign(msg.sender, nextPunkIndexToAssign); numberPunksReservedThisRun++; nextPunkIndexToAssign++; } punksRemainingToAssign -= numberPunksReservedThisRun; numberOfPunksReserved += numberPunksReservedThisRun; balanceOf[msg.sender] += numberPunksReservedThisRun; } function getPunk(uint punkIndex) { if (punksRemainingToAssign == 0) throw; if (punkIndexToAddress[punkIndex] != 0x0) throw; punkIndexToAddress[punkIndex] = msg.sender; balanceOf[msg.sender]++; punksRemainingToAssign--; Assign(msg.sender, punkIndex); } // Transfer ownership of a punk to another user without requiring payment function transferPunk(address to, uint punkIndex) { if (punkIndexToAddress[punkIndex] != msg.sender) throw; punkIndexToAddress[punkIndex] = to; balanceOf[msg.sender]--; balanceOf[to]++; Transfer(msg.sender, to, 1); PunkTransfer(msg.sender, to, punkIndex); } function punkNoLongerForSale(uint punkIndex) { if (punkIndexToAddress[punkIndex] != msg.sender) throw; punksOfferedForSale[punkIndex] = Offer(false, punkIndex, msg.sender, 0, 0x0); PunkNoLongerForSale(punkIndex); } function offerPunkForSale(uint punkIndex, uint minSalePriceInWei) { if (punkIndexToAddress[punkIndex] != msg.sender) throw; punksOfferedForSale[punkIndex] = Offer(true, punkIndex, msg.sender, minSalePriceInWei, 0x0); PunkOffered(punkIndex, minSalePriceInWei, 0x0); } function offerPunkForSaleToAddress(uint punkIndex, uint minSalePriceInWei, address toAddress) { if (punkIndexToAddress[punkIndex] != msg.sender) throw; punksOfferedForSale[punkIndex] = Offer(true, punkIndex, msg.sender, minSalePriceInWei, toAddress); PunkOffered(punkIndex, minSalePriceInWei, toAddress); } function buyPunk(uint punkIndex) payable { Offer offer = punksOfferedForSale[punkIndex]; if (!offer.isForSale) throw; // punk not actually for sale if (offer.onlySellTo != 0x0 && offer.onlySellTo != msg.sender) throw; // punk not supposed to be sold to this user if (msg.value < offer.minValue) throw; // Didn't send enough ETH if (offer.seller != punkIndexToAddress[punkIndex]) throw; // Seller no longer owner of punk punkIndexToAddress[punkIndex] = msg.sender; balanceOf[offer.seller]--; balanceOf[msg.sender]++; Transfer(offer.seller, msg.sender, 1); punkNoLongerForSale(punkIndex); pendingWithdrawals[offer.seller] += msg.value; PunkBought(punkIndex, msg.value, offer.seller, msg.sender); } function withdraw() { uint amount = pendingWithdrawals[msg.sender]; // Remember to zero the pending refund before // sending to prevent re-entrancy attacks pendingWithdrawals[msg.sender] = 0; msg.sender.transfer(amount); } }
Bearbeitung
Datei öffnen
// SPDX-License-Identifier: UNLICENSE pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; contract CryptoPhunksV2 is Ownable, ERC721Enumerable, ReentrancyGuard { using Counters for Counters.Counter; using Strings for uint256; // You can use this hash to verify the image file containing all the phunks string public constant imageHash = "122dab9670c21ad538dafdbb87191c4d7114c389af616c42c54556aa2211b899"; constructor() ERC721("CryptoPhunksV2", "PHUNK") {} bool public isSaleOn = false; bool public saleHasBeenStarted = false; uint256 public constant MAX_MINTABLE_AT_ONCE = 50; uint256[10000] private _availableTokens; uint256 private _numAvailableTokens = 10000; uint256 private _numFreeRollsGiven = 0; mapping(address => uint256) public freeRollPhunks; uint256 private _lastTokenIdMintedInInitialSet = 10000; function numTotalPhunks() public view virtual returns (uint256) { return 10000; } function freeRollMint() public nonReentrant() { uint256 toMint = freeRollPhunks[msg.sender]; freeRollPhunks[msg.sender] = 0; uint256 remaining = numTotalPhunks() - totalSupply(); if (toMint > remaining) { toMint = remaining; } _mint(toMint); } function getNumFreeRollPhunks(address owner) public view returns (uint256) { return freeRollPhunks[owner]; } function mint(uint256 _numToMint) public payable nonReentrant() { require(isSaleOn, "Sale hasn't started."); uint256 totalSupply = totalSupply(); require( totalSupply + _numToMint <= numTotalPhunks(), "There aren't this many phunks left." ); uint256 costForMintingPhunks = getCostForMintingPhunks(_numToMint); require( msg.value >= costForMintingPhunks, "Too little sent, please send more eth." ); if (msg.value > costForMintingPhunks) { payable(msg.sender).transfer(msg.value - costForMintingPhunks); } _mint(_numToMint); } // internal minting function function _mint(uint256 _numToMint) internal { require(_numToMint <= MAX_MINTABLE_AT_ONCE, "Minting too many at once."); uint256 updatedNumAvailableTokens = _numAvailableTokens; for (uint256 i = 0; i < _numToMint; i++) { uint256 newTokenId = useRandomAvailableToken(_numToMint, i); _safeMint(msg.sender, newTokenId); updatedNumAvailableTokens--; } _numAvailableTokens = updatedNumAvailableTokens; } function useRandomAvailableToken(uint256 _numToFetch, uint256 _i) internal returns (uint256) { uint256 randomNum = uint256( keccak256( abi.encode( msg.sender, tx.gasprice, block.number, block.timestamp, blockhash(block.number - 1), _numToFetch, _i ) ) ); uint256 randomIndex = randomNum % _numAvailableTokens; return useAvailableTokenAtIndex(randomIndex); } function useAvailableTokenAtIndex(uint256 indexToUse) internal returns (uint256) { uint256 valAtIndex = _availableTokens[indexToUse]; uint256 result; if (valAtIndex == 0) { // This means the index itself is still an available token result = indexToUse; } else { // This means the index itself is not an available token, but the val at that index is. result = valAtIndex; } uint256 lastIndex = _numAvailableTokens - 1; if (indexToUse != lastIndex) { // Replace the value at indexToUse, now that it's been used. // Replace it with the data from the last index in the array, since we are going to decrease the array size afterwards. uint256 lastValInArray = _availableTokens[lastIndex]; if (lastValInArray == 0) { // This means the index itself is still an available token _availableTokens[indexToUse] = lastIndex; } else { // This means the index itself is not an available token, but the val at that index is. _availableTokens[indexToUse] = lastValInArray; } } _numAvailableTokens--; return result; } function getCostForMintingPhunks(uint256 _numToMint) public view returns (uint256) { require( totalSupply() + _numToMint <= numTotalPhunks(), "There aren't this many phunks left." ); if (_numToMint == 1) { return 0.02 ether; } else if (_numToMint == 3) { return 0.05 ether; } else if (_numToMint == 5) { return 0.07 ether; } else if (_numToMint == 10) { return 0.10 ether; } else { revert("Unsupported mint amount"); } } function getPhunksBelongingToOwner(address _owner) external view returns (uint256[] memory) { uint256 numPhunks = balanceOf(_owner); if (numPhunks == 0) { return new uint256[](0); } else { uint256[] memory result = new uint256[](numPhunks); for (uint256 i = 0; i < numPhunks; i++) { result[i] = tokenOfOwnerByIndex(_owner, i); } return result; } } /* * Dev stuff. */ // metadata URI string private _baseTokenURI; function _baseURI() internal view virtual override returns (string memory) { return _baseTokenURI; } function tokenURI(uint256 _tokenId) public view override returns (string memory) { string memory base = _baseURI(); string memory _tokenURI = Strings.toString(_tokenId); // If there is no base URI, return the token URI. if (bytes(base).length == 0) { return _tokenURI; } return string(abi.encodePacked(base, _tokenURI)); } // contract metadata URI for opensea string public contractURI; /* * Owner stuff */ function startSale() public onlyOwner { isSaleOn = true; saleHasBeenStarted = true; } function endSale() public onlyOwner { isSaleOn = false; } function giveFreeRoll(address receiver) public onlyOwner { // max number of free mints we can give to the community for promotions/marketing require(_numFreeRollsGiven < 200, "already given max number of free rolls"); uint256 freeRolls = freeRollPhunks[receiver]; freeRollPhunks[receiver] = freeRolls + 1; _numFreeRollsGiven = _numFreeRollsGiven + 1; } // for handing out free rolls to v1 phunk owners // details on seeding info here: https://gist.github.com/cryptophunks/7f542feaee510e12464da3bb2a922713 function seedFreeRolls( address[] memory tokenOwners, uint256[] memory numOfFreeRolls ) public onlyOwner { require( !saleHasBeenStarted, "cannot seed free rolls after sale has started" ); require( tokenOwners.length == numOfFreeRolls.length, "tokenOwners does not match numOfFreeRolls length" ); // light check to make sure the proper values are being passed require(numOfFreeRolls[0] <= 3, "cannot give more than 3 free rolls"); for (uint256 i = 0; i < tokenOwners.length; i++) { freeRollPhunks[tokenOwners[i]] = numOfFreeRolls[i]; } } // for seeding the v2 contract with v1 state // details on seeding info here: https://gist.github.com/cryptophunks/7f542feaee510e12464da3bb2a922713 function seedInitialContractState( address[] memory tokenOwners, uint256[] memory tokens ) public onlyOwner { require( !saleHasBeenStarted, "cannot initial phunk mint if sale has started" ); require( tokenOwners.length == tokens.length, "tokenOwners does not match tokens length" ); uint256 lastTokenIdMintedInInitialSetCopy = _lastTokenIdMintedInInitialSet; for (uint256 i = 0; i < tokenOwners.length; i++) { uint256 token = tokens[i]; require( lastTokenIdMintedInInitialSetCopy > token, "initial phunk mints must be in decreasing order for our availableToken index to work" ); lastTokenIdMintedInInitialSetCopy = token; useAvailableTokenAtIndex(token); _safeMint(tokenOwners[i], token); } _lastTokenIdMintedInInitialSet = lastTokenIdMintedInInitialSetCopy; } // URIs function setBaseURI(string memory baseURI) external onlyOwner { _baseTokenURI = baseURI; } function setContractURI(string memory _contractURI) external onlyOwner { contractURI = _contractURI; } function withdrawMoney() public payable onlyOwner { (bool success, ) = msg.sender.call{value: address(this).balance}(""); require(success, "Transfer failed."); } function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override(ERC721Enumerable) { super._beforeTokenTransfer(from, to, tokenId); } function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Enumerable) returns (bool) { return super.supportsInterface(interfaceId); } }
Unterschied finden