文件 3 的 16:DiamondDawgs.sol
pragma solidity 0.8.7;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/finance/PaymentSplitter.sol";
contract DD is ERC721Enumerable {
bool public swappingActive = false;
uint256 public maxDawgsSupply = 6800;
uint256 private tokenCount;
uint256 public traitCount;
uint256 private timeOutLength = 10;
address public Owner;
struct Token {
uint256 baseAttributes;
mapping(uint256 => uint256) extraAttributes;
string legacyURI;
uint256 timeOut;
}
struct TraitType {
string attributeName;
string attributeURI;
mapping(uint256 => string) breedOverride;
string[] attributeValues;
bool swappable;
bool active;
}
mapping (uint256 => Token) public tokens;
mapping (uint256 => TraitType) public traitTypes;
address owner;
TraitGeneration private traitGeneration;
URIContract private uriContract;
address contractOperator;
modifier onlyOwner() {
require(msg.sender == owner || msg.sender == contractOperator);
_;
}
string[] private Signatures = ["None","Yes"];
constructor(address _generationContract, address _uriContract, address _mintContract) ERC721("Diamond Dawgs", "DAWGS") {
traitGeneration = TraitGeneration(_generationContract);
uriContract = URIContract(_uriContract);
contractOperator = _mintContract;
owner = msg.sender;
setAttribute(traitCount++, true, "Background", "", traitGeneration.getBackgrounds(),false);
setAttribute(traitCount++, true, "Breed", "", traitGeneration.getBreeds(),false);
setAttribute(traitCount++, true, "Eye", "", traitGeneration.getEyes(),false);
setAttribute(traitCount++, true, "Mouth", "", traitGeneration.getMouths(),false);
setAttribute(traitCount++, true, "Undershirt", "", traitGeneration.getUndershirts(),false);
setAttribute(traitCount++, true, "Jersey", "", traitGeneration.getJerseys(),false);
setAttribute(traitCount++, true, "Head", "", traitGeneration.getHeads(),false);
setAttribute(traitCount++, true, "Accessory", "", traitGeneration.getAccessories(),false);
setAttribute(traitCount++, true, "Signature", "", Signatures,false);
}
function getUriValues(uint256 attrI, uint256 valueI,uint256 breedI) public view returns (string memory, string memory, string memory, string memory, bool){
string memory an = traitTypes[attrI].attributeName;
string memory av = traitTypes[attrI].attributeValues[valueI];
string memory au = traitTypes[attrI].attributeURI;
string memory bo = traitTypes[attrI].breedOverride[breedI];
bool ac = traitTypes[attrI].active;
return (an, av, au, bo, ac);
}
function getExtraAttr(uint tokenId, uint256 attrI)public view returns(uint256){
return tokens[tokenId].extraAttributes[attrI];
}
function getLegacyURI(uint tokenId) public view returns(string memory){
return tokens[tokenId].legacyURI;
}
function setLegacyURI(uint tokenId, string memory legacyURI) public onlyOwner {
tokens[tokenId].legacyURI = legacyURI;
}
function addAttValue(uint256 _attributeId, string[] memory _valueArray)public onlyOwner{
traitTypes[_attributeId].attributeValues = _valueArray;
}
function addAttribute(bool active, string memory _traitName, string memory _traitURI, string[] memory _valueArray, bool _swappable) public onlyOwner{
setAttribute(traitCount++, active, _traitName, _traitURI, _valueArray, _swappable);
}
function setAttribute(uint256 _traitId, bool active, string memory _traitName, string memory _traitURI, string[] memory _valueArray, bool _swappable) public onlyOwner {
TraitType storage trait = traitTypes[_traitId];
trait.active = active;
trait.attributeName = _traitName;
trait.attributeURI = _traitURI;
if(_valueArray.length > 0){
trait.attributeValues = _valueArray;
}
trait.swappable = _swappable;
}
function attrOverrideURI(uint _traitIndex, uint[] memory _indexArray, string[] memory _stringArray) public onlyOwner {
for(uint i = 0; i < _indexArray.length; i++){
traitTypes[_traitIndex].breedOverride[_indexArray[i]] = _stringArray[i];
}
}
function generateToken(uint _tokenId) private {
bytes32 pepper = bytes32(abi.encodePacked(Base64.uint2str(_tokenId),block.timestamp, block.difficulty));
uint256[9] memory attributeIndexArray = traitGeneration.generateTraits(pepper);
saveBaseAttributes(_tokenId, attributeIndexArray);
}
function saveBaseAttributes(uint256 _tokenId, uint256[9] memory attrArray) private {
uint256 tokenBaseAtt = uint256(0x0);
for(uint256 i = attrArray.length; i > 0; i--){
uint256 ii = 256 - (i*8);
tokenBaseAtt |= attrArray[i-1]<<ii;
}
tokens[_tokenId].baseAttributes = tokenBaseAtt;
}
function getBaseAttributues(uint256 _tokenId) public view returns(uint256[9] memory){
uint256[9] memory baseAtt;
uint256 baseAttr = tokens[_tokenId].baseAttributes;
for(uint256 i = baseAtt.length; i > 0; i--){
uint256 ii = 256 - (i*8);
baseAtt[i-1] = uint256(uint8(baseAttr>>ii));
}
return baseAtt;
}
function editAttributeToToken(uint256 _tokenId, uint256 _attributeId, uint256 attributeValueId) public onlyOwner {
if(_attributeId < 9){
uint256[9] memory base = getBaseAttributues(_tokenId);
base[_attributeId] = attributeValueId;
saveBaseAttributes(_tokenId, base);
} else {
tokens[_tokenId].extraAttributes[_attributeId] = attributeValueId;
}
}
function swapAttributes(uint256 _token1, uint256 _token2, uint256 attributeId) public {
require(ownerOf(_token1) == msg.sender && ownerOf(_token2) == msg.sender, "Not owner of tokens");
require(swappingActive == true && traitTypes[attributeId].swappable == true, "Swapping not active or unswappable attribute");
require(traitTypes[attributeId].active == true, "Not a valid attribute");
if(attributeId < 9){
uint256[9] memory base1 = getBaseAttributues(_token1);
uint256[9] memory base2 = getBaseAttributues(_token2);
uint256 tmp = base1[attributeId];
base1[attributeId] = base2[attributeId];
base2[attributeId] = tmp;
saveBaseAttributes(_token1, base1);
saveBaseAttributes(_token2, base2);
} else {
uint256 tmp = tokens[_token1].extraAttributes[attributeId];
tokens[_token1].extraAttributes[attributeId] = tokens[_token2].extraAttributes[attributeId];
tokens[_token2].extraAttributes[attributeId] = tmp;
}
uint256 tO = timeOutLength + block.number;
tokens[_token1].timeOut = tO;
tokens[_token2].timeOut = tO;
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(tokens[tokenId].timeOut < block.number);
safeTransferFrom(from, to, tokenId, "");
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory rtn = uriContract.formTokenURI(tokenId);
return rtn;
}
function mint(uint _count, address _to) onlyOwner public {
uint256 _tokenId = tokenCount;
require(_tokenId + _count < maxDawgsSupply, "Max Dawgz Reached");
for(uint i = 0; i < _count; i++){
generateToken(_tokenId);
_safeMint(_to, _tokenId);
_tokenId++;
}
tokenCount = _tokenId;
}
function flipSwapping() public onlyOwner {
swappingActive = !swappingActive;
}
function changeParams(uint256 _totalSupply, address _generationContract, address _uriContract, uint256 _timeOut, address _contractOperator) public onlyOwner {
maxDawgsSupply = _totalSupply;
traitGeneration = TraitGeneration(_generationContract);
uriContract = URIContract(_uriContract);
timeOutLength = _timeOut;
contractOperator = _contractOperator;
}
function transferOwnership(address _newOwner) public onlyOwner {
require(msg.sender == owner, "Not owner");
owner = _newOwner;
}
function setTimeOut(uint256 _tokenId, uint256 _timeOut) public onlyOwner {
tokens[_tokenId].timeOut = _timeOut;
}
}
contract MintContract is Ownable, PaymentSplitter {
bool public sale = false;
bool public saleWhitelist = false;
mapping(address => uint256) public whitelist;
uint256 mintPrice;
uint256 public maxPerTransaction = 7;
address[] private _team = [
0xdE221Ab3868fd89d46835b1bA896aF288ec8705b,
0x12a49C53DEE28E10C392E57394FCACec4e3a3816,
0x3765240be64aF984bC5bB3B6A2988e431d668f6B
];
uint256[] private _teamShares = [
93,
6,
1
];
DD private dd;
constructor(uint256 _mintPrice) PaymentSplitter(_team, _teamShares) {
mintPrice = _mintPrice;
}
function setDD(address _dd) public onlyOwner{
dd = DD(_dd);
}
function flipWhitelistSale() public onlyOwner {
saleWhitelist = !saleWhitelist;
}
function flipSale() public onlyOwner {
sale = !sale;
}
function mint(uint256 _count) public payable {
require(sale == true, "Normal Sale Not Active");
require(_count <= maxPerTransaction, "Over maxPerTransaction");
require(msg.value == mintPrice * _count, "Insuffcient Amount Sent");
dd.mint(_count, msg.sender);
}
function mintWhitelist(uint256 _count) public payable{
require(saleWhitelist == true, "Whitelist Sale Not Active");
require(_count <= whitelist[msg.sender], "Over Whitelist Allowance");
require(msg.value == mintPrice * _count, "Wrong Amount Sent");
dd.mint(_count, msg.sender);
whitelist[msg.sender] -= _count;
}
function mintAirdrop(address[] memory _to) public onlyOwner{
for(uint i = 0; i < _to.length; i++){
dd.mint(1, _to[i]);
}
}
function changeParams(uint256 _mintPrice, uint256 _maxPerTransaction) public onlyOwner{
mintPrice = _mintPrice;
maxPerTransaction = _maxPerTransaction;
}
function addWhitelist(address[] memory _addressArray) public onlyOwner{
for(uint256 i = 0; i < _addressArray.length; i++){
whitelist[_addressArray[i]] = 3;
}
}
function withdrawAll() external onlyOwner {
for (uint256 i = 0; i < _team.length; i++) {
address payable wallet = payable(_team[i]);
release(wallet);
}
}
}
contract URIContract is Ownable {
uint256 size = 800;
string public description = "";
string public earURI = "";
string public placeholder = "https://diamonddawgs.s3.us-east-2.amazonaws.com/placeholder/placeholder.gif";
DD private dd;
function returnAttributeSVG(string memory _addTo, string memory _traitBaseURI, uint256 _valueIndex) public pure returns (string memory){
return string(abi.encodePacked(_addTo, '<image href="' , _traitBaseURI , Base64.uint2str(_valueIndex), '.png" x="0" y="0" width="100%" height="100%"/>'));
}
function returnAttributeValue(string memory _addTo, string memory _attributeName, string memory _attributeValue) public pure returns (string memory){
return string(abi.encodePacked(_addTo, '{"trait_type":"' , _attributeName ,'","value":"', _attributeValue ,'"}'));
}
struct TraitType {
string attributeName;
string attributeURI;
mapping(uint256 => string) breedOverride;
string[] attributeValues;
bool swappable;
bool active;
}
function contractParams(address _dd, string memory _description, uint _size, string memory _placeholder)public onlyOwner{
dd = DD(_dd);
description = _description;
size = _size;
placeholder = _placeholder;
}
function changeEarURI(string memory _earUri) public onlyOwner {
earURI = _earUri;
}
function formTokenURI(uint256 tokenId) public view returns (string memory) {
if(bytes(dd.getLegacyURI(tokenId)).length > 0){
return(dd.getLegacyURI(tokenId));
}
string memory strAttributes = '"attributes":[';
uint256[9] memory baseAtt = dd.getBaseAttributues(tokenId);
for(uint256 i = 0; i < dd.traitCount(); i++){
if(i < 9){
(string memory attributeName, string memory attributeValue, string memory attributeURI, string memory breedOverride, bool active) = dd.getUriValues(i, baseAtt[i], baseAtt[2]);
if(bytes(attributeValue).length > 0 && active == true){
strAttributes = returnAttributeValue(strAttributes, attributeName, attributeValue);
if(i!=8){
strAttributes = string(abi.encodePacked(strAttributes,','));
}
}
}
}
strAttributes = string(abi.encodePacked(strAttributes,']'));
string memory imageBase64 = string(abi.encodePacked('"',placeholder,'"'));
string memory rtn = string(abi.encodePacked('{"name":"DAWG #',Base64.uint2str(tokenId),'","description":"',description,'","image":',imageBase64,',',strAttributes,'}'));
return string(abi.encodePacked('data:application/json;base64,',Base64.encode(bytes(rtn))));
}
}
contract TraitGeneration {
string[] private backgrounds = ["Light Blue","Orange","Grey","Purple",
"Army","Teal","Mint",
"Stadium","LSD"];
string[] private breeds = ["Light","Medium","Dark","Light Husky","Medium Husky",
"Dark Husky","Blond Retriever","LSD Retriever","Gold",
"Gold Husky","LSD"];
string[] private eyes = ["Normal","Red","Blue","Puppy Cry","Grey Sunglasses","Grey Shine Glasses","Yellow Glasses","Eyes Open","Big Blue eyes",
"Yellow Shine Glasses","Black Heart Glasses","Red Heart Glasses","Colorful Glasses","Stoned Eyes",
"LSD Glasses","Gold Heart Glasses"];
string[] private mouths = ["Frown","Smile","Spitting","Smile + Tounge","Bored","Bored + Tounge",
"Gold Grills","Gold Grill + Bubble","Frown + Cigar","Frown + Tounge","Gold Grill + Tounge","Dip Smile","Cigar",
"Spitting Seeds","Gold Dip Smile","Bubble"];
string[] internal undershirts = ["None",
"White","Red","Blue","Black","Navy","Brown","Green","Baby Blue","Orange","Purple"];
string[] private jerseys = ["Red and Navy Blue","White with Red Pinstripe","White and Black","Black and Baby Blue","Black and White","White and Navy Blue","White and Red","Black and Purple","Navy Blue and Baby Blue","Blue and White","Cream and Orange","White and Blue","Black and Yellow","White with Blue Pinstripes","Cream and Blue","Navy Blue and Red","Blue and Red","Brown with Yellow","Navy Blue with Yellow","Green and Yellow",
"White with Navy Blue and Red Lining","White with Navy Blue pinstripes","Gold","Grey with Brown Pinstripes","Baby Blue and Red","LSD","Army","Floral",
"Baby Blue with USA Neck","Baby Blue with Maroon Shoulders","White with Blue Pinstripes and Blue and Orange Shoulders","All Star","Tatoos"];
string[] internal heads = ["Grey Catcher Mask","Blue Catcher Mask","Red Catcher Mask","Hair-Fade","Hair-Afro","blue/blue/white flat bill","navy/navy/white flat bill","red/red/white flat bill","Backwards Red","Backwards Blue","Backwards Navy","Rally Cap Red","Rally Cap Blue","Rally Cap Navy","Red Helmet","Blue Helmet","Red Curved","Blue Curved","Black Curved","Orange Curved",
"Navy Catcher Mask","Hair-Dreads","black/black/white flat bill","brown/brow/yellow flat bill","green/yellow/white flat bill","navy/red/white flat bill","white/orange/black flat bill","Backwards Black","Rally Cap Black","Rally Cap Pastel","Black Helmet","Navy Helmet","Navy Blue Curved","Army Curved","LSD Curved",
"Gold Catcher Mask","Army Flat Bill","Gold Flat Bill","LSD Flat Bill","Gold Helmet","Gold Curved","Black Flat Bill with Glove","Black Flat Bill with Upside Down Glasses"];
string[] internal accessories = ["None","Gold Chain","Black Chest Protector","Navy ChestProtector","Red Chest Protector","Freckles","Wood Baseball Bat",
"Black Diamond Necklace","Eyeblack","Silver Diamond Necklace","Silver Slugger Baseball Bat","Gold Baseball Bat","Blue Chest Protector","Dog Tag Necklace","Little League Pins",
"Flip Glasses","Lazer Eyes","Diamond Pennant Necklace"];
function random(bytes32 t, bytes32 _input, uint8 _mod) private pure returns (uint256) {
return uint256(keccak256(abi.encodePacked(t, _input)))%_mod;
}
function useWeight(uint8[3] memory _split, uint8 _saltI, bytes32 _pepper) private pure returns(uint8){
uint8[3] memory _weights = [75,95,100];
bytes32 salt = "308fd119edae5f1309aafade64147";
uint256 ran1 = random(salt[_saltI], _pepper, 100);
uint8 traitIndex;
uint8 i;
while (_weights[i] < ran1) {
traitIndex += _split[i];
i++;
}
uint256 ran2 = random(salt[_saltI + 2], _pepper, _split[i]);
return uint8(traitIndex + ran2);
}
function useWeightTwo(uint8[2] memory _split, uint8 _saltI, bytes32 _pepper) private pure returns(uint8){
uint8[2] memory _weights = [50,100];
bytes32 salt = "308fd119edae5f1309aafade64147";
uint256 ran1 = random(salt[_saltI], _pepper, 100);
uint8 traitIndex;
uint8 i;
while (_weights[i] < ran1) {
traitIndex += _split[i];
i++;
}
uint256 ran2 = random(salt[_saltI + 2], _pepper, _split[i]);
return uint8(traitIndex + ran2);
}
function useWeightFour(uint8[4] memory _split, uint8 _saltI, bytes32 _pepper) private pure returns(uint8){
uint8[4] memory _weights = [30,70,95,101];
bytes32 salt = "308fd119edae5f1309aafade64147bhs";
uint256 ran1 = random(salt[_saltI], _pepper, 100);
uint8 traitIndex;
uint8 i;
while (_weights[i] < ran1) {
traitIndex += _split[i];
i++;
}
uint256 ran2 = random(salt[_saltI + 1], _pepper, _split[i]);
return uint8(traitIndex + ran2);
}
function generateTraits(bytes32 _pepper) public pure returns (uint256[9] memory) {
uint8[3] memory bgSplit = [4,3,2];
uint8[3] memory brSplit = [5,4,2];
uint8[3] memory eySplit = [9,5,2];
uint8[3] memory moSplit = [6,5,3];
uint8[2] memory unSplit = [1,10];
uint8[3] memory jeSplit = [20,8,5];
uint8[3] memory heSplit = [20,15,8];
uint8[4] memory acSplit = [1,6,8,3];
uint256[9] memory attributeIndexArray;
attributeIndexArray[0] = useWeight(bgSplit, 0, _pepper);
attributeIndexArray[1] = useWeight(brSplit, 2, _pepper);
attributeIndexArray[2] = useWeight(eySplit, 4, _pepper);
attributeIndexArray[3] = useWeight(moSplit, 6, _pepper);
attributeIndexArray[4] = useWeightTwo(unSplit, 7, _pepper);
attributeIndexArray[5] = useWeight(jeSplit, 8, _pepper);
attributeIndexArray[6] = useWeight(heSplit, 12, _pepper);
attributeIndexArray[7] = useWeightFour(acSplit, 3, _pepper);
attributeIndexArray[8] = uint256(uint256(keccak256(abi.encodePacked(_pepper)))%2);
return attributeIndexArray;
}
function getBackgrounds() public view returns (string[] memory){
return backgrounds;
}
function getBreeds() public view returns (string[] memory){
return breeds;
}
function getEyes() public view returns (string[] memory){
return eyes;
}
function getMouths() public view returns (string[] memory){
return mouths;
}
function getJerseys() public view returns (string[] memory){
return jerseys;
}
function getUndershirts() public view returns (string[] memory){
return undershirts;
}
function getHeads() public view returns (string[] memory){
return heads;
}
function getAccessories() public view returns (string[] memory){
return accessories;
}
}
library Base64 {
string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function encode(bytes memory data) internal pure returns (string memory) {
if (data.length == 0) return '';
string memory table = TABLE_ENCODE;
uint256 encodedLen = 4 * ((data.length + 2) / 3);
string memory result = new string(encodedLen + 32);
assembly {
mstore(result, encodedLen)
let tablePtr := add(table, 1)
let dataPtr := data
let endPtr := add(dataPtr, mload(data))
let resultPtr := add(result, 32)
for {} lt(dataPtr, endPtr) {}
{
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and( input, 0x3F))))
resultPtr := add(resultPtr, 1)
}
switch mod(mload(data), 3)
case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
}
return result;
}
function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
if (_i == 0) {
return "0";
}
uint j = _i;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len;
while (_i != 0) {
k = k-1;
uint8 temp = (48 + uint8(_i - _i / 10 * 10));
bytes1 b1 = bytes1(temp);
bstr[k] = b1;
_i /= 10;
}
return string(bstr);
}
}