diff --git a/packages/core/src/erc1155.test.ts b/packages/core/src/erc1155.test.ts index 6cbd5a04..81f5d906 100644 --- a/packages/core/src/erc1155.test.ts +++ b/packages/core/src/erc1155.test.ts @@ -20,6 +20,11 @@ testERC1155('basic + roles', { access: 'roles', }); +testERC1155('royalty', { + royaltyRecipient: '0', + royaltyFraction: '2000', +}); + testERC1155('burnable', { burnable: true, }); diff --git a/packages/core/src/erc1155.test.ts.md b/packages/core/src/erc1155.test.ts.md index 88cba45a..c690687a 100644 --- a/packages/core/src/erc1155.test.ts.md +++ b/packages/core/src/erc1155.test.ts.md @@ -441,3 +441,27 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ` + +## royalty + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + pragma solidity ^0.8.2;␊ + ␊ + import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";␊ + import "@openzeppelin/contracts/access/Ownable.sol";␊ + import "@openzeppelin/contracts/token/ERC721/extensions/ERC1155Royalty.sol";␊ + ␊ + contract MyToken is ERC1155, Ownable, ERC1155Royalty {␊ + constructor()␊ + ERC1155("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/")␊ + {␊ + _setDefaultRoyalty(address(0), 2000);␊ + }␊ + ␊ + function setURI(string memory newuri) public onlyOwner {␊ + _setURI(newuri);␊ + }␊ + }␊ + ` diff --git a/packages/core/src/erc1155.test.ts.snap b/packages/core/src/erc1155.test.ts.snap index 7c8ff32f..467a2e42 100644 Binary files a/packages/core/src/erc1155.test.ts.snap and b/packages/core/src/erc1155.test.ts.snap differ diff --git a/packages/core/src/erc1155.ts b/packages/core/src/erc1155.ts index a24d5c82..37aadb58 100644 --- a/packages/core/src/erc1155.ts +++ b/packages/core/src/erc1155.ts @@ -6,10 +6,13 @@ import { defineFunctions } from './utils/define-functions'; import { CommonOptions, withCommonDefaults } from './common-options'; import { setUpgradeable } from './set-upgradeable'; import { setInfo } from './set-info'; +import { setRoyalty } from './set-royalty'; export interface ERC1155Options extends CommonOptions { name: string; uri: string; + royaltyRecipient?: string; + royaltyFraction?: string; burnable?: boolean; pausable?: boolean; mintable?: boolean; @@ -24,6 +27,18 @@ export function buildERC1155(opts: ERC1155Options): Contract { addBase(c, opts.uri); addSetUri(c, access); + if (opts.royaltyRecipient && opts.royaltyFraction) { + setRoyalty( + c, + { + name: 'ERC1155Royalty', + path: '@openzeppelin/contracts/token/ERC721/extensions/ERC1155Royalty.sol', + }, + opts.royaltyRecipient, + opts.royaltyFraction + ); + } + if (opts.pausable) { addPausable(c, access, [functions._beforeTokenTransfer]); } diff --git a/packages/core/src/erc721.test.ts b/packages/core/src/erc721.test.ts index cd6b1014..ecdac4f2 100644 --- a/packages/core/src/erc721.test.ts +++ b/packages/core/src/erc721.test.ts @@ -20,6 +20,11 @@ testERC721('base uri', { baseUri: 'https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/', }); +testERC721('royalty', { + royaltyRecipient: '0', + royaltyFraction: '2000', +}); + testERC721('enumerable', { enumerable: true, }); diff --git a/packages/core/src/erc721.test.ts.md b/packages/core/src/erc721.test.ts.md index c274a0de..fd43b9b4 100644 --- a/packages/core/src/erc721.test.ts.md +++ b/packages/core/src/erc721.test.ts.md @@ -464,3 +464,20 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ` + +## royalty + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + pragma solidity ^0.8.2;␊ + ␊ + import "@openzeppelin/contracts/token/ERC721/ERC721.sol";␊ + import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol";␊ + ␊ + contract MyToken is ERC721, ERC721Royalty {␊ + constructor() ERC721("MyToken", "MTK") {␊ + _setDefaultRoyalty(address(0), 2000);␊ + }␊ + }␊ + ` diff --git a/packages/core/src/erc721.test.ts.snap b/packages/core/src/erc721.test.ts.snap index 8a024a6c..f96f74da 100644 Binary files a/packages/core/src/erc721.test.ts.snap and b/packages/core/src/erc721.test.ts.snap differ diff --git a/packages/core/src/erc721.ts b/packages/core/src/erc721.ts index 1d254028..a36543c0 100644 --- a/packages/core/src/erc721.ts +++ b/packages/core/src/erc721.ts @@ -6,11 +6,14 @@ import { defineFunctions } from './utils/define-functions'; import { CommonOptions, withCommonDefaults } from './common-options'; import { setUpgradeable } from './set-upgradeable'; import { setInfo } from './set-info'; +import { setRoyalty } from './set-royalty'; export interface ERC721Options extends CommonOptions { name: string; symbol: string; baseUri?: string; + royaltyRecipient?: string; + royaltyFraction?: string; enumerable?: boolean; uriStorage?: boolean; burnable?: boolean; @@ -30,6 +33,18 @@ export function buildERC721(opts: ERC721Options): Contract { addBaseURI(c, opts.baseUri); } + if (opts.royaltyRecipient && opts.royaltyFraction) { + setRoyalty( + c, + { + name: "ERC721Royalty", + path: "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol", + }, + opts.royaltyRecipient, + opts.royaltyFraction + ); + } + if (opts.enumerable) { addEnumerable(c); } diff --git a/packages/core/src/generate/erc1155.ts b/packages/core/src/generate/erc1155.ts index 44d726a8..f117098e 100644 --- a/packages/core/src/generate/erc1155.ts +++ b/packages/core/src/generate/erc1155.ts @@ -9,6 +9,8 @@ const booleans = [true, false]; const blueprint = { name: ['MyToken'], uri: ['https://example.com/'], + royaltyRecipient: ['0'], + royaltyFraction: ['0'], burnable: booleans, pausable: booleans, mintable: booleans, diff --git a/packages/core/src/generate/erc721.ts b/packages/core/src/generate/erc721.ts index 2d60c848..aa7c168b 100644 --- a/packages/core/src/generate/erc721.ts +++ b/packages/core/src/generate/erc721.ts @@ -10,6 +10,8 @@ const blueprint = { name: ['MyToken'], symbol: ['MTK'], baseUri: ['https://example.com/'], + royaltyRecipient: ['0'], + royaltyFraction: ['0'], enumerable: booleans, uriStorage: booleans, burnable: booleans, diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index b944c530..0a5b0f2a 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -20,3 +20,5 @@ export { OptionsError } from './error'; export type { Kind } from './kind'; export { sanitizeKind } from './kind'; + +export { royaltyFractionPattern } from './set-royalty' \ No newline at end of file diff --git a/packages/core/src/set-royalty.ts b/packages/core/src/set-royalty.ts new file mode 100644 index 00000000..e85c79d7 --- /dev/null +++ b/packages/core/src/set-royalty.ts @@ -0,0 +1,12 @@ +import type { ContractBuilder, ParentContract } from './contract'; + +export const royaltyFractionPattern = /^\d+$/; + +export function setRoyalty(c: ContractBuilder, parent: ParentContract, recipient: string, fraction: string) { + if(!royaltyFractionPattern.test(fraction)) { + return; + } + + c.addParent(parent); + c.addConstructorCode(`_setDefaultRoyalty(address(${recipient}), ${fraction});`); +} \ No newline at end of file diff --git a/packages/ui/src/ERC1155Controls.svelte b/packages/ui/src/ERC1155Controls.svelte index b8c09e01..a03fd48f 100644 --- a/packages/ui/src/ERC1155Controls.svelte +++ b/packages/ui/src/ERC1155Controls.svelte @@ -2,7 +2,7 @@ import HelpTooltip from './HelpTooltip.svelte'; import type { KindedOptions } from '@openzeppelin/wizard'; - import { infoDefaults } from '@openzeppelin/wizard'; + import { royaltyFractionPattern, infoDefaults } from '@openzeppelin/wizard'; import AccessControlSection from './AccessControlSection.svelte'; import UpgradeabilitySection from './UpgradeabilitySection.svelte'; @@ -12,6 +12,8 @@ kind: 'ERC1155', name: 'MyToken', uri: '', + royaltyRecipient: '', + royaltyFraction: '', burnable: false, pausable: false, mintable: false, @@ -36,6 +38,20 @@ + +
diff --git a/packages/ui/src/ERC721Controls.svelte b/packages/ui/src/ERC721Controls.svelte index d34536e7..7eb69902 100644 --- a/packages/ui/src/ERC721Controls.svelte +++ b/packages/ui/src/ERC721Controls.svelte @@ -2,7 +2,7 @@ import HelpTooltip from './HelpTooltip.svelte'; import type { KindedOptions } from '@openzeppelin/wizard'; - import { infoDefaults } from '@openzeppelin/wizard'; + import { royaltyFractionPattern, infoDefaults } from '@openzeppelin/wizard'; import AccessControlSection from './AccessControlSection.svelte'; import UpgradeabilitySection from './UpgradeabilitySection.svelte'; @@ -14,6 +14,8 @@ name: 'MyToken', symbol: 'MTK', baseUri: '', + royaltyRecipient: '', + royaltyFraction: '', enumerable: false, uriStorage: false, burnable: false, @@ -62,6 +64,20 @@ + +