diff --git a/contract/contracts/ISVGTokenV1.sol b/contract/contracts/ISVGTokenV1.sol new file mode 100644 index 00000000..d2963d38 --- /dev/null +++ b/contract/contracts/ISVGTokenV1.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import './imageParts/interfaces/ISVGStoreV1.sol'; +import './providers/SVGImage1Provider.sol'; + + +interface ISVGTokenV1 { + struct ContractInfo { + IAssetProvider assetProvider; + ISVGStoreV1 svgStore; + uint256 assetId; + address owner; + } + function getContractInfo(uint256 _tokenId) external returns (ContractInfo memory); +} diff --git a/contract/contracts/SVGTokenV1.sol b/contract/contracts/SVGTokenV1.sol index ff742ece..c21d31e1 100644 --- a/contract/contracts/SVGTokenV1.sol +++ b/contract/contracts/SVGTokenV1.sol @@ -9,9 +9,10 @@ pragma solidity ^0.8.6; import '@openzeppelin/contracts/utils/Strings.sol'; import './libs/ProviderToken4.sol'; import './imageParts/interfaces/ISVGStoreV1.sol'; -import './providers/SVGImage1Provider.sol'; +// import './providers/SVGImage1Provider.sol'; +import './ISVGTokenV1.sol'; -contract SVGTokenV1 is ProviderToken4 { +contract SVGTokenV1 is ProviderToken4, ISVGTokenV1 { using Strings for uint256; ISVGStoreV1 public immutable svgStoreV1; @@ -40,6 +41,15 @@ contract SVGTokenV1 is ProviderToken4 { assetIds[tokenId] = assetId; } + function getContractInfo(uint256 _tokenId) external view returns (ISVGTokenV1.ContractInfo memory) { + ISVGTokenV1.ContractInfo memory ret = ISVGTokenV1.ContractInfo({ + assetProvider: assetProvider, + svgStore: svgStoreV1, + assetId: assetIds[_tokenId], + owner: ownerOf(_tokenId) + }); + return ret; + } function tokenURI(uint256 _tokenId) public view override returns (string memory) { uint256 assetId = assetIds[_tokenId]; require(_exists(_tokenId), 'SVGToken.tokenURI: nonexistent token'); diff --git a/contract/contracts/SimpleToken.sol b/contract/contracts/SimpleToken.sol new file mode 100644 index 00000000..0c914edb --- /dev/null +++ b/contract/contracts/SimpleToken.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT + +/** + * This is a part of an effort to update ERC271 so that the sales transaction + * becomes decentralized and trustless, which makes it possible to enforce + * royalities without relying on marketplaces. + * + * Please see "https://hackmd.io/@snakajima/BJqG3fkSo" for details. + * + * Created by Satoshi Nakajima (@snakajima) + */ + +pragma solidity ^0.8.6; + +import './packages/ERC721P2P/ERC721AP2P.sol'; +import './packages/ERC721P2P/erc721a/IERC721A.sol'; + +contract SimpleToken is ERC721AP2P { + uint public nextTokenId; + uint constant mintLimit = 100; + IERC721A private immutable baseToken; + uint256 private immutable baseAssetId; + + constructor(IERC721A _baseToken, uint256 assetId) ERC721A('sample', 'SAMPLE') { + baseToken = _baseToken; + baseAssetId = assetId; + } + + function _processRoyalty(uint _salesPrice, uint) internal override returns (uint256 royalty) { + royalty = (_salesPrice * 50) / 1000; // 5.0% + // artist.transfer(royalty); + } + + function mint() public payable virtual returns (uint256 tokenId) { + require(nextTokenId < mintLimit, 'Sold out'); + tokenId = nextTokenId++; + _safeMint(msg.sender, 1); + } + function tokenURI(uint256 _tokenId) public view override returns (string memory) { + return baseToken.tokenURI(baseAssetId); + } + + // Helper method for test script + function etherBalanceOf(address _wallet) public view returns (uint256) { + return _wallet.balance; + } +} diff --git a/contract/contracts/factories/TokenFactory.sol b/contract/contracts/factories/TokenFactory.sol new file mode 100644 index 00000000..4c34cbc5 --- /dev/null +++ b/contract/contracts/factories/TokenFactory.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +/* + * Created by Isamu Arimoto (@isamua) + */ + +pragma solidity ^0.8.6; + +// import "./packages/ERC721P2P/IERC721P2P.sol"; +import "../SVGTokenV1.sol"; +import "../ISVGTokenV1.sol"; + +// import "./packages/ERC721P2P/SampleAP2PToken.sol"; + +contract TokenFactory { + ISVGTokenV1 public immutable token; + constructor(ISVGTokenV1 _token) { + token = _token; + } + function forkContract() public returns ( + IAssetProvider _assetProvider, + ISVGStoreV1 _svgStore + ) { + ISVGTokenV1.ContractInfo memory info = token.getContractInfo(0); + new SVGTokenV1(info.assetProvider, info.svgStore); + } + +} diff --git a/contract/contracts/factories/TokenFactory2.sol b/contract/contracts/factories/TokenFactory2.sol new file mode 100644 index 00000000..cb69b8c8 --- /dev/null +++ b/contract/contracts/factories/TokenFactory2.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT + +/* + * Created by Isamu Arimoto (@isamua) + */ + +pragma solidity ^0.8.6; + +import "../packages/ERC721P2P/IERC721P2P.sol"; + +import "../SimpleToken.sol"; + +contract TokenFactory2 { + IERC721A private immutable baseToken; + + mapping(uint256 => ERC721AP2P) tokens; // tokenId => token + + constructor(IERC721A _token) { + baseToken = _token; + } + function forkContract(uint256 assetId) public returns (ERC721AP2P _token){ + _token = new SimpleToken(baseToken, assetId); + tokens[assetId] = _token; + } + +} diff --git a/contract/test/copy.ts b/contract/test/copy.ts new file mode 100644 index 00000000..cb1078cd --- /dev/null +++ b/contract/test/copy.ts @@ -0,0 +1,77 @@ +import { expect } from 'chai'; +import { ethers, SignerWithAddress, Contract } from 'hardhat'; + +let store: Contract, provider: Contract, token: Contract, tokenFactory: Contract, tokenFactory2: Contract, token3: Contract; +let balanceO, balanceA, balance1, balance2, balance3; + +const data = { + paths: [ + '0x4d50bc270673f754f4f56427fe54c6fe54c663500000554e0d557c0c05734e45fb4f45ea05358a0835610435bdfe34af6350000045a1fa447efb04739d54029954016350000045bd6445ac8005530955fb0a650d63500000551b14554b1f057346550f4b550f1845f91c45ed5a00', + ], + fills: ['pink'], + strokes: [0], + matrixes: [''], +}; + +before(async () => { + + const factoryStore = await ethers.getContractFactory('SVGStoreV1'); + store = await factoryStore.deploy(); + + const factoryProvider = await ethers.getContractFactory('SVGImage1Provider'); + provider = await factoryProvider.deploy(store.address); + + const factoryToken = await ethers.getContractFactory('SVGTokenV1'); + token = await factoryToken.deploy(provider.address, store.address); + + await token.deployed(); + + const tx = await token.mintWithAsset(data); + await tx.wait(); +/* + const factoryCopy = await ethers.getContractFactory('TokenFactory'); + tokenFactory = await factoryCopy.deploy(token.address); + await tokenFactory.deployed(); +*/ + const factoryCopy2 = await ethers.getContractFactory('TokenFactory2'); + tokenFactory2 = await factoryCopy2.deploy(token.address); + await tokenFactory2.deployed(); + +}); + +describe('Copy', function () { + it('TokenFactory', async function () { + // just copy SVGTokenV1 + /* + const tx = await tokenFactory.forkContract(0); + const ret = await tx.wait(); + await tx2.wait(); + + console.log(hoge); + console.log(hoge.assetProvider); + console.log(hoge.assetId); + */ + }); + + it('TokenFactory2', async function () { + // copy new simple token + const tx = await tokenFactory2.forkContract(0); + const ret = await tx.wait(); + console.log(ret.events); + const addr = await tokenFactory2.getTokenAddress(0); + console.log(addr); + + + const simpletoken_abi = require("../artifacts/contracts/SimpleToken.sol/SimpleToken.json"); + + const [owner] = await ethers.getSigners(); + const simpletoken = new ethers.Contract(addr, simpletoken_abi.abi, owner); + + await simpletoken.mint(); + const token = await simpletoken.tokenURI(0); + console.log(token); + // console.log(hoge.assetProvider); + // console.log(hoge.assetId); + }); + +});