Diff
checker
Texto
Texto
Imagens
Documentos
Excel
Pastas
Legal
Enterprise
Aplicativo para desktop
Preços
Fazer login
Baixar o Diffchecker Desktop
Comparar texto
Encontre a diferença entre dois arquivos de texto
Ferramentas
Histórico
Editor live
Recolher inalteradas
Sem quebra de linha
Layout
Dividido
Unificado
Nível de detalhe
Inteligente
Palavra
Caractere
Realce de sintaxe
Escolher sintaxe
Ignorar
Transformar texto
Ir à primeira mudança
Editar entrada
Diffchecker Desktop
A maneira mais segura de usar o Diffchecker. Obtenha o aplicativo Diffchecker Desktop: seus diffs nunca saem do seu computador!
Obter Desktop
CryptoPunks v1 vs CryptoPhunks
Criado
há 4 anos
O diff nunca expira
Limpar
Exportar
Compartilhar
Explicar
124 remoções
Linhas
Total
Removido
Caracteres
Total
Removido
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
140 linhas
Copiar tudo
298 adições
Linhas
Total
Adicionado
Caracteres
Total
Adicionado
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
314 linhas
Copiar tudo
Copiar
Copiado
Copiar
Copiado
/**
// SPDX-License-Identifier: UNLICENSE
*Submitted for verification at Etherscan.io on 2017-06-17
pragma solidity ^0.8.0;
*/
Copiar
Copiado
Copiar
Copiado
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";
Copiar
Copiado
Copiar
Copiado
// 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;
Copiar
Copiado
Copiar
Copiado
address owner;
// You can use this hash to verify the image file containing all the phunks
string public constant imageHash =
"122dab9670c21ad538dafdbb87191c4d7114c389af616c42c54556aa2211b899";
Copiar
Copiado
Copiar
Copiado
string public standard = 'CryptoPunks';
constructor() ERC721("CryptoPhunksV2", "PHUNK") {}
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
Copiar
Copiado
Copiar
Copiado
uint
public
nextPunkIndexToAssign
=
0
;
bool
public
isSaleOn
=
false
;
Copiar
Copiado
Copiar
Copiado
//
bool public
allPunksAssigned
= false;
bool public
saleHasBeenStarted
= false;
uint public punksRemainingToAssign = 0;
uint public numberOfPunksToReserve;
uint public numberOfPunksReserved = 0;
Copiar
Copiado
Copiar
Copiado
//mapping (address =>
uint
)
public
addressToPunkIndex;
uint
256
public
constant MAX_MINTABLE_AT_ONCE = 50;
mapping (uint => address) public punkIndexToAddress;
Copiar
Copiado
Copiar
Copiado
/* This creates an array with all balances */
uint256[10000] private _availableTokens;
mapping (address =>
uint256
) public balanceOf
;
uint256 private _numAvailableTokens = 10000;
uint256
private _numFreeRollsGiven = 0
;
Copiar
Copiado
Copiar
Copiado
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
}
Copiar
Copiado
Copiar
Copiado
// 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;
Copiar
Copiado
Copiar
Copiado
mapping (address => uint
) public
pendingWithdrawals;
function numTotalPhunks(
) public
view virtual returns (uint256) {
return 10000;
}
Copiar
Copiado
Copiar
Copiado
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);
}
Copiar
Copiado
Copiar
Copiado
/* 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);
}
}
Copiar
Copiado
Copiar
Copiado
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;
}
}
Copiar
Copiado
Copiar
Copiado
_numAvailableTokens = updatedNumAvailableTokens;
}
Copiar
Copiado
Copiar
Copiado
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;
}
}
Copiar
Copiado
Copiar
Copiado
// 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;
}
}
}
Copiar
Copiado
Copiar
Copiado
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");
}
}
Copiar
Copiado
Copiar
Copiado
}
Copiar
Copiado
Copiar
Copiado
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
;
}
}
Copiar
Copiado
Copiar
Copiado
}
Copiar
Copiado
Copiar
Copiado
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;
}
}
Copiar
Copiado
Copiar
Copiado
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
Copiar
Copiado
Copiar
Copiado
punkIndexToAddress[punkIndex] = msg.sender;
// contract metadata URI for opensea
balanceOf[offer.seller]--;
string public contractURI;
balanceOf[msg.sender]++;
Transfer(offer.seller, msg.sender, 1);
Copiar
Copiado
Copiar
Copiado
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];
}
}
Copiar
Copiado
Copiar
Copiado
}
Copiar
Copiado
Copiar
Copiado
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);
}
}
Copiar
Copiado
Copiar
Copiado
_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);
}
}
}
Diferenças salvas
Texto original
Abrir arquivo
/** *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); } }
Texto alterado
Abrir arquivo
// 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); } }
Encontrar Diferença