Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERC2981 (Royalty Info) for Cairo #413

Merged
merged 35 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d4f6afb
Add functionality for declaring constants within traits
immrsd Oct 1, 2024
42bca98
Specify return types for printing functions, support constants for tr…
immrsd Oct 1, 2024
6af508f
Merge master
immrsd Nov 21, 2024
5df51a2
Support uint Cairo types
immrsd Nov 27, 2024
5e3cf95
Add support for ERC2981 extension
immrsd Nov 27, 2024
168c862
Add RoyaltyInfo for ERC1155
immrsd Nov 27, 2024
3d72bd9
Add RoyaltyInfo for ERC721
immrsd Nov 27, 2024
6155fea
Introduce RoyaltyInfoSection with UI controls
immrsd Nov 27, 2024
6b37bd9
Enable errors proxying to ERC1155 controls
immrsd Nov 27, 2024
0f52a2c
Add RoyaltyInfo section to ERC1155 controls
immrsd Nov 27, 2024
6fee79c
Add RoyaltyInfo section to ERC721 controls
immrsd Nov 27, 2024
b02d19d
Update changelog
immrsd Nov 27, 2024
9219dfd
Fix unnecessary brackets for Cairo constants import
immrsd Nov 27, 2024
83d8017
Make Access control required for RoyaltyInfo
immrsd Nov 27, 2024
8b4037c
Update snapshot for Cairo custom contract tests
immrsd Nov 27, 2024
f424d78
Apply minor fixes
immrsd Nov 27, 2024
310b23f
Add missing semicolons
immrsd Nov 29, 2024
d1b80ce
Rename setRoyaltyInfoIfNeeded to setRoyaltyInfo
immrsd Nov 29, 2024
d5b9830
Sanitize ERC20 premint value
immrsd Nov 29, 2024
30b858d
Add explicit function return types
immrsd Nov 29, 2024
81a51f2
Introduce DEFAULT_ACCESS_CONTROL constant
immrsd Nov 29, 2024
81fc2eb
Remove number check for negative
immrsd Nov 29, 2024
1609800
Fix broken link
immrsd Nov 29, 2024
826ba89
Add multiple Royalty info options for generate-based-testing
immrsd Nov 29, 2024
3fb9051
Bump package version
immrsd Dec 2, 2024
1362b81
Add multiple royalty info testing options
immrsd Dec 2, 2024
d884644
Add royalty info tests for ERC1155
immrsd Dec 2, 2024
63b0105
Add royalty info tests for ERC721
immrsd Dec 2, 2024
73dd5bd
Rename royaltyInfoTestOptions to royaltyInfoOptions
immrsd Dec 2, 2024
46f5cb9
Refactor ERC1155 tests
immrsd Dec 2, 2024
54110a0
Refactor ERC721 tests
immrsd Dec 2, 2024
651d6db
Update ERC1155 test snapshots
immrsd Dec 2, 2024
145f2d8
Update ERC721 test snapshots
immrsd Dec 2, 2024
044c2c7
Remove unused import
immrsd Dec 2, 2024
ff08e5e
Revert "Remove unused import"
immrsd Dec 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/core-cairo/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.19.0 (2024-11-27)

- Add ERC2981 (RoyaltyInfo) for ERC721 and ERC1155 ([#413](https://github.com/OpenZeppelin/contracts-wizard/pull/413))

## 0.18.0 (2024-11-15)

- **Breaking changes**:
Expand Down
2 changes: 1 addition & 1 deletion packages/core-cairo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openzeppelin/wizard-cairo",
"version": "0.18.0",
"version": "0.19.0",
"description": "A boilerplate generator to get started with OpenZeppelin Contracts for Cairo",
"license": "MIT",
"repository": "github:OpenZeppelin/contracts-wizard",
Expand Down
25 changes: 24 additions & 1 deletion packages/core-cairo/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface Contract {
superVariables: Variable[];
}

export type Value = string | number | { lit: string } | { note: string, value: Value };
export type Value = string | number | bigint | { lit: string } | { note: string, value: Value };

export interface Component {
name: string;
Expand Down Expand Up @@ -57,6 +57,7 @@ export interface BaseImplementedTrait {
}

export interface ImplementedTrait extends BaseImplementedTrait {
superVariables: Variable[];
functions: ContractFunction[];
}

Expand Down Expand Up @@ -172,6 +173,7 @@ export class ContractBuilder implements Contract {
name: baseTrait.name,
of: baseTrait.of,
tags: [ ...baseTrait.tags ],
superVariables: [],
functions: [],
priority: baseTrait.priority,
};
Expand All @@ -180,6 +182,27 @@ export class ContractBuilder implements Contract {
}
}

addSuperVariableToTrait(baseTrait: BaseImplementedTrait, newVar: Variable): boolean {
const trait = this.addImplementedTrait(baseTrait);
for (const existingVar of trait.superVariables) {
if (existingVar.name === newVar.name) {
if (existingVar.type !== newVar.type) {
throw new Error(
`Tried to add duplicate super var ${newVar.name} with different type: ${newVar.type} instead of ${existingVar.type}.`
);
}
if (existingVar.value !== newVar.value) {
throw new Error(
`Tried to add duplicate super var ${newVar.name} with different value: ${newVar.value} instead of ${existingVar.value}.`
);
}
return false; // No need to add, already exists
}
}
trait.superVariables.push(newVar);
return true;
}

addFunction(baseTrait: BaseImplementedTrait, fn: BaseFunction): ContractFunction {
const t = this.addImplementedTrait(baseTrait);

Expand Down
2 changes: 1 addition & 1 deletion packages/core-cairo/src/custom.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ Generated by [AVA](https://avajs.dev).
use openzeppelin::upgrades::interface::IUpgradeable;␊
use starknet::ClassHash;␊
use starknet::ContractAddress;␊
use super::{UPGRADER_ROLE};␊
use super::UPGRADER_ROLE;␊
component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊
component!(path: SRC5Component, storage: src5, event: SRC5Event);␊
Expand Down
Binary file modified packages/core-cairo/src/custom.test.ts.snap
Binary file not shown.
67 changes: 50 additions & 17 deletions packages/core-cairo/src/erc1155.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,25 @@ import { erc1155 } from '.';

import { buildERC1155, ERC1155Options } from './erc1155';
import { printContract } from './print';
import { royaltyInfoOptions } from './set-royalty-info';

const NAME = 'MyToken';
const CUSTOM_NAME = 'CustomToken';
const BASE_URI = 'https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/';

const allFeaturesON: Partial<ERC1155Options> = {
mintable: true,
burnable: true,
pausable: true,
royaltyInfo: royaltyInfoOptions.enabledDefault,
upgradeable: true
} as const;

function testERC1155(title: string, opts: Partial<ERC1155Options>) {
test(title, t => {
const c = buildERC1155({
name: 'MyToken',
baseUri: 'https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/',
name: NAME,
baseUri: BASE_URI,
...opts,
});
t.snapshot(printContract(c));
Expand All @@ -18,10 +31,10 @@ function testERC1155(title: string, opts: Partial<ERC1155Options>) {
/**
* Tests external API for equivalence with internal API
*/
function testAPIEquivalence(title: string, opts?: ERC1155Options) {
function testAPIEquivalence(title: string, opts?: ERC1155Options) {
test(title, t => {
t.is(erc1155.print(opts), printContract(buildERC1155({
name: 'MyToken',
name: NAME,
baseUri: '',
...opts,
})));
Expand Down Expand Up @@ -59,33 +72,51 @@ testERC1155('mintable + roles', {
access: 'roles',
});

testERC1155('royalty info disabled', {
royaltyInfo: royaltyInfoOptions.disabled
});

testERC1155('royalty info enabled default + ownable', {
royaltyInfo: royaltyInfoOptions.enabledDefault,
access: 'ownable'
});

testERC1155('royalty info enabled default + roles', {
royaltyInfo: royaltyInfoOptions.enabledDefault,
access: 'roles'
});

testERC1155('royalty info enabled custom + ownable', {
royaltyInfo: royaltyInfoOptions.enabledCustom,
access: 'ownable'
});

testERC1155('royalty info enabled custom + roles', {
royaltyInfo: royaltyInfoOptions.enabledCustom,
access: 'roles'
});

testERC1155('full non-upgradeable', {
mintable: true,
...allFeaturesON,
access: 'roles',
burnable: true,
pausable: true,
upgradeable: false,
});

testERC1155('full upgradeable', {
mintable: true,
...allFeaturesON,
access: 'roles',
burnable: true,
pausable: true,
upgradeable: true,
});

testAPIEquivalence('API default');

testAPIEquivalence('API basic', { name: 'CustomToken', baseUri: 'https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/' });
testAPIEquivalence('API basic', { name: CUSTOM_NAME, baseUri: BASE_URI });

testAPIEquivalence('API full upgradeable', {
name: 'CustomToken',
baseUri: 'https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/',
mintable: true,
...allFeaturesON,
name: CUSTOM_NAME,
baseUri: BASE_URI,
access: 'roles',
burnable: true,
pausable: true,
upgradeable: true,
});

Expand All @@ -98,6 +129,8 @@ test('API isAccessControlRequired', async t => {
t.is(erc1155.isAccessControlRequired({ updatableUri: false, pausable: true }), true);
t.is(erc1155.isAccessControlRequired({ updatableUri: false, upgradeable: true }), true);
t.is(erc1155.isAccessControlRequired({ updatableUri: true }), true);
t.is(erc1155.isAccessControlRequired({ updatableUri: false}), false);
t.is(erc1155.isAccessControlRequired({ royaltyInfo: royaltyInfoOptions.enabledDefault }), true);
t.is(erc1155.isAccessControlRequired({ royaltyInfo: royaltyInfoOptions.enabledCustom }), true);
t.is(erc1155.isAccessControlRequired({ updatableUri: false }), false);
t.is(erc1155.isAccessControlRequired({}), true); // updatableUri is true by default
});
Loading