Skip to content

Commit

Permalink
Cairo: Add ERC1155 (#351)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericglau authored Apr 3, 2024
1 parent 56dbddf commit 8d9189d
Show file tree
Hide file tree
Showing 25 changed files with 1,725 additions and 132 deletions.
8 changes: 8 additions & 0 deletions packages/core-cairo/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.10.2 (2024-04-03)

- Use OpenZeppelin Contracts for Cairo v0.11.0. ([#351](https://github.com/OpenZeppelin/contracts-wizard/pull/351))
- Add ERC1155.
- Remove redundant not paused assertions for camel case functions.
- Fix use of ERC20 mixin.
- Sort imports alphabetically.

## 0.10.1 (2024-03-27)

- Use mixins. ([#348](https://github.com/OpenZeppelin/contracts-wizard/pull/348))
Expand Down
11 changes: 0 additions & 11 deletions packages/core-cairo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,6 @@ Calculates the initial supply that would be used in an ERC20 contract based on a
Returns `premint` with zeros padded or removed based on `decimals`.
Throws an error if `premint` has more than one decimal character or is more precise than allowed by the `decimals` argument.

### Utility functions

#### `utils.toUint256`

Returns Uint256 components for low and high bits based on a given number in string format.

- `num` Number in string format

Returns an object with lowBits and highBits.
Throws an error if the provided number is larger than 256 bits.

### Examples

Import the contract type(s) or function categories (for example, `erc20` or `utils`) that you want to use from the `@openzeppelin/wizard-cairo` package:
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.10.1",
"version": "0.10.2",
"description": "A boilerplate generator to get started with OpenZeppelin Contracts for Cairo",
"license": "MIT",
"repository": "github:OpenZeppelin/contracts-wizard",
Expand Down
7 changes: 7 additions & 0 deletions packages/core-cairo/src/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { CommonOptions } from './common-options';
import { printERC20, defaults as erc20defaults, isAccessControlRequired as erc20IsAccessControlRequired, ERC20Options } from './erc20';
import { printERC721, defaults as erc721defaults, isAccessControlRequired as erc721IsAccessControlRequired, ERC721Options } from './erc721';
import { printERC1155, defaults as erc1155defaults, isAccessControlRequired as erc1155IsAccessControlRequired, ERC1155Options } from './erc1155';
import { printCustom, defaults as customDefaults, isAccessControlRequired as customIsAccessControlRequired, CustomOptions } from './custom';

export interface WizardContractAPI<Options extends CommonOptions> {
Expand All @@ -23,6 +24,7 @@ export interface WizardContractAPI<Options extends CommonOptions> {

export type ERC20 = WizardContractAPI<ERC20Options>;
export type ERC721 = WizardContractAPI<ERC721Options>;
export type ERC1155 = WizardContractAPI<ERC1155Options>;
export type Custom = WizardContractAPI<CustomOptions>;

export const erc20: ERC20 = {
Expand All @@ -35,6 +37,11 @@ export const erc721: ERC721 = {
defaults: erc721defaults,
isAccessControlRequired: erc721IsAccessControlRequired
}
export const erc1155: ERC1155 = {
print: printERC1155,
defaults: erc1155defaults,
isAccessControlRequired: erc1155IsAccessControlRequired
}
export const custom: Custom = {
print: printCustom,
defaults: customDefaults,
Expand Down
5 changes: 5 additions & 0 deletions packages/core-cairo/src/build-generic.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { ERC20Options, buildERC20 } from './erc20';
import { ERC721Options, buildERC721 } from './erc721';
import { ERC1155Options, buildERC1155 } from './erc1155';
import { CustomOptions, buildCustom } from './custom';

export interface KindedOptions {
ERC20: { kind: 'ERC20' } & ERC20Options;
ERC721: { kind: 'ERC721' } & ERC721Options;
ERC1155: { kind: 'ERC1155' } & ERC1155Options;
Custom: { kind: 'Custom' } & CustomOptions;
}

Expand All @@ -18,6 +20,9 @@ export function buildGeneric(opts: GenericOptions) {
case 'ERC721':
return buildERC721(opts);

case 'ERC1155':
return buildERC1155(opts);

case 'Custom':
return buildCustom(opts);

Expand Down
16 changes: 8 additions & 8 deletions packages/core-cairo/src/contract.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod Foo {␊
Expand All @@ -24,7 +24,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod Foo {␊
Expand All @@ -44,7 +44,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod Foo {␊
Expand All @@ -64,7 +64,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod Foo {␊
Expand All @@ -89,7 +89,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod Foo {␊
Expand All @@ -114,7 +114,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod Foo {␊
Expand Down Expand Up @@ -152,12 +152,12 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod Foo {␊
use some::path::FooComponent;␊
use some::library::SomeLibrary;␊
use some::path::FooComponent;␊
component!(path: FooComponent, storage: foo, event: FooEvent);␊
Expand Down
Binary file modified packages/core-cairo/src/contract.test.ts.snap
Binary file not shown.
22 changes: 11 additions & 11 deletions packages/core-cairo/src/custom.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod MyContract {␊
Expand All @@ -24,12 +24,12 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod MyContract {␊
use openzeppelin::security::pausable::PausableComponent;␊
use openzeppelin::access::ownable::OwnableComponent;␊
use openzeppelin::security::pausable::PausableComponent;␊
use starknet::ContractAddress;␊
component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊
Expand Down Expand Up @@ -88,12 +88,12 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod MyContract {␊
use openzeppelin::upgrades::UpgradeableComponent;␊
use openzeppelin::access::ownable::OwnableComponent;␊
use openzeppelin::upgrades::UpgradeableComponent;␊
use openzeppelin::upgrades::interface::IUpgradeable;␊
use starknet::ClassHash;␊
use starknet::ContractAddress;␊
Expand Down Expand Up @@ -144,7 +144,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod MyContract {␊
Expand All @@ -159,7 +159,7 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod MyContract {␊
Expand Down Expand Up @@ -198,13 +198,13 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod MyContract {␊
use openzeppelin::access::accesscontrol::AccessControlComponent;␊
use openzeppelin::introspection::src5::SRC5Component;␊
use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;␊
use openzeppelin::introspection::src5::SRC5Component;␊
use starknet::ContractAddress;␊
component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊
Expand Down Expand Up @@ -246,12 +246,12 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊
// Compatible with OpenZeppelin Contracts for Cairo ^0.11.0␊
#[starknet::contract]␊
mod MyContract {␊
use openzeppelin::security::pausable::PausableComponent;␊
use openzeppelin::access::ownable::OwnableComponent;␊
use openzeppelin::security::pausable::PausableComponent;␊
use starknet::ContractAddress;␊
component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊
Expand Down
Binary file modified packages/core-cairo/src/custom.test.ts.snap
Binary file not shown.
91 changes: 91 additions & 0 deletions packages/core-cairo/src/erc1155.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import test from 'ava';
import { erc1155 } from '.';

import { buildERC1155, ERC1155Options } from './erc1155';
import { printContract } from './print';

function testERC1155(title: string, opts: Partial<ERC1155Options>) {
test(title, t => {
const c = buildERC1155({
name: 'MyToken',
baseUri: 'https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/',
...opts,
});
t.snapshot(printContract(c));
});
}

/**
* Tests external API for equivalence with internal API
*/
function testAPIEquivalence(title: string, opts?: ERC1155Options) {
test(title, t => {
t.is(erc1155.print(opts), printContract(buildERC1155({
name: 'MyToken',
baseUri: '',
...opts,
})));
});
}

testERC1155('basic', {});

testERC1155('basic + roles', {
access: 'roles',
});

testERC1155('no updatable uri', {
updatableUri: false,
});

testERC1155('burnable', {
burnable: true,
});

testERC1155('pausable', {
pausable: true,
});

testERC1155('mintable', {
mintable: true,
});

testERC1155('mintable + roles', {
mintable: true,
access: 'roles',
});

testERC1155('full upgradeable', {
mintable: true,
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 full upgradeable', {
name: 'CustomToken',
baseUri: 'https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/',
mintable: true,
access: 'roles',
burnable: true,
pausable: true,
upgradeable: true,
});

test('API assert defaults', async t => {
t.is(erc1155.print(erc1155.defaults), erc1155.print());
});

test('API isAccessControlRequired', async t => {
t.is(erc1155.isAccessControlRequired({ updatableUri: false, mintable: true }), true);
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({}), true); // updatableUri is true by default
});
Loading

0 comments on commit 8d9189d

Please sign in to comment.