Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
bf5fc34
Update lockfile
renovate[bot] Nov 1, 2024
52e1bbe
Add stablecoin section and community repo
cairoeth Nov 4, 2024
63c23db
Add real world assets and update stablecoin
cairoeth Nov 4, 2024
e5be59f
Add limitations section
cairoeth Nov 4, 2024
15e990f
Add limitations build
cairoeth Nov 4, 2024
8ffb9a5
Add custodian feature
cairoeth Nov 5, 2024
a4c79da
Remove upgradeability on stablecoin
cairoeth Nov 5, 2024
4b42090
Add tests
cairoeth Nov 5, 2024
ed2f32c
Update tests
cairoeth Nov 5, 2024
2bd2b3f
Use repo dependency
cairoeth Nov 7, 2024
5bef7c5
Improve access managed custodian
cairoeth Nov 8, 2024
2e4bb09
Update limitation options
cairoeth Nov 14, 2024
cdd5198
Add experimental note
cairoeth Nov 14, 2024
7d26a46
Update stablecoin.ts
cairoeth Nov 14, 2024
2cd81ec
Fix default
cairoeth Nov 14, 2024
6ae0d65
Simplify
cairoeth Nov 14, 2024
54129d3
Merge remote-tracking branch 'upstream/renovate/lock-file-maintenance…
cairoeth Nov 14, 2024
63457fd
Revert "Merge remote-tracking branch 'upstream/renovate/lock-file-mai…
cairoeth Nov 14, 2024
a8ab856
Community dependency
cairoeth Nov 14, 2024
edc3bd9
Fix Real-World Assets tab, disable Remix and download packages
ericglau Nov 14, 2024
b43be4d
Add experimental notice
cairoeth Nov 18, 2024
71af676
Rename to `Real-World Asset`
cairoeth Nov 18, 2024
630b535
Update default RWA name and symbol
cairoeth Nov 18, 2024
b8ba6c0
Add asterisks
cairoeth Nov 18, 2024
9343183
Add asterisks on tabs
cairoeth Nov 18, 2024
aae71ba
Add changelog, bump version
ericglau Nov 18, 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
5 changes: 5 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 0.4.5 (2024-11-18)

- Add `stablecoin` and `realWorldAsset` contract types. ([#404](https://github.com/OpenZeppelin/contracts-wizard/pull/404))
**Note:** `stablecoin` and `realWorldAsset` are experimental and may be subject to change.

## 0.4.4 (2024-10-23)

### Potentially breaking changes
Expand Down
13 changes: 13 additions & 0 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ The following contract types are supported:
- `erc20`
- `erc721`
- `erc1155`
- `stablecoin`
- `realWorldAsset`
- `governor`
- `custom`

Note that `stablecoin` and `realWorldAsset` are experimental and may be subject to change.

Each contract type has functions/constants as defined below.

### Functions
Expand All @@ -34,6 +38,9 @@ function print(opts?: ERC721Options): string
function print(opts?: ERC1155Options): string
```
```js
function print(opts?: StablecoinOptions): string
```
```js
function print(opts?: GovernorOptions): string
```
```js
Expand All @@ -52,6 +59,9 @@ const defaults: Required<ERC721Options>
const defaults: Required<ERC1155Options>
```
```js
const defaults: Required<StablecoinOptions>
```
```js
const defaults: Required<GovernorOptions>
```
```js
Expand All @@ -70,6 +80,9 @@ function isAccessControlRequired(opts: Partial<ERC721Options>): boolean
function isAccessControlRequired(opts: Partial<ERC1155Options>): boolean
```
```js
function isAccessControlRequired(opts: Partial<StablecoinOptions>): boolean
```
```js
function isAccessControlRequired(opts: Partial<GovernorOptions>): boolean
```
```js
Expand Down
3 changes: 2 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openzeppelin/wizard",
"version": "0.4.4",
"version": "0.4.5",
"description": "A boilerplate generator to get started with OpenZeppelin Contracts",
"license": "MIT",
"repository": "github:OpenZeppelin/contracts-wizard",
Expand All @@ -20,6 +20,7 @@
"update-env": "rm ./src/environments/hardhat/package-lock.json && npm install --package-lock-only --prefix ./src/environments/hardhat && rm ./src/environments/hardhat/upgradeable/package-lock.json && npm install --package-lock-only --prefix ./src/environments/hardhat/upgradeable"
},
"devDependencies": {
"@openzeppelin/community-contracts": "https://github.com/OpenZeppelin/openzeppelin-community-contracts",
"@openzeppelin/contracts": "^5.1.0",
"@openzeppelin/contracts-upgradeable": "^5.1.0",
"@types/node": "^18.0.0",
Expand Down
13 changes: 13 additions & 0 deletions packages/core/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,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 { printStablecoin, defaults as stablecoinDefaults, isAccessControlRequired as stablecoinIsAccessControlRequired, StablecoinOptions } from './stablecoin';
import { printGovernor, defaults as governorDefaults, isAccessControlRequired as governorIsAccessControlRequired, GovernorOptions } from './governor';
import { printCustom, defaults as customDefaults, isAccessControlRequired as customIsAccessControlRequired, CustomOptions } from './custom';

Expand All @@ -26,6 +27,8 @@ export interface WizardContractAPI<Options extends CommonOptions> {
export type ERC20 = WizardContractAPI<ERC20Options>;
export type ERC721 = WizardContractAPI<ERC721Options>;
export type ERC1155 = WizardContractAPI<ERC1155Options>;
export type Stablecoin = WizardContractAPI<StablecoinOptions>;
export type RealWorldAsset = WizardContractAPI<StablecoinOptions>;
export type Governor = WizardContractAPI<GovernorOptions>;
export type Custom = WizardContractAPI<CustomOptions>;

Expand All @@ -44,6 +47,16 @@ export const erc1155: ERC1155 = {
defaults: erc1155defaults,
isAccessControlRequired: erc1155IsAccessControlRequired
}
export const stablecoin: Stablecoin = {
print: printStablecoin,
defaults: stablecoinDefaults,
isAccessControlRequired: stablecoinIsAccessControlRequired
}
export const realWorldAsset: RealWorldAsset = {
print: printStablecoin,
defaults: stablecoinDefaults,
isAccessControlRequired: stablecoinIsAccessControlRequired
}
export const governor: Governor = {
print: printGovernor,
defaults: governorDefaults,
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/build-generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { CustomOptions, buildCustom } from './custom';
import { ERC20Options, buildERC20 } from './erc20';
import { ERC721Options, buildERC721 } from './erc721';
import { ERC1155Options, buildERC1155 } from './erc1155';
import { StablecoinOptions, buildStablecoin } from './stablecoin';
import { GovernorOptions, buildGovernor } from './governor';

export interface KindedOptions {
ERC20: { kind: 'ERC20' } & ERC20Options;
ERC721: { kind: 'ERC721' } & ERC721Options;
ERC1155: { kind: 'ERC1155' } & ERC1155Options;
Stablecoin: { kind: 'Stablecoin' } & StablecoinOptions;
RealWorldAsset: { kind: 'RealWorldAsset' } & StablecoinOptions;
Governor: { kind: 'Governor' } & GovernorOptions;
Custom: { kind: 'Custom' } & CustomOptions;
}
Expand All @@ -25,6 +28,12 @@ export function buildGeneric(opts: GenericOptions) {
case 'ERC1155':
return buildERC1155(opts);

case 'Stablecoin':
return buildStablecoin(opts);

case 'RealWorldAsset':
return buildStablecoin(opts);

case 'Governor':
return buildGovernor(opts);

Expand Down
13 changes: 13 additions & 0 deletions packages/core/src/generate/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import crypto from 'crypto';
import { generateERC20Options } from './erc20';
import { generateERC721Options } from './erc721';
import { generateERC1155Options } from './erc1155';
import { generateStablecoinOptions } from './stablecoin';
import { generateGovernorOptions } from './governor';
import { generateCustomOptions } from './custom';
import { buildGeneric, GenericOptions, KindedOptions } from '../build-generic';
Expand Down Expand Up @@ -36,6 +37,18 @@ export function* generateOptions(kind?: Kind): Generator<GenericOptions> {
}
}

if (!kind || kind === 'Stablecoin') {
for (const kindOpts of generateStablecoinOptions()) {
yield { kind: 'Stablecoin', ...kindOpts };
}
}

if (!kind || kind === 'RealWorldAsset') {
for (const kindOpts of generateStablecoinOptions()) {
yield { kind: 'RealWorldAsset', ...kindOpts };
}
}

if (!kind || kind === 'Governor') {
for (const kindOpts of generateGovernorOptions()) {
yield { kind: 'Governor', ...kindOpts };
Expand Down
31 changes: 31 additions & 0 deletions packages/core/src/generate/stablecoin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { StablecoinOptions } from '../stablecoin';
import { accessOptions } from '../set-access-control';
import { clockModeOptions } from '../set-clock-mode';
import { infoOptions } from '../set-info';
import { upgradeableOptions } from '../set-upgradeable';
import { generateAlternatives } from './alternatives';

const booleans = [true, false];

const blueprint = {
name: ['MyStablecoin'],
symbol: ['MST'],
burnable: booleans,
pausable: booleans,
mintable: booleans,
permit: booleans,
limitations: [false, 'allowlist', 'blocklist'] as const,
votes: [ ...booleans, ...clockModeOptions ] as const,
flashmint: booleans,
premint: ['1'],
custodian: booleans,
access: accessOptions,
upgradeable: upgradeableOptions,
info: infoOptions,
};

export function* generateStablecoinOptions(): Generator<Required<StablecoinOptions>> {
for (const opts of generateAlternatives(blueprint)) {
yield { ...opts, upgradeable: false };
}
}
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ export { OptionsError } from './error';
export type { Kind } from './kind';
export { sanitizeKind } from './kind';

export { erc20, erc721, erc1155, governor, custom } from './api';
export { erc20, erc721, erc1155, stablecoin, realWorldAsset, governor, custom } from './api';

export { compatibleContractsSemver } from './utils/version';
2 changes: 2 additions & 0 deletions packages/core/src/kind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ function isKind<T>(value: Kind | T): value is Kind {
case 'ERC20':
case 'ERC1155':
case 'ERC721':
case 'Stablecoin':
case 'RealWorldAsset':
case 'Governor':
case 'Custom':
return true;
Expand Down
135 changes: 135 additions & 0 deletions packages/core/src/stablecoin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import test from 'ava';
import { stablecoin } from '.';

import { buildStablecoin, StablecoinOptions } from './stablecoin';
import { printContract } from './print';

function testStablecoin(title: string, opts: Partial<StablecoinOptions>) {
test(title, t => {
const c = buildStablecoin({
name: 'MyStablecoin',
symbol: 'MST',
...opts,
});
t.snapshot(printContract(c));
});
}

/**
* Tests external API for equivalence with internal API
*/
function testAPIEquivalence(title: string, opts?: StablecoinOptions) {
test(title, t => {
t.is(stablecoin.print(opts), printContract(buildStablecoin({
name: 'MyStablecoin',
symbol: 'MST',
...opts,
})));
});
}

testStablecoin('basic stablecoin', {});

testStablecoin('stablecoin burnable', {
burnable: true,
});

testStablecoin('stablecoin pausable', {
pausable: true,
access: 'ownable',
});

testStablecoin('stablecoin pausable with roles', {
pausable: true,
access: 'roles',
});

testStablecoin('stablecoin pausable with managed', {
pausable: true,
access: 'managed',
});

testStablecoin('stablecoin burnable pausable', {
burnable: true,
pausable: true,
});

testStablecoin('stablecoin preminted', {
premint: '1000',
});

testStablecoin('stablecoin premint of 0', {
premint: '0',
});

testStablecoin('stablecoin mintable', {
mintable: true,
access: 'ownable',
});

testStablecoin('stablecoin mintable with roles', {
mintable: true,
access: 'roles',
});

testStablecoin('stablecoin permit', {
permit: true,
});

testStablecoin('stablecoin custodian', {
custodian: true,
});

testStablecoin('stablecoin allowlist', {
limitations: 'allowlist',
});

testStablecoin('stablecoin blocklist', {
limitations: 'blocklist',
});

testStablecoin('stablecoin votes', {
votes: true,
});

testStablecoin('stablecoin votes + blocknumber', {
votes: 'blocknumber',
});

testStablecoin('stablecoin votes + timestamp', {
votes: 'timestamp',
});

testStablecoin('stablecoin flashmint', {
flashmint: true,
});

testAPIEquivalence('stablecoin API default');

testAPIEquivalence('stablecoin API basic', { name: 'CustomStablecoin', symbol: 'CST' });

testAPIEquivalence('stablecoin API full', {
name: 'CustomStablecoin',
symbol: 'CST',
premint: '2000',
access: 'roles',
burnable: true,
mintable: true,
pausable: true,
permit: true,
votes: true,
flashmint: true,
limitations: 'allowlist',
custodian: true
});

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

test('stablecoin API isAccessControlRequired', async t => {
t.is(stablecoin.isAccessControlRequired({ mintable: true }), true);
t.is(stablecoin.isAccessControlRequired({ pausable: true }), true);
t.is(stablecoin.isAccessControlRequired({ limitations: 'allowlist' }), true);
t.is(stablecoin.isAccessControlRequired({ limitations: 'blocklist' }), true);
});
Loading