Diff
checker
Testo
Testo
Immagini
Documenti
Excel
Cartelle
Legal
Enterprise
Applicazione per desktop
Prezzi
Accedi
Scarica Diffchecker Desktop
Confronta il testo
Trova la differenza tra due file di testo
Strumenti
Cronologia
Editor live
Comprimi invariate
Senza a capo
Layout
Diviso
Unificato
Livello di dettaglio
Intelligente
Parola
Carattere
Evidenziazione sintassi
Scegli sintassi
Ignora
Trasforma testo
Vai alla prima modifica
Modifica input
Diffchecker Desktop
Il modo più sicuro per usare Diffchecker. Ottieni l'app Diffchecker Desktop: i tuoi diff non lasciano mai il tuo computer!
Ottieni Desktop
CryptoPunks v1 vs CryptoPhunks
Creato
4 anni fa
Il diff non scade mai
Eliminare
Esporta
Condividere
Spiegare
124 rimozioni
Linee
Totale
Rimosso
Caratteri
Totale
Rimosso
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
140 linee
Copia tutti
298 aggiunte
Linee
Totale
Aggiunto
Caratteri
Totale
Aggiunto
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
314 linee
Copia tutti
Copia
Copiato
Copia
Copiato
/**
// SPDX-License-Identifier: UNLICENSE
*Submitted for verification at Etherscan.io on 2017-06-17
pragma solidity ^0.8.0;
*/
Copia
Copiato
Copia
Copiato
pragma solidity ^0.4.8;
import "@openzeppelin/contracts/access/Ownable.sol";
contract CryptoPunks {
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";
Copia
Copiato
Copia
Copiato
// You can use this hash to verify the image file containing all the punks
contract CryptoPhunksV2 is Ownable, ERC721Enumerable, ReentrancyGuard {
string public imageHash = "ac39af4793119ee46bbff351d8cb6b5f23da60222126add4268e261199a2921b";
using Counters for Counters.Counter;
using Strings for uint256;
Copia
Copiato
Copia
Copiato
address owner;
// You can use this hash to verify the image file containing all the phunks
string public constant imageHash =
"122dab9670c21ad538dafdbb87191c4d7114c389af616c42c54556aa2211b899";
Copia
Copiato
Copia
Copiato
string public standard = 'CryptoPunks';
constructor() ERC721("CryptoPhunksV2", "PHUNK") {}
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
Copia
Copiato
Copia
Copiato
uint
public
nextPunkIndexToAssign
=
0
;
bool
public
isSaleOn
=
false
;
Copia
Copiato
Copia
Copiato
//
bool public
allPunksAssigned
= false;
bool public
saleHasBeenStarted
= false;
uint public punksRemainingToAssign = 0;
uint public numberOfPunksToReserve;
uint public numberOfPunksReserved = 0;
Copia
Copiato
Copia
Copiato
//mapping (address =>
uint
)
public
addressToPunkIndex;
uint
256
public
constant MAX_MINTABLE_AT_ONCE = 50;
mapping (uint => address) public punkIndexToAddress;
Copia
Copiato
Copia
Copiato
/* This creates an array with all balances */
uint256[10000] private _availableTokens;
mapping (address =>
uint256
) public balanceOf
;
uint256 private _numAvailableTokens = 10000;
uint256
private _numFreeRollsGiven = 0
;
Copia
Copiato
Copia
Copiato
struct Offer {
mapping(
address
=>
uint
256) public freeRollPhunks;
bool isForSale;
uint punkIndex;
address
seller;
uint
minValue; // in ether
address onlySellTo; // specify to sell only to a specific person
}
Copia
Copiato
Copia
Copiato
// A record of punks that are offered for sale at a specific minimum value, and perhaps to a specific person
uint256 private _lastTokenIdMintedInInitialSet = 10000;
mapping (uint => Offer) public punksOfferedForSale;
Copia
Copiato
Copia
Copiato
mapping (address => uint
) public
pendingWithdrawals;
function numTotalPhunks(
) public
view virtual returns (uint256) {
return 10000;
}
Copia
Copiato
Copia
Copiato
event Assign(address indexed to, uint256 punkIndex);
function freeRollMint() public nonReentrant() {
event Transfer(address indexed from, address indexed to, uint256 value);
uint256 toMint = freeRollPhunks[msg.sender];
event PunkTransfer(address indexed from, address indexed to, uint256 punkIndex);
freeRollPhunks[msg.sender] = 0;
event PunkOffered(uint indexed punkIndex, uint minValue, address indexed toAddress);
uint256 remaining = numTotalPhunks() - totalSupply();
event PunkBought(uint indexed punkIndex, uint value, address indexed fromAddress, address indexed toAddress);
if (toMint > remaining) {
event PunkNoLongerForSale(u
int
indexed punkIndex);
toMint = remaining;
}
_m
int
(toMint);
}
Copia
Copiato
Copia
Copiato
/* Initializes contract with initial supply tokens to the creator of the contract */
function getNumFreeRollPhunks(address owner) public view returns (uint256) {
function CryptoPunks() payable {
return freeRollPhunks[owner];
// balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
}
owner = msg.sender;
totalSupply = 10000; // Update total supply
function mint(uint256 _numToMint) public payable nonReentrant() {
punksRemainingToAssign = totalSupply;
require(isSaleOn, "Sale hasn't started.");
numberOfPunksToReserve = 1000;
uint256 totalSupply = totalSupply();
name = "CRYPTOPUNKS"; // Set the name for display purposes
require(
symbol
=
"Ͼ";
// Set the symbol for display purposes
totalSupply + _numToMint <= numTotalPhunks(),
decimals = 0;
// Amount of decimals for display purposes
"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);
}
}
Copia
Copiato
Copia
Copiato
function reservePunksForOwner(uint maxForThisRun) {
_mint(_numToMint);
if (msg.sender != owner) throw;
}
if (numberOfPunksReserved >= numberOfPunksToReserve) throw;
uint numberPunksReservedThisRun = 0;
// internal minting function
while (numberOfPunksReserved < numberOfPunksToReserve && numberPunksReservedThisRun < maxForThisRun) {
function _mint(uint256 _numToMint) internal {
punkIndexToAddress[nextPunkIndexToAssign]
=
msg.sender
;
require(_numToMint <= MAX_MINTABLE_AT_ONCE, "Minting too many at once.");
Assign
(msg.sender,
nextPunkIndexToAssign
);
numberPunksReservedThisRun++;
uint256 updatedNumAvailableTokens = _numAvailableTokens;
nextPunkIndexToAssign++;
for (uint256 i = 0; i < _numToMint; i++) {
}
uint256 newTokenId
=
useRandomAvailableToken(_numToMint, i)
;
punksRemainingToAssign -= numberPunksReservedThisRun;
_safeMint
(msg.sender,
newTokenId
);
numberOfPunksReserved += numberPunksReservedThisRun;
updatedNumAvailableTokens--;
balanceOf[msg.sender] += numberPunksReservedThisRun;
}
}
Copia
Copiato
Copia
Copiato
_numAvailableTokens = updatedNumAvailableTokens;
}
Copia
Copiato
Copia
Copiato
function getPunk(uint punkIndex) {
function useRandomAvailableToken(uint256 _numToFetch, uint256 _i)
if (punksRemainingToAssign == 0) throw;
internal
if (punkIndexToAddress[punkIndex] != 0x0) throw;
returns (uint256)
punkIndexToAddress[punkIndex] = msg.sender;
{
balanceOf[msg.sender]++;
uint256 randomNum =
punksRemainingToAssign--;
uint256(
Assign(msg.sender, punkIndex);
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;
}
}
Copia
Copiato
Copia
Copiato
// Transfer ownership of a punk to another user without requiring payment
uint256 lastIndex = _numAvailableTokens - 1;
function transferPunk(address to, uint punkIndex
) {
if (indexToUse != lastIndex
) {
if (punkIndexToAddress[punkIndex] != msg.sender) throw;
// Replace the value at indexToUse, now that it's been used.
punkIndexToAddress[punkIndex] = to;
// Replace it with the data from the last index in the array, since we are going to decrease the array size afterwards.
balanceOf[msg.sender]--;
uint256 lastValInArray = _availableTokens[lastIndex];
balanceOf[to]++;
if (lastValInArray == 0) {
Transfer(msg.sender, to, 1);
// This means the index itself is still an available token
PunkTransfer(msg.sender, to, punkIndex);
_availableTokens[indexToUse] = lastIndex;
} else {
// This means the index itself is not an available token, but the val at that index is.
_availableTokens[indexToUse] = lastValInArray;
}
}
}
Copia
Copiato
Copia
Copiato
function punkNoLongerForSale(uint punkIndex) {
_numAvailableTokens--;
if (punkIndexToAddress[punkIndex] != msg.sender) throw;
return result;
punksOfferedForSale[punkIndex] = Offer(false, punkIndex, msg.sender, 0, 0x0);
}
PunkNoLongerForSale(punkIndex);
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");
}
}
Copia
Copiato
Copia
Copiato
}
Copia
Copiato
Copia
Copiato
function offerPunkForSale(uint punkIndex, uint minSalePriceInWei) {
function getPhunksBelongingToOwner(address _owner)
if (punkIndexToAddress[punkIndex] != msg.sender) throw;
external
punksOfferedForSale[punkIndex] = Offer(true, punkIndex, msg.sender, minSalePriceInWei, 0x0);
view
PunkOffered(punkIndex, minSalePriceInWei, 0x0)
;
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
;
}
}
Copia
Copiato
Copia
Copiato
}
Copia
Copiato
Copia
Copiato
function offerPunkForSaleToAddress(uint punkIndex, uint minSalePriceInWei, address toAddress) {
/*
if (punkIndexToAddress[punkIndex] != msg.sender) throw;
* Dev stuff.
punksOfferedForSale[punkIndex] = Offer(true, punkIndex, msg.sender, minSalePriceInWei, toAddress);
*/
PunkOffered(punkIndex, minSalePriceInWei, toAddress);
// 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;
}
}
Copia
Copiato
Copia
Copiato
function buyPunk(uint punkIndex) payable {
return string(abi.encodePacked(base, _tokenURI));
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
Copia
Copiato
Copia
Copiato
punkIndexToAddress[punkIndex] = msg.sender;
// contract metadata URI for opensea
balanceOf[offer.seller]--;
string public contractURI;
balanceOf[msg.sender]++;
Transfer(offer.seller, msg.sender, 1);
Copia
Copiato
Copia
Copiato
punkNoLongerForSale(punkIndex);
/*
pendingWithdrawals[offer.seller] += msg.value;
* Owner stuff
PunkBought(punkIndex, msg.value, offer.seller, msg.sender);
*/
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];
}
}
Copia
Copiato
Copia
Copiato
}
Copia
Copiato
Copia
Copiato
function withdraw() {
// for seeding the v2 contract with v1 state
uint amount = pendingWithdrawals[msg.sender];
// details on seeding info here: https://gist.github.com/cryptophunks/7f542feaee510e12464da3bb2a922713
// Remember to zero the pending refund before
function seedInitialContractState(
// sending to prevent re-entrancy attacks
address[] memory tokenOwners,
pendingWithdrawals[msg.sender] = 0;
uint256[] memory tokens
msg.sender.transfer(amount);
) 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);
}
}
Copia
Copiato
Copia
Copiato
_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);
}
}
}
Diff salvati
Testo originale
Apri file
/** *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); } }
Testo modificato
Apri file
// 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); } }
Trovare la differenza