diff --git a/contract/contracts/LocalNounsToken.sol b/contract/contracts/LocalNounsToken.sol index 655d3b44..e9785eb9 100644 --- a/contract/contracts/LocalNounsToken.sol +++ b/contract/contracts/LocalNounsToken.sol @@ -7,6 +7,7 @@ pragma solidity ^0.8.6; import '@openzeppelin/contracts/utils/Strings.sol'; + import './libs/ProviderTokenA2.sol'; import { INounsSeeder } from './localNouns/interfaces/INounsSeeder.sol'; import './localNouns/interfaces/IAssetProviderExMint.sol'; @@ -77,7 +78,7 @@ contract LocalNounsToken is ProviderTokenA2, ILocalNounsToken { uint256 _prefectureId, uint256 _amount ) public virtual returns (uint256 tokenId) { - require(msg.sender == minter, 'Sender is not the minter'); + require(msg.sender == minter || msg.sender == owner(), 'Sender is not minter nor owner'); require(_prefectureId % 100 <= 47, 'Invalid prefectureId'); for (uint256 i = 0; i < _amount; i++) { @@ -87,6 +88,20 @@ contract LocalNounsToken is ProviderTokenA2, ILocalNounsToken { return _nextTokenId() - 1; } + function ownerMint( + address[] memory _to, + uint256[] memory _prefectureId, + uint256[] memory _amount + ) public onlyOwner returns (uint256 tokenId) { + // 引数の整合性チェック + require(_to.length == _prefectureId.length && _to.length == _amount.length, 'Invalid Arrays length'); + + for (uint256 i; i < _to.length; i++) { + mintSelectedPrefecture(_to[i], _prefectureId[i], _amount[i]); + } + return _nextTokenId() - 1; + } + function mint() public payable override returns (uint256 tokenId) { revert('Cannot use this function'); } @@ -171,9 +186,10 @@ contract LocalNounsToken is ProviderTokenA2, ILocalNounsToken { (bool sent, ) = payable(administratorsAddress).call{ value: address(this).balance }(''); require(sent, 'failed to move fund to administratorsAddress contract'); } - + // iLocalNounsTokenでERC721のtotalSupplyを使用したいけど、二重継承でエラーになるので個別関数を準備 function totalSupply2() public view returns (uint256) { return super.totalSupply(); + } } diff --git a/contract/contracts/external/nouns/NounsDescripter.sol b/contract/contracts/external/nouns/NounsDescripter.sol index f62d6fd3..2bbb56ec 100644 --- a/contract/contracts/external/nouns/NounsDescripter.sol +++ b/contract/contracts/external/nouns/NounsDescripter.sol @@ -261,6 +261,7 @@ contract NounsDescriptor is INounsDescriptor, Ownable { */ function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) public view override returns (string memory) { string memory nounId = tokenId.toString(); + string memory name = string(abi.encodePacked('Aid pNoun ', nounId)); string memory description = string(abi.encodePacked('Aid pNoun ', nounId, ' is proof of contribution to pNouns DAO.')); diff --git a/contract/contracts/localNouns/LocalNounsProvider.sol b/contract/contracts/localNouns/LocalNounsProvider.sol index 7e9f6470..8f23a2e4 100644 --- a/contract/contracts/localNouns/LocalNounsProvider.sol +++ b/contract/contracts/localNouns/LocalNounsProvider.sol @@ -33,6 +33,13 @@ contract LocalNounsProvider is IAssetProviderExMint, IERC165, Ownable { mapping(uint256 => uint256) public tokenIdToPrefectureId; mapping(uint256 => string) public prefectureName; mapping(uint256 => uint256) public mintNumberPerPrefecture; // 都道府県ごとのミント数 + // mapping(uint256 => uint256) public prefectureRatio; // ランダムミント時に決定される都道府県の割合 + uint256 totalPrefectureRatio; + + uint256[5] ratioRank = [5, 4, 3, 3, 2]; + uint256[5] acumulationRatioRank = [5, 9, 12, 15, 17]; // ratioRankの積み上げ + uint256 acumulationRatioRankTotal = 17; // sum(ratioRank) + mapping(uint256 => uint256[]) public prefectureRatio; constructor( INounsDescriptor _descriptor, @@ -94,6 +101,12 @@ contract LocalNounsProvider is IAssetProviderExMint, IERC165, Ownable { prefectureName[45] = 'Miyazaki'; prefectureName[46] = 'Kagoshima'; prefectureName[47] = 'Okinawa'; + + prefectureRatio[0] = [13, 14, 27, 23, 11, 12, 28, 1, 40]; + prefectureRatio[1] = [22, 8, 34, 26, 4, 15, 20, 21, 10]; + prefectureRatio[2] = [9, 33, 7, 24, 43, 46, 47, 25, 35]; + prefectureRatio[3] = [29, 38, 42, 2, 3, 17, 44, 45, 6, 16]; + prefectureRatio[4] = [37, 5, 30, 19, 41, 18, 36, 39, 32, 31]; } function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { @@ -166,16 +179,45 @@ contract LocalNounsProvider is IAssetProviderExMint, IERC165, Ownable { ); } - function mint(uint256 prefectureId, uint256 _assetId) external returns (uint256) { + bool randomValueForTest = false; + + function setRandomValueForTest(bool _test) public onlyOwner { + randomValueForTest = _test; + } + + // テスト用にpublic + function determinePrefectureId(uint256 _assetId) public view returns (uint256) { + uint256 randomValue; + if (randomValueForTest) { + // For TEST + randomValue = _assetId; + } else { + // ブロック番号とアセット番号から計算した値 -> ランダム値 + randomValue = uint256(keccak256(abi.encodePacked(block.timestamp, _assetId))); + } + + uint256 rank = randomValue % acumulationRatioRankTotal; + for (uint256 i = 0; i < acumulationRatioRank.length; i++) { + if (rank < acumulationRatioRank[i]) { + rank = i; + break; + } + } + return prefectureRatio[rank][randomValue % prefectureRatio[rank].length]; + } + + function mint(uint256 _prefectureId, uint256 _assetId) external returns (uint256) { + uint256 prefectureId; // 末尾2桁が00の場合は都道府県をランダムに決定する - if (prefectureId % 100 == 0) { - prefectureId = prefectureId + ((block.number * _assetId) % 46) + 1; + if (_prefectureId % 100 == 0) { + prefectureId = _prefectureId + determinePrefectureId(_assetId); + } else { + prefectureId = _prefectureId; } seeds[_assetId] = generateSeed(prefectureId, _assetId); - uint256 prefectureId = prefectureId % 100; // 下2桁:都道府県番号、下3桁より上位:バージョン番号 - tokenIdToPrefectureId[_assetId] = prefectureId; - mintNumberPerPrefecture[prefectureId]++; + tokenIdToPrefectureId[_assetId] = prefectureId % 100; + mintNumberPerPrefecture[prefectureId % 100]++; nextTokenId++; return _assetId; diff --git a/contract/contracts/localNouns/LocalNounsSeeder.sol b/contract/contracts/localNouns/LocalNounsSeeder.sol index cd7a847a..1f8b3f74 100644 --- a/contract/contracts/localNouns/LocalNounsSeeder.sol +++ b/contract/contracts/localNouns/LocalNounsSeeder.sol @@ -29,10 +29,12 @@ contract LocalNounsSeeder is ILocalNounsSeeder { keccak256(abi.encodePacked(blockhash(block.number - 1), nounId)) ); + uint256 accessoryCount = descriptor.accessoryCountInPrefecture(prefectureId % 100); // 1,2桁目:都道府県番号、3桁目以降:バージョン番号 uint256 headCount = descriptor.headCountInPrefecture(prefectureId); uint256 accesoryPartId = descriptor.accessoryInPrefecture(prefectureId % 100, (pseudorandomness >> 96) % accessoryCount); + uint256 headPartId = descriptor.headInPrefecture(prefectureId, (pseudorandomness >> 144) % headCount); return Seed({ diff --git a/contract/contracts/localNouns/interfaces/IAssetProviderExMint.sol b/contract/contracts/localNouns/interfaces/IAssetProviderExMint.sol index aac77903..0b263a3a 100644 --- a/contract/contracts/localNouns/interfaces/IAssetProviderExMint.sol +++ b/contract/contracts/localNouns/interfaces/IAssetProviderExMint.sol @@ -7,4 +7,5 @@ import 'assetprovider.sol/IAssetProvider.sol'; interface IAssetProviderExMint is IAssetProvider { function mint(uint256 prefectureId, uint256 _assetId) external returns (uint256); function getPrefectureId(uint256 prefectureId) external returns (uint256); + } diff --git a/contract/contracts/localNouns/interfaces/INounsDescriptor.sol b/contract/contracts/localNouns/interfaces/INounsDescriptor.sol index 79a08076..557b933e 100644 --- a/contract/contracts/localNouns/interfaces/INounsDescriptor.sol +++ b/contract/contracts/localNouns/interfaces/INounsDescriptor.sol @@ -21,87 +21,87 @@ import { INounsSeeder } from './INounsSeeder.sol'; import { INounsDescriptorMinimal } from './INounsDescriptorMinimal.sol'; interface INounsDescriptor is INounsDescriptorMinimal { - event PartsLocked(); + event PartsLocked(); - event DataURIToggled(bool enabled); + event DataURIToggled(bool enabled); - event BaseURIUpdated(string baseURI); + event BaseURIUpdated(string baseURI); - function arePartsLocked() external returns (bool); + function arePartsLocked() external returns (bool); - function isDataURIEnabled() external returns (bool); + function isDataURIEnabled() external returns (bool); - function baseURI() external returns (string memory); + function baseURI() external returns (string memory); - function palettes(uint8 paletteIndex, uint256 colorIndex) external view returns (string memory); + function palettes(uint8 paletteIndex, uint256 colorIndex) external view returns (string memory); - function backgrounds(uint256 index) external view returns (string memory); + function backgrounds(uint256 index) external view returns (string memory); - function bodies(uint256 index) external view returns (bytes memory); + function bodies(uint256 index) external view returns (bytes memory); - function accessories(uint256 index) external view returns (bytes memory); + function accessories(uint256 index) external view returns (bytes memory); - function heads(uint256 index) external view returns (bytes memory); + function heads(uint256 index) external view returns (bytes memory); - function glasses(uint256 index) external view returns (bytes memory); + function glasses(uint256 index) external view returns (bytes memory); - function backgroundCount() external view override returns (uint256); + function backgroundCount() external view override returns (uint256); - function bodyCount() external view override returns (uint256); + function bodyCount() external view override returns (uint256); - function accessoryCount() external view override returns (uint256); + function accessoryCount() external view override returns (uint256); - function accessoryCountInPrefecture(uint256 prefectureId) external view returns (uint256); + function accessoryCountInPrefecture(uint256 prefectureId) external view returns (uint256); - function accessoryName(uint256 partsId) external view returns (string memory); - - function headCount() external view override returns (uint256); + function accessoryName(uint256 partsId) external view returns (string memory); - function headCountInPrefecture(uint256 prefectureId) external view returns (uint256); + function headCount() external view override returns (uint256); - function headName(uint256 partsId) external view returns (string memory); + function headCountInPrefecture(uint256 prefectureId) external view returns (uint256); - function glassesCount() external view override returns (uint256); + function headName(uint256 partsId) external view returns (string memory); - function addManyColorsToPalette(uint8 paletteIndex, string[] calldata newColors) external; + function glassesCount() external view override returns (uint256); - function addManyBackgrounds(string[] calldata backgrounds) external; + function addManyColorsToPalette(uint8 paletteIndex, string[] calldata newColors) external; - function addManyBodies(bytes[] calldata bodies) external; + function addManyBackgrounds(string[] calldata backgrounds) external; - function addManyAccessories(uint256 prefectureId, bytes[] calldata accessories, string[] calldata name) external; + function addManyBodies(bytes[] calldata bodies) external; - function addManyHeads(uint256 prefectureId, bytes[] calldata heads, string[] calldata name) external; + function addManyAccessories(uint256 prefectureId, bytes[] calldata accessories, string[] calldata name) external; - function addManyGlasses(bytes[] calldata glasses) external; + function addManyHeads(uint256 prefectureId, bytes[] calldata heads, string[] calldata name) external; - function addColorToPalette(uint8 paletteIndex, string calldata color) external; + function addManyGlasses(bytes[] calldata glasses) external; - function addBackground(string calldata background) external; + function addColorToPalette(uint8 paletteIndex, string calldata color) external; - function addBody(bytes calldata body) external; + function addBackground(string calldata background) external; - function addAccessory(uint256 prefectureId, bytes calldata accessory, string calldata name) external; + function addBody(bytes calldata body) external; - function addHead(uint256 prefectureId, bytes calldata head, string calldata name) external; + function addAccessory(uint256 prefectureId, bytes calldata accessory, string calldata name) external; - function addGlasses(bytes calldata glasses) external; + function addHead(uint256 prefectureId, bytes calldata head, string calldata name) external; - function lockParts() external; + function addGlasses(bytes calldata glasses) external; - function toggleDataURIEnabled() external; + function lockParts() external; - function setBaseURI(string calldata baseURI) external; + function toggleDataURIEnabled() external; - function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory); + function setBaseURI(string calldata baseURI) external; - function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory); + function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory); - function genericDataURI( - string calldata name, - string calldata description, - INounsSeeder.Seed memory seed - ) external view returns (string memory); + function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory); - function generateSVGImage(INounsSeeder.Seed memory seed) external view returns (string memory); + function genericDataURI( + string calldata name, + string calldata description, + INounsSeeder.Seed memory seed + ) external view returns (string memory); + + function generateSVGImage(INounsSeeder.Seed memory seed) external view returns (string memory); } diff --git a/contract/scripts/deploy_localNouns.ts b/contract/scripts/deploy_localNouns.ts index 59ce8bad..1cd2cbea 100644 --- a/contract/scripts/deploy_localNouns.ts +++ b/contract/scripts/deploy_localNouns.ts @@ -1,5 +1,6 @@ import { ethers, network } from 'hardhat'; import { exec } from 'child_process'; + import { writeFile } from 'fs'; import { addresses } from '../../src/utils/addresses'; @@ -25,7 +26,6 @@ async function main() { const addresses = `export const addresses = {\n` + ` localseeder:"${localseeder.address}",\n` + `}\n`; await writeFile(`../src/utils/addresses/localseeder_${network.name}.ts`, addresses, () => { }); - const factoryLocalNounsDescriptor = await ethers.getContractFactory('LocalNounsDescriptor', { libraries: { NFTDescriptor: nftDescriptor, @@ -41,7 +41,6 @@ async function main() { const addresses2 = `export const addresses = {\n` + ` localNounsDescriptor:"${localNounsDescriptor.address}",\n` + `}\n`; await writeFile(`../src/utils/addresses/localNounsDescriptor_${network.name}.ts`, addresses2, () => { }); - const factorySVGStore = await ethers.getContractFactory('LocalNounsProvider'); const provider = await factorySVGStore.deploy(nounsDescriptor, localNounsDescriptor.address, nounsSeeder, localseeder.address); await provider.deployed(); diff --git a/contract/scripts/deploy_nounsDescriptorV1.ts b/contract/scripts/deploy_nounsDescriptorV1.ts index 284ee072..93ef643d 100644 --- a/contract/scripts/deploy_nounsDescriptorV1.ts +++ b/contract/scripts/deploy_nounsDescriptorV1.ts @@ -1,6 +1,7 @@ import { ethers, network } from 'hardhat'; import { exec } from 'child_process'; import addresses from '@nouns/sdk/dist/contract/addresses.json'; + import { writeFile } from 'fs'; // const nftDescriptor: string = network.name == 'goerli' ? addresses[5].nftDescriptor : addresses[1].nftDescriptor; diff --git a/contract/scripts/populate_localNouns.ts b/contract/scripts/populate_localNouns.ts index 307cf715..887f3a76 100644 --- a/contract/scripts/populate_localNouns.ts +++ b/contract/scripts/populate_localNouns.ts @@ -1,5 +1,6 @@ import * as dotenv from "dotenv"; import { ethers, network } from 'hardhat'; + import { addresses } from '../../src/utils/addresses'; const nounsDescriptor = addresses.nounsDescriptor[network.name]; @@ -13,7 +14,6 @@ import { abi as localMinterABI } from "../artifacts/contracts/localNouns/LocalNo dotenv.config(); - const localSeederAddress = addresses.localSeeder[network.name]; const localNounsDescriptorAddress = addresses.localNounsDescriptor[network.name]; const localProviderAddress = addresses.localProvider[network.name]; @@ -32,7 +32,7 @@ async function main() { const localProvider = new ethers.Contract(localProviderAddress, localProviderABI, wallet); const localToken = new ethers.Contract(localTokenAddress, localTokenABI, wallet); const localMinter = new ethers.Contract(localMinterAddress, localMinterABI, wallet); - + if (true) { // set Palette console.log(`set Palette start`); @@ -43,8 +43,10 @@ async function main() { console.log(`set Accessories start`); const accessoryChunk = chunkArrayByPrefectureId(images.accessories); for (const chunk of accessoryChunk) { + const prefectureId = chunk[0].prefectureId; await localNounsDescriptor.addManyAccessories(prefectureId, chunk.map(({ data }) => data), chunk.map(({ filename }) => filename)); + // console.log("chunk:", prefectureId, chunk); } console.log(`set Accessories end`); @@ -53,8 +55,10 @@ async function main() { console.log(`set Heads start`); const headChunk = chunkArrayByPrefectureId(images.heads); for (const chunk of headChunk) { + const prefectureId = chunk[0].prefectureId; await localNounsDescriptor.addManyHeads(prefectureId, chunk.map(({ data }) => data), chunk.map(({ filename }) => filename)); + // console.log("chunk:", prefectureId, chunk); } console.log(`set Heads end`); @@ -88,7 +92,8 @@ main().catch(error => { }); interface ImageData { - prefectureId: string; +prefectureId: string; + filename: string; data: string; } @@ -117,6 +122,7 @@ function chunkArrayByPrefectureId(imagedata: ImageData[]): ImageData[][] { } imagedata[i].filename = name; console.log("imagedata[i].filename", imagedata[i].filename); + if (!map.has(id)) { map.set(id, []); } diff --git a/contract/scripts/populate_nounsV1.ts b/contract/scripts/populate_nounsV1.ts index 2124e07e..dca19ab6 100644 --- a/contract/scripts/populate_nounsV1.ts +++ b/contract/scripts/populate_nounsV1.ts @@ -4,6 +4,7 @@ import { ethers, network } from 'hardhat'; import { images, palette, bgcolors } from "../test/image-original-nouns-data"; // import { abi as nounsDescriptorABI } from "../artifacts/contracts/localNouns/LocalNounsDescriptor.sol/LocalNounsDescriptor"; import { abi as nounsDescriptorABI } from "../artifacts/contracts/external/nouns/NounsDescripter.sol/NounsDescriptor"; + import { addresses } from '../../src/utils/addresses'; dotenv.config(); @@ -17,6 +18,7 @@ async function main() { } else { privateKey = process.env.PRIVATE_KEY !== undefined ? process.env.PRIVATE_KEY : ''; } + const wallet = new ethers.Wallet(privateKey, ethers.provider); // const [wallet] = await ethers.getSigners(); // localhost @@ -30,26 +32,33 @@ async function main() { console.log(`set Palette start`); await nounsDescriptor.addManyColorsToPalette(0, palette, { gasPrice: feeData.gasPrice }); + console.log(`set Palette end`); console.log(`set Accessories start`); const accessoryChunk = chunkArray(images.accessories, 10); for (const chunk of accessoryChunk) { + await nounsDescriptor.addManyAccessories(chunk.map(({ data }) => data), { gasPrice: feeData.gasPrice }); + } console.log(`set Accessories end`); console.log(`set Bodies start`); const bodiesChunk = chunkArray(images.bodies, 10); for (const chunk of bodiesChunk) { + await nounsDescriptor.addManyBodies(chunk.map(({ data }) => data), { gasPrice: feeData.gasPrice }); + } console.log(`set Bodies end`); console.log(`set heads start`); + const headChunk = chunkArray(images.heads, 5); for (const chunk of headChunk) { await nounsDescriptor.addManyHeads(chunk.map(({ data }) => data), { gasPrice: feeData.gasPrice }); + } console.log(`set heads end`); @@ -61,6 +70,7 @@ async function main() { console.log(`set glasses end`); console.log(`set backgrounds start`); + await nounsDescriptor.addManyBackgrounds(bgcolors, { gasPrice: feeData.gasPrice }); console.log(`set backgrounds end`); diff --git a/contract/test/image-local-data.json b/contract/test/image-local-data.json index 36296273..4f374a26 100644 --- a/contract/test/image-local-data.json +++ b/contract/test/image-local-data.json @@ -1462,4 +1462,4 @@ } ] } -} \ No newline at end of file +} diff --git a/contract/test/localNouns.ts b/contract/test/localNouns.ts index 98d5e631..6052aeb0 100644 --- a/contract/test/localNouns.ts +++ b/contract/test/localNouns.ts @@ -64,7 +64,10 @@ describe('mint functions', function () { .revertedWith('Cannot use this function'); await expect(token.connect(user1).functions.mintSelectedPrefecture(user1.address, 1, 1)) - .revertedWith('Sender is not the minter'); + .revertedWith('Sender is not minter nor owner'); + + await expect(token.connect(user1).functions.ownerMint([user1.address], [1], [1])) + .revertedWith('Ownable: caller is not the owner'); }); @@ -93,7 +96,7 @@ describe('mint functions', function () { it('mint from minter', async function () { const txParams = { value: ethers.utils.parseUnits("0.001", "ether") }; - await minter.connect(user1).functions.mintSelectedPrefecture(0, 1,txParams); + await minter.connect(user1).functions.mintSelectedPrefecture(0, 1, txParams); const [balance] = await token.functions.balanceOf(user1.address); expect(balance.toNumber()).to.equal(1); // user1は1つ保持 @@ -105,7 +108,7 @@ describe('mint functions', function () { expect(totalSupply.toNumber()).to.equal(1); // tokenId=1 const [traits1] = await provider.functions.generateTraits(0); - console.log('mint from minter',traits1); + console.log('mint from minter', traits1); }); @@ -137,9 +140,9 @@ describe('mint functions', function () { const [traits2] = await provider.functions.generateTraits(2); const [traits3] = await provider.functions.generateTraits(3); // head,accessoryがランダムなので県のみチェック(head,accessoryは目視) - console.log('multiple mint',traits1); - console.log('multiple mint',traits2); - console.log('multiple mint',traits3); + console.log('multiple mint', traits1); + console.log('multiple mint', traits2); + console.log('multiple mint', traits3); expect(traits1.includes('{"trait_type": "prefecture" , "value":"Toyama"}')).to.equal(true); expect(traits2.includes('{"trait_type": "prefecture" , "value":"Toyama"}')).to.equal(true); expect(traits3.includes('{"trait_type": "prefecture" , "value":"Toyama"}')).to.equal(true); @@ -150,6 +153,29 @@ describe('mint functions', function () { }); + it('owner mint', async function () { + + const [balance3] = await token.functions.balanceOf(user3.address); + const [balance4] = await token.functions.balanceOf(user4.address); + const [balance5] = await token.functions.balanceOf(user5.address); + const [totalSupply] = await token.functions.totalSupply(); + + const txParams = { value: 0 }; + await token.connect(owner).functions.ownerMint([user3.address, user4.address, user5.address], [3, 5, 0], [1, 2, 20], txParams); + + const [balance3a] = await token.functions.balanceOf(user3.address); + const [balance4a] = await token.functions.balanceOf(user4.address); + const [balance5a] = await token.functions.balanceOf(user5.address); + + expect(balance3a.toNumber()).to.equal(balance3.toNumber() + 1); + expect(balance4a.toNumber()).to.equal(balance4.toNumber() + 2); + expect(balance5a.toNumber()).to.equal(balance5.toNumber() + 20); + + const [totalSupplya] = await token.functions.totalSupply(); + expect(totalSupplya.toNumber()).to.equal(totalSupply.toNumber() + 23); + + }); + it('tokenGate', async function () { await minter.connect(owner).functions.setPhase(1); @@ -192,6 +218,28 @@ describe('mint functions', function () { .revertedWith('Must send the mint price'); }); + +}); + +describe('determinePrefectureId', function () { + it('determinePrefectureId', async function () { + + await provider.connect(owner).functions.setRandomValueForTest(true); + let prefectureCount = new Array(47).fill(0); + + for (var i = 0; i < 300; i++) { + const [prefectureId] = await provider.connect(owner).functions.determinePrefectureId(i); + prefectureCount[prefectureId.toNumber() - 1]++; + } + + // 全ての都道府県が1以上出現する + for (var i = 0; i < prefectureCount.length; i++) { + expect(prefectureCount[i]).to.greaterThan(0); + // console.log("prefectureId", i, prefectureCount[i]); + } + + await provider.connect(owner).functions.setRandomValueForTest(false); + }); }); describe('P2P', function () { @@ -214,20 +262,21 @@ describe('P2P', function () { // mintMaxに現在の発行数+1をセット const [totalSupply] = await token.functions.totalSupply(); - await minter.functions.setMintMax(totalSupply.toNumber()+1); + await minter.functions.setMintMax(totalSupply.toNumber() + 1); const [mintMax] = await minter.functions.mintMax(); - expect(mintMax.toNumber()).to.equal(totalSupply.toNumber()+1); + expect(mintMax.toNumber()).to.equal(totalSupply.toNumber() + 1); const txParams = { value: ethers.utils.parseUnits("0.006", "ether") }; await expect(minter.connect(user5).functions.mintSelectedPrefecture(47, 2, txParams)) .revertedWith('Over the mint limit'); // 一つだけならOK + const [balance] = await token.functions.balanceOf(user5.address); const txParams2 = { value: ethers.utils.parseUnits("0.003", "ether") }; - await minter.connect(user5).functions.mintSelectedPrefecture(47, 1,txParams2); + await minter.connect(user5).functions.mintSelectedPrefecture(47, 1, txParams2); - const [balance] = await token.functions.balanceOf(user5.address); - expect(balance.toNumber()).to.equal(1); // user1は1つ保持 + const [balancea] = await token.functions.balanceOf(user5.address); + expect(balancea.toNumber()).to.equal(balance.toNumber() + 1); // user1は1つ保持 await minter.functions.setMintMax(1500); const [mintMax2] = await minter.functions.mintMax(); diff --git a/src/utils/addresses.ts b/src/utils/addresses.ts index 345e2521..71dbd538 100644 --- a/src/utils/addresses.ts +++ b/src/utils/addresses.ts @@ -110,6 +110,7 @@ export const addresses: Addresses = { }, messageSplatter: { goerli: message_splatter_goerli.messageSplatterToken, + }, messageStore: { localhost: messagestore2_localhost.messageStore, @@ -125,6 +126,7 @@ export const addresses: Addresses = { localhost: messagetoken_localhost.messageToken, goerli: messagetoken_goerli.messageToken, mumbai: messagetoken_mumbai.messageToken, + }, svgHelper: { goerli: splatter_goerli.svgHelperAddress,