Diff
checker
Texte
Texte
Images
Documents
Excel
Dossiers
Legal
Enterprise
Application de bureau
Prix
Se connecter
Télécharger Diffchecker Desktop
Comparer le texte
Trouver la différence entre deux fichiers texte
Outils
Historique
Éditeur live
Cacher identiques
Sans retour à la ligne
Vue
Divisé
Unifié
Niveau de précision
Intelligent
Mot
Caractère
Coloration syntaxique
Choisir la syntaxe
Ignorer
Transformer le texte
Aller au premier écart
Modifier l'entrée
Diffchecker Desktop
La façon la plus sécurisée d'utiliser Diffchecker. Obtenez l'application Diffchecker Desktop : vos diffs ne quittent jamais votre ordinateur !
Obtenir Desktop
CryptoPunks v1 vs CryptoPhunks
Créé
il y a 4 ans
Le diff n'expire jamais
Effacer
Exporter
Partager
Expliquer
124 suppressions
Lignes
Total
Supprimé
Caractères
Total
Supprimé
Pour continuer à utiliser cette fonctionnalité, passez à
Diff
checker
Pro
Voir les prix
140 lignes
Copier tout
298 ajouts
Lignes
Total
Ajouté
Caractères
Total
Ajouté
Pour continuer à utiliser cette fonctionnalité, passez à
Diff
checker
Pro
Voir les prix
314 lignes
Copier tout
Copier
Copié
Copier
Copié
/**
// SPDX-License-Identifier: UNLICENSE
*Submitted for verification at Etherscan.io on 2017-06-17
pragma solidity ^0.8.0;
*/
Copier
Copié
Copier
Copié
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";
Copier
Copié
Copier
Copié
// 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;
Copier
Copié
Copier
Copié
address owner;
// You can use this hash to verify the image file containing all the phunks
string public constant imageHash =
"122dab9670c21ad538dafdbb87191c4d7114c389af616c42c54556aa2211b899";
Copier
Copié
Copier
Copié
string public standard = 'CryptoPunks';
constructor() ERC721("CryptoPhunksV2", "PHUNK") {}
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
Copier
Copié
Copier
Copié
uint
public
nextPunkIndexToAssign
=
0
;
bool
public
isSaleOn
=
false
;
Copier
Copié
Copier
Copié
//
bool public
allPunksAssigned
= false;
bool public
saleHasBeenStarted
= false;
uint public punksRemainingToAssign = 0;
uint public numberOfPunksToReserve;
uint public numberOfPunksReserved = 0;
Copier
Copié
Copier
Copié
//mapping (address =>
uint
)
public
addressToPunkIndex;
uint
256
public
constant MAX_MINTABLE_AT_ONCE = 50;
mapping (uint => address) public punkIndexToAddress;
Copier
Copié
Copier
Copié
/* This creates an array with all balances */
uint256[10000] private _availableTokens;
mapping (address =>
uint256
) public balanceOf
;
uint256 private _numAvailableTokens = 10000;
uint256
private _numFreeRollsGiven = 0
;
Copier
Copié
Copier
Copié
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
}
Copier
Copié
Copier
Copié
// 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;
Copier
Copié
Copier
Copié
mapping (address => uint
) public
pendingWithdrawals;
function numTotalPhunks(
) public
view virtual returns (uint256) {
return 10000;
}
Copier
Copié
Copier
Copié
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);
}
Copier
Copié
Copier
Copié
/* 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);
}
}
Copier
Copié
Copier
Copié
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;
}
}
Copier
Copié
Copier
Copié
_numAvailableTokens = updatedNumAvailableTokens;
}
Copier
Copié
Copier
Copié
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;
}
}
Copier
Copié
Copier
Copié
// 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;
}
}
}
Copier
Copié
Copier
Copié
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");
}
}
Copier
Copié
Copier
Copié
}
Copier
Copié
Copier
Copié
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
;
}
}
Copier
Copié
Copier
Copié
}
Copier
Copié
Copier
Copié
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;
}
}
Copier
Copié
Copier
Copié
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
Copier
Copié
Copier
Copié
punkIndexToAddress[punkIndex] = msg.sender;
// contract metadata URI for opensea
balanceOf[offer.seller]--;
string public contractURI;
balanceOf[msg.sender]++;
Transfer(offer.seller, msg.sender, 1);
Copier
Copié
Copier
Copié
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];
}
}
Copier
Copié
Copier
Copié
}
Copier
Copié
Copier
Copié
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);
}
}
Copier
Copié
Copier
Copié
_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érences enregistrées
Texte d'origine
Ouvrir un fichier
/** *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); } }
Texte modifié
Ouvrir un fichier
// 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); } }
Trouver la différence