From 4b82b461c1b73ae12315077125e9bcf068a76725 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 29 Jan 2025 15:55:52 -0500 Subject: [PATCH 01/75] Refactor stablecoin to build based on erc20 --- packages/core/src/build-generic.ts | 3 +- packages/core/src/erc20.ts | 17 +- packages/core/src/stablecoin.test.ts.md | 12 +- packages/core/src/stablecoin.test.ts.snap | Bin 1670 -> 1683 bytes packages/core/src/stablecoin.ts | 319 ++++------------------ 5 files changed, 75 insertions(+), 276 deletions(-) diff --git a/packages/core/src/build-generic.ts b/packages/core/src/build-generic.ts index 6387058f8..e0b9084da 100644 --- a/packages/core/src/build-generic.ts +++ b/packages/core/src/build-generic.ts @@ -4,6 +4,7 @@ import { ERC721Options, buildERC721 } from './erc721'; import { ERC1155Options, buildERC1155 } from './erc1155'; import { StablecoinOptions, buildStablecoin } from './stablecoin'; import { GovernorOptions, buildGovernor } from './governor'; +import { Contract } from './contract'; export interface KindedOptions { ERC20: { kind: 'ERC20' } & ERC20Options; @@ -17,7 +18,7 @@ export interface KindedOptions { export type GenericOptions = KindedOptions[keyof KindedOptions]; -export function buildGeneric(opts: GenericOptions) { +export function buildGeneric(opts: GenericOptions): Contract { switch (opts.kind) { case 'ERC20': return buildERC20(opts); diff --git a/packages/core/src/erc20.ts b/packages/core/src/erc20.ts index 2a5e1afed..54df2fe0d 100644 --- a/packages/core/src/erc20.ts +++ b/packages/core/src/erc20.ts @@ -39,7 +39,7 @@ export const defaults: Required = { info: commonDefaults.info, } as const; -function withDefaults(opts: ERC20Options): Required { +export function withDefaults(opts: ERC20Options): Required { return { ...opts, ...withCommonDefaults(opts), @@ -61,7 +61,7 @@ export function isAccessControlRequired(opts: Partial): boolean { return opts.mintable || opts.pausable || opts.upgradeable === 'uups'; } -export function buildERC20(opts: ERC20Options): Contract { +export function buildERC20(opts: ERC20Options): ContractBuilder { const allOpts = withDefaults(opts); const c = new ContractBuilder(allOpts.name); @@ -118,6 +118,7 @@ function addBase(c: ContractBuilder, name: string, symbol: string) { ); c.addOverride(ERC20, functions._update); + c.addOverride(ERC20, functions._approve); // allows override from stablecoin } function addPausableExtension(c: ContractBuilder, access: Access) { @@ -202,7 +203,7 @@ function addFlashMint(c: ContractBuilder) { }); } -const functions = defineFunctions({ +export const functions = defineFunctions({ _update: { kind: 'internal' as const, args: [ @@ -212,6 +213,16 @@ const functions = defineFunctions({ ], }, + _approve: { + kind: 'internal' as const, + args: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'emitEvent', type: 'bool' }, + ], + }, + mint: { kind: 'public' as const, args: [ diff --git a/packages/core/src/stablecoin.test.ts.md b/packages/core/src/stablecoin.test.ts.md index da4c4d4d2..98b34fb5c 100644 --- a/packages/core/src/stablecoin.test.ts.md +++ b/packages/core/src/stablecoin.test.ts.md @@ -315,11 +315,11 @@ Generated by [AVA](https://avajs.dev). import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ ␊ - contract MyStablecoin is ERC20, ERC20Custodian, Ownable, ERC20Permit {␊ + contract MyStablecoin is ERC20, ERC20Permit, ERC20Custodian, Ownable {␊ constructor(address initialOwner)␊ ERC20("MyStablecoin", "MST")␊ - Ownable(initialOwner)␊ ERC20Permit("MyStablecoin")␊ + Ownable(initialOwner)␊ {}␊ ␊ function _isCustodian(address user) internal view override returns (bool) {␊ @@ -350,11 +350,11 @@ Generated by [AVA](https://avajs.dev). import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ ␊ - contract MyStablecoin is ERC20, ERC20Allowlist, Ownable, ERC20Permit {␊ + contract MyStablecoin is ERC20, ERC20Permit, ERC20Allowlist, Ownable {␊ constructor(address initialOwner)␊ ERC20("MyStablecoin", "MST")␊ - Ownable(initialOwner)␊ ERC20Permit("MyStablecoin")␊ + Ownable(initialOwner)␊ {}␊ ␊ function allowUser(address user) public onlyOwner {␊ @@ -396,11 +396,11 @@ Generated by [AVA](https://avajs.dev). import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ ␊ - contract MyStablecoin is ERC20, ERC20Blocklist, Ownable, ERC20Permit {␊ + contract MyStablecoin is ERC20, ERC20Permit, ERC20Blocklist, Ownable {␊ constructor(address initialOwner)␊ ERC20("MyStablecoin", "MST")␊ - Ownable(initialOwner)␊ ERC20Permit("MyStablecoin")␊ + Ownable(initialOwner)␊ {}␊ ␊ function blockUser(address user) public onlyOwner {␊ diff --git a/packages/core/src/stablecoin.test.ts.snap b/packages/core/src/stablecoin.test.ts.snap index d7bbd19526a90570609e5035851fa5285a0ff5db..4770f427f16c01af215014a985ad894abf7af02f 100644 GIT binary patch delta 428 zcmV;d0aN~l4U-KrK~_N^Q*L2!b7*gLAa*kf0{}Fbu!`_S_#*90+-wz=)sWLfYovC+ zjShv2Bu@^k=XkL)PXrhmHo7n_n%&9k*^r!u*U_7n6C09kDvjlniUc46VAPYW1R*5r zOA_N^u}GqG`?*9hfRRxrnxxN&x5GA-lW1qUos=&UicCh6@dQK~FJFy|#p0{Z?J*gc z^clfdpG_j2?p18MntYQ_1v7ui(W%G3@S;oMh@q$9B51*MJhH4vj0y2;E`wwE5WC_a zh4D=k%vn8hchKhO$R3&=850^Y`rU#i0eliZlbG*zQB1io<-(K;Zy^`%=5Rq#7o{Su zms2tSCqsq5i(N6FQsHu_U{;D1Jb{wW)rOR+gEar_QC_iH->B&4Si^s0?TNFDHA9y96O5Yef>{Re?#ObNjhOF@TX# zCz_^x}B6S5{gWEk_AK>6<>{41?H>H?J*gc^clfdpG_j2?p18Mn&gvS z1v7sM3N6uv9{<9NE`=k8o`#E{1=I1!vLZ1i#ILywj^RV>ih~r!H&HNW^~l{po1-Ip zXnJH!XvFAu3z`J*N%%}+zS~7H<-(K;Q!c!PT)3OV1w~zyinv}*#r&TP75*-E#e7PI z%b|is>JDY7 z4XHEYV%?>OXj?>L*1*NpwZ$*CJ8MhJiItw8B3EK%@QpCr0T*2^`Z>myU2fxov9es) z6W80w$#j{j=McFYyh+aaw&?u~9{(%$tKp}CqaDi5MMxuZ#a=!~7skBT@G|;;A$kTC II`BXM09~fUfB*mh diff --git a/packages/core/src/stablecoin.ts b/packages/core/src/stablecoin.ts index 1f6537e97..66ba36c0d 100644 --- a/packages/core/src/stablecoin.ts +++ b/packages/core/src/stablecoin.ts @@ -1,60 +1,28 @@ import { Contract, ContractBuilder } from './contract'; import { Access, setAccessControl, requireAccessControl } from './set-access-control'; -import { addPauseFunctions } from './add-pausable'; import { defineFunctions } from './utils/define-functions'; -import { CommonOptions, withCommonDefaults, defaults as commonDefaults } from './common-options'; -import { setUpgradeable } from './set-upgradeable'; -import { setInfo } from './set-info'; import { printContract } from './print'; -import { ClockMode, clockModeDefault, setClockMode } from './set-clock-mode'; +import { buildERC20, ERC20Options, defaults as erc20defaults, withDefaults as withERC20Defaults, functions as erc20functions } from './erc20'; -export interface StablecoinOptions extends CommonOptions { - name: string; - symbol: string; - burnable?: boolean; - pausable?: boolean; - premint?: string; - mintable?: boolean; - permit?: boolean; +export interface StablecoinOptions extends ERC20Options { limitations?: false | "allowlist" | "blocklist"; - /** - * Whether to keep track of historical balances for voting in on-chain governance, and optionally specify the clock mode. - * Setting `true` is equivalent to 'blocknumber'. Setting a clock mode implies voting is enabled. - */ - votes?: boolean | ClockMode; - flashmint?: boolean; custodian?: boolean; } export const defaults: Required = { + ...erc20defaults, name: 'MyStablecoin', symbol: 'MST', - burnable: false, - pausable: false, - premint: '0', - mintable: false, - permit: true, limitations: false, - votes: false, - flashmint: false, custodian: false, - access: commonDefaults.access, - upgradeable: commonDefaults.upgradeable, - info: commonDefaults.info, } as const; function withDefaults(opts: StablecoinOptions): Required { return { - ...opts, - ...withCommonDefaults(opts), - burnable: opts.burnable ?? defaults.burnable, - pausable: opts.pausable ?? defaults.pausable, - premint: opts.premint || defaults.premint, - mintable: opts.mintable ?? defaults.mintable, - permit: opts.permit ?? defaults.permit, + ...withERC20Defaults(opts), + name: opts.name ?? defaults.name, + symbol: opts.symbol ?? defaults.symbol, limitations: opts.limitations ?? defaults.limitations, - votes: opts.votes ?? defaults.votes, - flashmint: opts.flashmint ?? defaults.flashmint, custodian: opts.custodian ?? defaults.custodian, }; } @@ -70,116 +38,22 @@ export function isAccessControlRequired(opts: Partial): boole export function buildStablecoin(opts: StablecoinOptions): Contract { const allOpts = withDefaults(opts); - const c = new ContractBuilder(allOpts.name); - - const { access, upgradeable, info } = allOpts; - - addBase(c, allOpts.name, allOpts.symbol); - - if (allOpts.burnable) { - addBurnable(c); - } - - if (allOpts.pausable) { - addPausableExtension(c, access); - } - - if (allOpts.premint) { - addPremint(c, allOpts.premint); - } - - if (allOpts.mintable) { - addMintable(c, access); - } + // Upgradeability is not yet available for the community contracts + allOpts.upgradeable = false; - if (allOpts.limitations) { - addLimitations(c, access, allOpts.limitations); - } + const c = buildERC20(allOpts); if (allOpts.custodian) { - addCustodian(c, access); - } - - // Note: Votes requires Permit - if (allOpts.permit || allOpts.votes) { - addPermit(c, allOpts.name); - } - - if (allOpts.votes) { - const clockMode = allOpts.votes === true ? clockModeDefault : allOpts.votes; - addVotes(c, clockMode); + addCustodian(c, allOpts.access); } - if (allOpts.flashmint) { - addFlashMint(c); + if (allOpts.limitations) { + addLimitations(c, allOpts.access, allOpts.limitations); } - setAccessControl(c, access); - - // Upgradeability is not yet available for the community contracts - // setUpgradeable(c, upgradeable, access); - - setInfo(c, info); - return c; } -function addBase(c: ContractBuilder, name: string, symbol: string) { - const ERC20 = { - name: 'ERC20', - path: '@openzeppelin/contracts/token/ERC20/ERC20.sol', - }; - c.addParent( - ERC20, - [name, symbol], - ); - - c.addOverride(ERC20, functions._update); - c.addOverride(ERC20, functions._approve); -} - -function addPausableExtension(c: ContractBuilder, access: Access) { - const ERC20Pausable = { - name: 'ERC20Pausable', - path: '@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol', - }; - c.addParent(ERC20Pausable); - c.addOverride(ERC20Pausable, functions._update); - - addPauseFunctions(c, access); -} - -function addBurnable(c: ContractBuilder) { - c.addParent({ - name: 'ERC20Burnable', - path: '@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol', - }); -} - -export const premintPattern = /^(\d*)(?:\.(\d+))?(?:e(\d+))?$/; - -function addPremint(c: ContractBuilder, amount: string) { - const m = amount.match(premintPattern); - if (m) { - const integer = m[1]?.replace(/^0+/, '') ?? ''; - const decimals = m[2]?.replace(/0+$/, '') ?? ''; - const exponent = Number(m[3] ?? 0); - - if (Number(integer + decimals) > 0) { - const decimalPlace = decimals.length - exponent; - const zeroes = new Array(Math.max(0, -decimalPlace)).fill('0').join(''); - const units = integer + decimals + zeroes; - const exp = decimalPlace <= 0 ? 'decimals()' : `(decimals() - ${decimalPlace})`; - c.addConstructorCode(`_mint(msg.sender, ${units} * 10 ** ${exp});`); - } - } -} - -function addMintable(c: ContractBuilder, access: Access) { - requireAccessControl(c, functions.mint, access, 'MINTER', 'minter'); - c.addFunctionCode('_mint(to, amount);', functions.mint); -} - function addLimitations(c: ContractBuilder, access: Access, mode: boolean | 'allowlist' | 'blocklist') { const type = mode === 'allowlist'; const ERC20Limitation = { @@ -249,132 +123,45 @@ function addCustodian(c: ContractBuilder, access: Access) { } } -function addPermit(c: ContractBuilder, name: string) { - const ERC20Permit = { - name: 'ERC20Permit', - path: '@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol', - }; - c.addParent(ERC20Permit, [name]); - c.addOverride(ERC20Permit, functions.nonces); - -} - -function addVotes(c: ContractBuilder, clockMode: ClockMode) { - if (!c.parents.some(p => p.contract.name === 'ERC20Permit')) { - throw new Error('Missing ERC20Permit requirement for ERC20Votes'); - } - - const ERC20Votes = { - name: 'ERC20Votes', - path: '@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol', - }; - c.addParent(ERC20Votes); - c.addOverride(ERC20Votes, functions._update); - - c.addImportOnly({ - name: 'Nonces', - path: '@openzeppelin/contracts/utils/Nonces.sol', - }); - c.addOverride({ - name: 'Nonces', - }, functions.nonces); - - setClockMode(c, ERC20Votes, clockMode); -} - -function addFlashMint(c: ContractBuilder) { - c.addParent({ - name: 'ERC20FlashMint', - path: '@openzeppelin/contracts/token/ERC20/extensions/ERC20FlashMint.sol', - }); -} - -const functions = defineFunctions({ - _update: { - kind: 'internal' as const, - args: [ - { name: 'from', type: 'address' }, - { name: 'to', type: 'address' }, - { name: 'value', type: 'uint256' }, - ], - }, - - _approve: { - kind: 'internal' as const, - args: [ - { name: 'owner', type: 'address' }, - { name: 'spender', type: 'address' }, - { name: 'value', type: 'uint256' }, - { name: 'emitEvent', type: 'bool' }, - ], - }, - - _isCustodian: { - kind: 'internal' as const, - args: [ - { name: 'user', type: 'address' }, - ], - returns: ['bool'], - mutability: 'view' as const - }, - - mint: { - kind: 'public' as const, - args: [ - { name: 'to', type: 'address' }, - { name: 'amount', type: 'uint256' }, - ], - }, +const functions = { + ...erc20functions, + ...defineFunctions({ + _isCustodian: { + kind: 'internal' as const, + args: [ + { name: 'user', type: 'address' }, + ], + returns: ['bool'], + mutability: 'view' as const + }, + + allowUser: { + kind: 'public' as const, + args: [ + { name: 'user', type: 'address' } + ], + }, + + disallowUser: { + kind: 'public' as const, + args: [ + { name: 'user', type: 'address' } + ], + }, + + blockUser: { + kind: 'public' as const, + args: [ + { name: 'user', type: 'address' } + ], + }, + + unblockUser: { + kind: 'public' as const, + args: [ + { name: 'user', type: 'address' } + ], + }, + }) +}; - allowUser: { - kind: 'public' as const, - args: [ - { name: 'user', type: 'address' } - ], - }, - - disallowUser: { - kind: 'public' as const, - args: [ - { name: 'user', type: 'address' } - ], - }, - - blockUser: { - kind: 'public' as const, - args: [ - { name: 'user', type: 'address' } - ], - }, - - unblockUser: { - kind: 'public' as const, - args: [ - { name: 'user', type: 'address' } - ], - }, - - pause: { - kind: 'public' as const, - args: [], - }, - - unpause: { - kind: 'public' as const, - args: [], - }, - - snapshot: { - kind: 'public' as const, - args: [], - }, - - nonces: { - kind: 'public' as const, - args: [ - { name: 'owner', type: 'address' }, - ], - returns: ['uint256'], - mutability: 'view' as const, - } -}); From 78d9fced2c9aa576bb324e837319c98e29465d33 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 30 Jan 2025 16:59:40 -0500 Subject: [PATCH 02/75] Add ERC20Bridgeable to core --- packages/core/src/erc20.ts | 40 ++++++++++++++++++++++++ packages/core/src/generate/erc20.ts | 10 ++++-- packages/core/src/generate/stablecoin.ts | 21 +++---------- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/packages/core/src/erc20.ts b/packages/core/src/erc20.ts index 54df2fe0d..8ae388889 100644 --- a/packages/core/src/erc20.ts +++ b/packages/core/src/erc20.ts @@ -7,6 +7,7 @@ import { setUpgradeable } from './set-upgradeable'; import { setInfo } from './set-info'; import { printContract } from './print'; import { ClockMode, clockModeDefault, setClockMode } from './set-clock-mode'; +import { supportsInterface } from './common-functions'; export interface ERC20Options extends CommonOptions { name: string; @@ -22,6 +23,7 @@ export interface ERC20Options extends CommonOptions { */ votes?: boolean | ClockMode; flashmint?: boolean; + bridgeable?: boolean | 'superchain'; } export const defaults: Required = { @@ -34,6 +36,7 @@ export const defaults: Required = { permit: true, votes: false, flashmint: false, + bridgeable: false, access: commonDefaults.access, upgradeable: commonDefaults.upgradeable, info: commonDefaults.info, @@ -50,6 +53,7 @@ export function withDefaults(opts: ERC20Options): Required { permit: opts.permit ?? defaults.permit, votes: opts.votes ?? defaults.votes, flashmint: opts.flashmint ?? defaults.flashmint, + bridgeable: opts.bridgeable ?? defaults.bridgeable, }; } @@ -100,6 +104,10 @@ export function buildERC20(opts: ERC20Options): ContractBuilder { addFlashMint(c); } + if (allOpts.bridgeable) { + addBridgeable(c, allOpts.bridgeable, allOpts.upgradeable, access); + } + setAccessControl(c, access); setUpgradeable(c, upgradeable, access); setInfo(c, info); @@ -203,6 +211,31 @@ function addFlashMint(c: ContractBuilder) { }); } +function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', upgradeable: false | 'transparent' | 'uups', access: Access) { + if (bridgeable !== false) { + const ERC20Bridgeable = { + name: 'ERC20Bridgeable', + path: `@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol`, + }; + + c.addParent(ERC20Bridgeable); + c.addOverride(ERC20Bridgeable, supportsInterface); + + if (upgradeable !== false) { + throw new Error('ERC20Bridgeable does not currently support usage with upgradeable contracts'); + } + + c.addOverride(ERC20Bridgeable, functions._checkTokenBridge); + if (bridgeable === 'superchain') { + c.addVariable('address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;'); + c.setFunctionBody(['if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], functions._checkTokenBridge); + } else { + c.setFunctionBody([], functions._checkTokenBridge); + requireAccessControl(c, functions._checkTokenBridge, access, 'TOKEN_BRIDGE', 'tokenBridge'); + } + } +} + export const functions = defineFunctions({ _update: { kind: 'internal' as const, @@ -253,5 +286,12 @@ export const functions = defineFunctions({ ], returns: ['uint256'], mutability: 'view' as const, + }, + + _checkTokenBridge: { + kind: 'internal' as const, + args: [ + { name: 'caller', type: 'address' }, + ], } }); diff --git a/packages/core/src/generate/erc20.ts b/packages/core/src/generate/erc20.ts index 929da1af5..206fbeb4e 100644 --- a/packages/core/src/generate/erc20.ts +++ b/packages/core/src/generate/erc20.ts @@ -7,7 +7,7 @@ import { generateAlternatives } from './alternatives'; const booleans = [true, false]; -const blueprint = { +export const blueprint = { name: ['MyToken'], symbol: ['MTK'], burnable: booleans, @@ -17,11 +17,17 @@ const blueprint = { votes: [ ...booleans, ...clockModeOptions ] as const, flashmint: booleans, premint: ['1'], + bridgeable: [ ...booleans, 'superchain' ] as const, access: accessOptions, upgradeable: upgradeableOptions, info: infoOptions, }; export function* generateERC20Options(): Generator> { - yield* generateAlternatives(blueprint); + for (const opts of generateAlternatives(blueprint)) { + // Only yield options that are not both bridgeable and upgradeable, since ERC20Bridgeable does not currently support usage with upgradeable contracts. + if (!(opts.bridgeable && opts.upgradeable)) { + yield opts; + } + } } diff --git a/packages/core/src/generate/stablecoin.ts b/packages/core/src/generate/stablecoin.ts index 358052aa9..9c36a4799 100644 --- a/packages/core/src/generate/stablecoin.ts +++ b/packages/core/src/generate/stablecoin.ts @@ -1,31 +1,18 @@ 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'; +import { blueprint as erc20Blueprint } from './erc20'; const booleans = [true, false]; const blueprint = { + ...erc20Blueprint, 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, + upgradeable: [false] as const, }; export function* generateStablecoinOptions(): Generator> { - for (const opts of generateAlternatives(blueprint)) { - yield { ...opts, upgradeable: false }; - } + yield* generateAlternatives(blueprint); } From 60f13d959bec20df24c5eb2d0ee3a474dd6db4aa Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 30 Jan 2025 17:13:13 -0500 Subject: [PATCH 03/75] Add testcases WIP --- packages/core/src/erc20.test.ts | 34 ++++++ packages/core/src/erc20.test.ts.md | 158 +++++++++++++++++++++++++++ packages/core/src/erc20.test.ts.snap | Bin 1960 -> 2338 bytes packages/core/src/erc20.ts | 2 + 4 files changed, 194 insertions(+) diff --git a/packages/core/src/erc20.test.ts b/packages/core/src/erc20.test.ts index 7cd107d26..6ab626ff4 100644 --- a/packages/core/src/erc20.test.ts +++ b/packages/core/src/erc20.test.ts @@ -92,6 +92,40 @@ testERC20('erc20 flashmint', { flashmint: true, }); +// TODO test for error +// testERC20('erc20 bridgeable', { +// bridgeable: true, +// access: 'ownable', +// }); + +testERC20('erc20 bridgeable roles', { + bridgeable: true, + access: 'roles', +}); + +testERC20('erc20 bridgeable managed', { + bridgeable: true, + access: 'managed', +}); + +testERC20('erc20 bridgeable superchain', { + bridgeable: 'superchain', +}); + +testERC20('erc20 bridgeable superchain roles', { + bridgeable: 'superchain', + access: 'roles', +}); + +testERC20('erc20 bridgeable superchain managed', { + bridgeable: 'superchain', + access: 'managed', +}); + +// TODO test and catch error when bridgeable and upgradeable are both true + +// TODO test and catch error when bridgeable is 'superchain' and upgradeable is true + testERC20('erc20 full upgradeable transparent', { premint: '2000', access: 'roles', diff --git a/packages/core/src/erc20.test.ts.md b/packages/core/src/erc20.test.ts.md index 2fcc8e59c..f72eb77a1 100644 --- a/packages/core/src/erc20.test.ts.md +++ b/packages/core/src/erc20.test.ts.md @@ -436,6 +436,164 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## erc20 bridgeable roles + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessControl {␊ + bytes32 public constant TOKEN_BRIDGE_ROLE = keccak256("TOKEN_BRIDGE_ROLE");␊ + ␊ + constructor(address defaultAdmin, address tokenBridge)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + {␊ + _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ + _grantRole(TOKEN_BRIDGE_ROLE, tokenBridge);␊ + }␊ + ␊ + function _checkTokenBridge(address caller)␊ + internal␊ + onlyRole(TOKEN_BRIDGE_ROLE)␊ + override␊ + {}␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function supportsInterface(bytes4 interfaceId)␊ + public␊ + view␊ + override(ERC20Bridgeable, AccessControl)␊ + returns (bool)␊ + {␊ + return super.supportsInterface(interfaceId);␊ + }␊ + }␊ + ` + +## erc20 bridgeable managed + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {AccessManaged} from "@openzeppelin/contracts/access/manager/AccessManaged.sol";␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessManaged {␊ + constructor(address initialAuthority)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + AccessManaged(initialAuthority)␊ + {}␊ + ␊ + function _checkTokenBridge(address caller) internal restricted override {}␊ + }␊ + ` + +## erc20 bridgeable superchain + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable {␊ + address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ + ␊ + constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") {}␊ + ␊ + function _checkTokenBridge(address caller) internal override {␊ + if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + }␊ + ` + +## erc20 bridgeable superchain roles + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessControl {␊ + address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ + ␊ + constructor(address defaultAdmin)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + {␊ + _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ + }␊ + ␊ + function _checkTokenBridge(address caller) internal override {␊ + if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function supportsInterface(bytes4 interfaceId)␊ + public␊ + view␊ + override(ERC20Bridgeable, AccessControl)␊ + returns (bool)␊ + {␊ + return super.supportsInterface(interfaceId);␊ + }␊ + }␊ + ` + +## erc20 bridgeable superchain managed + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {AccessManaged} from "@openzeppelin/contracts/access/manager/AccessManaged.sol";␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessManaged {␊ + address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ + ␊ + constructor(address initialAuthority)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + AccessManaged(initialAuthority)␊ + {}␊ + ␊ + function _checkTokenBridge(address caller) internal override {␊ + if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + }␊ + ` + ## erc20 full upgradeable transparent > Snapshot 1 diff --git a/packages/core/src/erc20.test.ts.snap b/packages/core/src/erc20.test.ts.snap index 47f0669a62f4cd700bc2f73327bfa0ec3211e159..14580891ad24efe2b8b5c3f784b2a55ec1039776 100644 GIT binary patch literal 2338 zcmV+-3ElQVRzV4E^gyDZm z_*xVQX&;LS00000000B+T+44Gw;A6@76r6epaptp5fo*Vi?q=z>Ta-DV~aSplL)(h zz>gxyAp$i+*@S1v3CXdob@z~S|A3y;|Diy7>ZL$?D$qZmK<_Pj>8(YJVrDoG&T#ay zEotKMVHXm~k00mzzTfxa=$qldqQ)uz^>2{C!a}D5$gu$sGrAqj33T`g75wXOOcM(D z`Q2aLzw^C2-rwB^cYbj1mv`H3aIm-eS@RV(5aFoVGZ7JZh!J}ZwtI(_b{lL^+kpZP zECkN6I03s3B3~fKK^7)pgA&1@AvpN*X{*!fR2&A6Z3sBEu!+S8eA#I|YjwM8l?t{U z$^^LF+TZAQ-hd&aHmH6`9YkJBYHcH=))w>>k+wfI__xKWRb5kw>>*}jF$*blArRr1 z65dWwkhCk|8n8V&^cDfkfj_MQ60^Z&1pojHO1NOIAtyvk zijMs2exY?_PoDEiQj|0npd%se-Seq58yW`Uye(%>4L%H!2&~T z_naVB_h)&3Im#G~%S~!yR%cY!AHIB3@&6yX#1NPgUujXT4jgx2VFOTNjeKg7W$&*q z=dAhPqzSlW8WPbgg-E*%4o?smQp=*}m>fq`Ie-iSdWIOoCgOmhuUyQK2?ir@Aa%Tz zVx;dnCKM=ovYwb5Ap9g~1Gt!o?$Zyz8MIs!KQ2rJVgy>z7va7&orL9cj3#r}L97*S z9&GAu7Hkq8H^PdGAFE&y7&oI9;u_reqkqoB+`|F$Ay&a#)hQf(7qtvRznHnLB zdW_N_RGLElYJfMETnT<5_`R(IKN}Kwj7$yuH5B;!$@1WDJ7952_zMoi+REAz2Iqu9 z`TS-KsMcL^LKzmL=}}ABt~P0#{;#gYvxQwxYWfi3-q(uI*u7F{ zi*vyRbFw~u=sXd$sY}Fo*Xb|z7RkxEb;VFu$JQ0^KUdWDy=C+xR=BRXIP99c(6`;& zIn);V5(9G-`uuQYOGdHkKxxb@t=z&5}OdKYQuTi{Q;q1CgCkp~b{M zD-!#C!F#kf=Sy8x zK8Y`Yh)t>nMFGY}AI~s4&*3W+O(4*i0z<-OgoBzqZkp#{T(T~i37E)@i+rmG?*acl z7IEzXVkHKY7*JxsEx>?t6#@jd5f{*QG%bO@DFE=7Vz&fJ09X(JL`GqF-X*Srduku4 zyQh^B=J@)>CoXrrc$FOX?Kj#LIW zUhQtY>~HUGZpBmVHEd<&-jJEmi28P}@A*eYv&M|7gFr`N@{1!kHPKqt5A{ zIN)#9ik+F`H56|3o~Lh|Amj8fo)?|pfR>f?LRps>mO?Wd*E8-(X>44pi|4N6sV(n$ z>RzYMw5^EMlL~)0XZ<`9mz~qG!dO5R7zfMj53l-%?;v&P5HKIoIp%8X7xxhtN#_d zKYz>BU+R0T<5Fj$z~SI%Z)<91vgUz+BG0Ds|@stfv; z9^bDf7?dIWR3ZGk>0F9OW{TOtHjdOOK;f`jk2UdHqDx}fRjzx?AJPzxTfDk7)N8K>(=dd8+>TE zTu}QteH{vgH(kQv5H+C}Y$si?rr?msH)NAPk_}=!?=3tW&6(==9P+Py$AnliP)~5x z_odPICT1gpwe-ADWrF$H@lbIzTwhNo|CcI&_RX^H z*f-0-ytm_5@@Fs>cXz)y7gMH$RxMDj-bEIL=Zr(TnOnba=fvx->u745kAA2G>JJ{3 zfqEIJmw|d2s4qWI54Siv+B=wYgXAevWWIyhKm(-CxI*c{I2uQLpX{%1YN;qgg-$Y8?j=Pc}!j&6XzgN;aVz6v^PQLJ=?L6jfjBW+-YtB zDw0^_4Zt#&TGd?Y-7&dTeh>8F&y}32y}ag!Y&~5qr_#1Y%iOBWt;*c0%&k@_x5`4( z&F5CDl!|077-*7;B_<4gXj>`4K7a5Aj9F)=bEsnnb4~|A@ Igga^g02GON-T(jq literal 1960 zcmV;Z2Uqw(RzV@ ze}-*`1++vbL?lursU%L8L(jYI8+6}cz;3$?*lobR!R`Zg*=@jpK@#odSx~^QXTHCA zWx1Ljm$X*F$!Y1d zBt1p~UxBvA2yEL(|iRbu3yn^PSl z>vEpw@}iV6h8T%tuN@8)+0Zl*=Z5S(F!;#%)PNj#R=`2aVu*8q2^JXIYlj4}YS7F7 z^a#edT`H;c8J!E+p!wvq6#U=uh$%27LC~T~6}Vp8#wMV|?grAN$^K_Y_L&d9$qMku zAR^*kiV(v9TYCs}sBP0jOm<_b96*KuJwS|M3vs~EYY#JIfp!;c${25C4B7Eq3knp! zS>Mey5IqT610E(~?$Kj#0BsK?uL~1_7=d>DMWnZ)^RRr6acAzih&3YRp;BL2s3e+h zj1@;8s$dZ=ZbogyHMsGcf*U{Ix&qu-2-ZU|klF(-9%YPfiC;$?8UjO<_oqXWc2^+& z$y~JL0$_nefc1s#&E<`qjkVQf@C@uD(}eqTj~-XbsfKcOzSI+rEYyLXEfy>XlVtG( zYj+5E>IXmxChRgu#0IrdWoh}v!uIOc&cae_)ban983QZgk{=x|{Lm6AZ;D|6N-`|i4)q*GX zD8r&VIBF^CDrd+UExlrh3x-XBtkK~{FQdR1i7|&NVeiMvUMuj@z6yAmBIZ6_Ff$g` zm#r=oB(NZXgJ2YuX%It>uUC`$%>1fg(@)b~Rh;5da1y<~t11rPZE!>^#A@JSv)Kgq z!NVrFe;-)L#16E1rJ8p)Q``+`2NcEs$@O@?uX=0=3eaP)3BTGhb}vyLW_yND<1o0%Fk#o zXDbg{zVu(SGLm0WVxBG46WHcP*mt;Kk`ICE3ks~MW3R#FN29K)og{ETY$jEc zq7Y-_#{-NGd)O7ZCUj^bfg#~B!a+q&H*0g)E=`xlghuqti-J`T9)RFJ7V(@mVg&{i z7*JrqHNb#F6#@iy5EsyKHAez}Dgf}ubRP*605B#1h!=(F?=DFd+z!m;{vC=B1 zH-mlQPqc-}xzI2cGC3SsKE#$?G-p04%RupL8+h(6gBA+Pi-JMIUC59wcJ5?O*6&<( zeQ`Un{0tA(QtKiB|Hnk$HVG$89nOC{7n&}%>zfASUNq-&q0f;iY*dSQ$sVi zJ@PG@V9C_>HDj_4PG=+euXRh}f-VF1lQGmegJBrpx#@91ou~9Tatg0|gu@Q1Lq8Wx zZ%vx5Dpi7)*=_6_#CWgkCphji&_(9n=N*Y4md@8wR_z4d*zr5&chvc8zbItF{`vMO za5U{o`1Bkf1X0GCe77K`ddY|*EADV{CpW#XXant)in+d5D!{16LKAuadwhph)5FLH zgjOw3P9B3(Y|d>+ms9S(*CSu|JXdq*b@u}$QNMk+NYsl&y-3uHME&X$^+?6`_WI_C z3evO4hmW*7I>H?T?uYZdGurf?E~bYLd8B9-1znTTK!b$^F3s4XL<7 uLLuD~w&!e}K!PzO1DLSC{4jJ@t`|PeR6Mbu$iA;}_WeI)T-fq7RR91xF{tAJ diff --git a/packages/core/src/erc20.ts b/packages/core/src/erc20.ts index 8ae388889..f6dba7e3a 100644 --- a/packages/core/src/erc20.ts +++ b/packages/core/src/erc20.ts @@ -224,6 +224,8 @@ function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', u if (upgradeable !== false) { throw new Error('ERC20Bridgeable does not currently support usage with upgradeable contracts'); } + // TODO if ownable, throw error that ERC20Bridgeable does not support ownable, unless it is superchain + // or hardcode a variable for token bridge but require user to set it c.addOverride(ERC20Bridgeable, functions._checkTokenBridge); if (bridgeable === 'superchain') { From daa322dbc12db9dbe82b23c290dc642d8d442385 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 13:31:32 -0500 Subject: [PATCH 04/75] Use options error --- packages/core/src/erc20.ts | 49 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/packages/core/src/erc20.ts b/packages/core/src/erc20.ts index f6dba7e3a..e7792260b 100644 --- a/packages/core/src/erc20.ts +++ b/packages/core/src/erc20.ts @@ -8,6 +8,7 @@ import { setInfo } from './set-info'; import { printContract } from './print'; import { ClockMode, clockModeDefault, setClockMode } from './set-clock-mode'; import { supportsInterface } from './common-functions'; +import { OptionsError } from './error'; export interface ERC20Options extends CommonOptions { name: string; @@ -212,29 +213,37 @@ function addFlashMint(c: ContractBuilder) { } function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', upgradeable: false | 'transparent' | 'uups', access: Access) { - if (bridgeable !== false) { - const ERC20Bridgeable = { - name: 'ERC20Bridgeable', - path: `@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol`, - }; + if (bridgeable === false) { + return; + } + + const ERC20Bridgeable = { + name: 'ERC20Bridgeable', + path: `@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol`, + }; - c.addParent(ERC20Bridgeable); - c.addOverride(ERC20Bridgeable, supportsInterface); + c.addParent(ERC20Bridgeable); + c.addOverride(ERC20Bridgeable, supportsInterface); - if (upgradeable !== false) { - throw new Error('ERC20Bridgeable does not currently support usage with upgradeable contracts'); - } - // TODO if ownable, throw error that ERC20Bridgeable does not support ownable, unless it is superchain - // or hardcode a variable for token bridge but require user to set it - - c.addOverride(ERC20Bridgeable, functions._checkTokenBridge); - if (bridgeable === 'superchain') { - c.addVariable('address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;'); - c.setFunctionBody(['if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], functions._checkTokenBridge); - } else { - c.setFunctionBody([], functions._checkTokenBridge); - requireAccessControl(c, functions._checkTokenBridge, access, 'TOKEN_BRIDGE', 'tokenBridge'); + if (upgradeable) { + throw new OptionsError({ + bridgeable: 'Bridgeable does not currently support use in upgradeable contracts' + }); + } + + c.addOverride(ERC20Bridgeable, functions._checkTokenBridge); + if (bridgeable === 'superchain') { + c.addVariable('address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;'); + c.setFunctionBody(['if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], functions._checkTokenBridge); + } else { + if (access === 'ownable') { + throw new OptionsError({ + bridgeable: 'Bridgeable requires roles or managed access control' + }); } + + c.setFunctionBody([], functions._checkTokenBridge); + requireAccessControl(c, functions._checkTokenBridge, access, 'TOKEN_BRIDGE', 'tokenBridge'); } } From c6fd584a3576b53f92ea173216da289843899e2b Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 13:31:44 -0500 Subject: [PATCH 05/75] Add to UI --- packages/ui/src/ERC20Controls.svelte | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/ui/src/ERC20Controls.svelte b/packages/ui/src/ERC20Controls.svelte index 1cc1a69ec..24043b501 100644 --- a/packages/ui/src/ERC20Controls.svelte +++ b/packages/ui/src/ERC20Controls.svelte @@ -90,6 +90,39 @@ +
+

+ + +

+ +
+ + + +
+
+

From cef188707602ce0c4277d659246c3adc59b39b05 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 14:00:27 -0500 Subject: [PATCH 06/75] Fix access control handling WIP --- packages/core/src/erc20.ts | 44 +++++++++++++++++++++++++++------ packages/core/src/stablecoin.ts | 2 +- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/packages/core/src/erc20.ts b/packages/core/src/erc20.ts index e7792260b..a6488e1ca 100644 --- a/packages/core/src/erc20.ts +++ b/packages/core/src/erc20.ts @@ -63,7 +63,7 @@ export function printERC20(opts: ERC20Options = defaults): string { } export function isAccessControlRequired(opts: Partial): boolean { - return opts.mintable || opts.pausable || opts.upgradeable === 'uups'; + return opts.mintable || opts.pausable || opts.upgradeable === 'uups' || opts.bridgeable === true; } export function buildERC20(opts: ERC20Options): ContractBuilder { @@ -234,16 +234,44 @@ function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', u c.addOverride(ERC20Bridgeable, functions._checkTokenBridge); if (bridgeable === 'superchain') { c.addVariable('address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;'); - c.setFunctionBody(['if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], functions._checkTokenBridge); + c.setFunctionBody(['if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], functions._checkTokenBridge); } else { - if (access === 'ownable') { - throw new OptionsError({ - bridgeable: 'Bridgeable requires roles or managed access control' - }); + if (access === false) { + access = 'ownable'; } - c.setFunctionBody([], functions._checkTokenBridge); - requireAccessControl(c, functions._checkTokenBridge, access, 'TOKEN_BRIDGE', 'tokenBridge'); + setAccessControl(c, access); + + switch (access) { + case 'ownable': { + // TODO add immutable and don't use owner + c.setFunctionBody([`return caller == owner();`], functions._checkTokenBridge); + break; + } + case 'roles': { + const roleOwner = 'tokenBridge'; + const roleId = 'TOKEN_BRIDGE_ROLE'; + const addedConstant = c.addVariable(`bytes32 public constant ${roleId} = keccak256("${roleId}");`); + if (roleOwner && addedConstant) { + c.addConstructorArgument({type: 'address', name: roleOwner}); + c.addConstructorCode(`_grantRole(${roleId}, ${roleOwner});`); + } + c.setFunctionBody([`return hasRole(${roleId}, caller);`], functions._checkTokenBridge); + break; + } + case 'managed': { + c.addImportOnly({ + name: 'AuthorityUtils', + path: `@openzeppelin/contracts/access/manager/AuthorityUtils.sol`, + }); + const logic = [ + `(bool immediate,) = AuthorityUtils.canCallWithDelay(authority(), caller, address(this), bytes4(_msgData()[0:4]));`, + `return immediate;` + ] + c.setFunctionBody(logic, functions._checkTokenBridge); + break; + } + } } } diff --git a/packages/core/src/stablecoin.ts b/packages/core/src/stablecoin.ts index 66ba36c0d..bfa286f1b 100644 --- a/packages/core/src/stablecoin.ts +++ b/packages/core/src/stablecoin.ts @@ -105,7 +105,7 @@ function addCustodian(c: ContractBuilder, access: Access) { c.addConstructorArgument({type: 'address', name: roleOwner}); c.addConstructorCode(`_grantRole(${roleId}, ${roleOwner});`); } - c.setFunctionBody([`return hasRole(CUSTODIAN_ROLE, user);`], functions._isCustodian); + c.setFunctionBody([`return hasRole(${roleId}, user);`], functions._isCustodian); break; } case 'managed': { From 8dc16b06a8092f93c51ff8157499b75d6fd60f2c Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 14:34:30 -0500 Subject: [PATCH 07/75] Use revert --- packages/core/src/erc20.ts | 15 ++++++++++----- packages/core/src/stablecoin.ts | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/core/src/erc20.ts b/packages/core/src/erc20.ts index a6488e1ca..15162909d 100644 --- a/packages/core/src/erc20.ts +++ b/packages/core/src/erc20.ts @@ -244,19 +244,24 @@ function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', u switch (access) { case 'ownable': { - // TODO add immutable and don't use owner - c.setFunctionBody([`return caller == owner();`], functions._checkTokenBridge); + const addedImmutable = c.addVariable(`address public immutable TOKEN_BRIDGE;`); + if (addedImmutable) { + c.addConstructorArgument({type: 'address', name: 'tokenBridge'}); + c.addConstructorCode(`require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");`); + c.addConstructorCode(`TOKEN_BRIDGE = tokenBridge;`); + } + c.setFunctionBody([`if (caller != TOKEN_BRIDGE) revert Unauthorized();`], functions._checkTokenBridge); break; } case 'roles': { const roleOwner = 'tokenBridge'; const roleId = 'TOKEN_BRIDGE_ROLE'; const addedConstant = c.addVariable(`bytes32 public constant ${roleId} = keccak256("${roleId}");`); - if (roleOwner && addedConstant) { + if (addedConstant) { c.addConstructorArgument({type: 'address', name: roleOwner}); c.addConstructorCode(`_grantRole(${roleId}, ${roleOwner});`); } - c.setFunctionBody([`return hasRole(${roleId}, caller);`], functions._checkTokenBridge); + c.setFunctionBody([`if (!hasRole(${roleId}, caller)) revert Unauthorized();`], functions._checkTokenBridge); break; } case 'managed': { @@ -266,7 +271,7 @@ function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', u }); const logic = [ `(bool immediate,) = AuthorityUtils.canCallWithDelay(authority(), caller, address(this), bytes4(_msgData()[0:4]));`, - `return immediate;` + `if (!immediate) revert Unauthorized();` ] c.setFunctionBody(logic, functions._checkTokenBridge); break; diff --git a/packages/core/src/stablecoin.ts b/packages/core/src/stablecoin.ts index bfa286f1b..e28d86ee8 100644 --- a/packages/core/src/stablecoin.ts +++ b/packages/core/src/stablecoin.ts @@ -101,7 +101,7 @@ function addCustodian(c: ContractBuilder, access: Access) { const roleOwner = 'custodian'; const roleId = 'CUSTODIAN_ROLE'; const addedConstant = c.addVariable(`bytes32 public constant ${roleId} = keccak256("${roleId}");`); - if (roleOwner && addedConstant) { + if (addedConstant) { c.addConstructorArgument({type: 'address', name: roleOwner}); c.addConstructorCode(`_grantRole(${roleId}, ${roleOwner});`); } From c883dd95b71cf9c7ab27995f38322d9d8d10ef40 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 16:05:57 -0500 Subject: [PATCH 08/75] Fix mutability, update snapshots --- packages/core/src/erc20.test.ts.md | 32 +++++++++++++++++---------- packages/core/src/erc20.test.ts.snap | Bin 2338 -> 2438 bytes packages/core/src/erc20.ts | 9 ++++---- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/core/src/erc20.test.ts.md b/packages/core/src/erc20.test.ts.md index f72eb77a1..35b90e926 100644 --- a/packages/core/src/erc20.test.ts.md +++ b/packages/core/src/erc20.test.ts.md @@ -451,6 +451,7 @@ Generated by [AVA](https://avajs.dev). ␊ contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessControl {␊ bytes32 public constant TOKEN_BRIDGE_ROLE = keccak256("TOKEN_BRIDGE_ROLE");␊ + error Unauthorized();␊ ␊ constructor(address defaultAdmin, address tokenBridge)␊ ERC20("MyToken", "MTK")␊ @@ -460,11 +461,9 @@ Generated by [AVA](https://avajs.dev). _grantRole(TOKEN_BRIDGE_ROLE, tokenBridge);␊ }␊ ␊ - function _checkTokenBridge(address caller)␊ - internal␊ - onlyRole(TOKEN_BRIDGE_ROLE)␊ - override␊ - {}␊ + function _checkTokenBridge(address caller) internal view override {␊ + if (!hasRole(TOKEN_BRIDGE_ROLE, caller)) revert Unauthorized();␊ + }␊ ␊ // The following functions are overrides required by Solidity.␊ ␊ @@ -488,18 +487,24 @@ Generated by [AVA](https://avajs.dev). pragma solidity ^0.8.22;␊ ␊ import {AccessManaged} from "@openzeppelin/contracts/access/manager/AccessManaged.sol";␊ + import {AuthorityUtils} from "@openzeppelin/contracts/access/manager/AuthorityUtils.sol";␊ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessManaged {␊ + error Unauthorized();␊ + ␊ constructor(address initialAuthority)␊ ERC20("MyToken", "MTK")␊ ERC20Permit("MyToken")␊ AccessManaged(initialAuthority)␊ {}␊ ␊ - function _checkTokenBridge(address caller) internal restricted override {}␊ + function _checkTokenBridge(address caller) internal view override {␊ + (bool immediate,) = AuthorityUtils.canCallWithDelay(authority(), caller, address(this), bytes4(_msgData()[0:4]));␊ + if (!immediate) revert Unauthorized();␊ + }␊ }␊ ` @@ -517,11 +522,12 @@ Generated by [AVA](https://avajs.dev). ␊ contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable {␊ address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ + error Unauthorized();␊ ␊ constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") {}␊ ␊ - function _checkTokenBridge(address caller) internal override {␊ - if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ + function _checkTokenBridge(address caller) internal pure override {␊ + if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ }␊ }␊ ` @@ -541,6 +547,7 @@ Generated by [AVA](https://avajs.dev). ␊ contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessControl {␊ address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ + error Unauthorized();␊ ␊ constructor(address defaultAdmin)␊ ERC20("MyToken", "MTK")␊ @@ -549,8 +556,8 @@ Generated by [AVA](https://avajs.dev). _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ }␊ ␊ - function _checkTokenBridge(address caller) internal override {␊ - if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ + function _checkTokenBridge(address caller) internal pure override {␊ + if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ }␊ ␊ // The following functions are overrides required by Solidity.␊ @@ -581,6 +588,7 @@ Generated by [AVA](https://avajs.dev). ␊ contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessManaged {␊ address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ + error Unauthorized();␊ ␊ constructor(address initialAuthority)␊ ERC20("MyToken", "MTK")␊ @@ -588,8 +596,8 @@ Generated by [AVA](https://avajs.dev). AccessManaged(initialAuthority)␊ {}␊ ␊ - function _checkTokenBridge(address caller) internal override {␊ - if (msg.sender != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ + function _checkTokenBridge(address caller) internal pure override {␊ + if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ }␊ }␊ ` diff --git a/packages/core/src/erc20.test.ts.snap b/packages/core/src/erc20.test.ts.snap index 14580891ad24efe2b8b5c3f784b2a55ec1039776..007518e0368dd061cdb6106672b4a0487ac097ff 100644 GIT binary patch literal 2438 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 Igga^g02GON-T(jq diff --git a/packages/core/src/erc20.ts b/packages/core/src/erc20.ts index 15162909d..d234b8167 100644 --- a/packages/core/src/erc20.ts +++ b/packages/core/src/erc20.ts @@ -234,7 +234,7 @@ function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', u c.addOverride(ERC20Bridgeable, functions._checkTokenBridge); if (bridgeable === 'superchain') { c.addVariable('address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;'); - c.setFunctionBody(['if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], functions._checkTokenBridge); + c.setFunctionBody(['if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], functions._checkTokenBridge, 'pure'); } else { if (access === false) { access = 'ownable'; @@ -250,7 +250,7 @@ function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', u c.addConstructorCode(`require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");`); c.addConstructorCode(`TOKEN_BRIDGE = tokenBridge;`); } - c.setFunctionBody([`if (caller != TOKEN_BRIDGE) revert Unauthorized();`], functions._checkTokenBridge); + c.setFunctionBody([`if (caller != TOKEN_BRIDGE) revert Unauthorized();`], functions._checkTokenBridge, 'view'); break; } case 'roles': { @@ -261,7 +261,7 @@ function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', u c.addConstructorArgument({type: 'address', name: roleOwner}); c.addConstructorCode(`_grantRole(${roleId}, ${roleOwner});`); } - c.setFunctionBody([`if (!hasRole(${roleId}, caller)) revert Unauthorized();`], functions._checkTokenBridge); + c.setFunctionBody([`if (!hasRole(${roleId}, caller)) revert Unauthorized();`], functions._checkTokenBridge, 'view'); break; } case 'managed': { @@ -273,11 +273,12 @@ function addBridgeable(c: ContractBuilder, bridgeable: boolean | 'superchain', u `(bool immediate,) = AuthorityUtils.canCallWithDelay(authority(), caller, address(this), bytes4(_msgData()[0:4]));`, `if (!immediate) revert Unauthorized();` ] - c.setFunctionBody(logic, functions._checkTokenBridge); + c.setFunctionBody(logic, functions._checkTokenBridge, 'view'); break; } } } + c.addVariable('error Unauthorized();'); } export const functions = defineFunctions({ From 5094865f5a3487f21adb4b10b0d8d201982450e4 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 16:57:34 -0500 Subject: [PATCH 09/75] Fix access control check --- packages/core/src/generate/erc20.ts | 2 +- packages/core/src/stablecoin.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/generate/erc20.ts b/packages/core/src/generate/erc20.ts index 206fbeb4e..84bed36e0 100644 --- a/packages/core/src/generate/erc20.ts +++ b/packages/core/src/generate/erc20.ts @@ -25,7 +25,7 @@ export const blueprint = { export function* generateERC20Options(): Generator> { for (const opts of generateAlternatives(blueprint)) { - // Only yield options that are not both bridgeable and upgradeable, since ERC20Bridgeable does not currently support usage with upgradeable contracts. + // bridgeable does not currently support upgradeable if (!(opts.bridgeable && opts.upgradeable)) { yield opts; } diff --git a/packages/core/src/stablecoin.ts b/packages/core/src/stablecoin.ts index e28d86ee8..e91eb809b 100644 --- a/packages/core/src/stablecoin.ts +++ b/packages/core/src/stablecoin.ts @@ -2,7 +2,7 @@ import { Contract, ContractBuilder } from './contract'; import { Access, setAccessControl, requireAccessControl } from './set-access-control'; import { defineFunctions } from './utils/define-functions'; import { printContract } from './print'; -import { buildERC20, ERC20Options, defaults as erc20defaults, withDefaults as withERC20Defaults, functions as erc20functions } from './erc20'; +import { buildERC20, ERC20Options, defaults as erc20defaults, withDefaults as withERC20Defaults, functions as erc20functions, isAccessControlRequired as erc20IsAccessControlRequired } from './erc20'; export interface StablecoinOptions extends ERC20Options { limitations?: false | "allowlist" | "blocklist"; @@ -32,7 +32,7 @@ export function printStablecoin(opts: StablecoinOptions = defaults): string { } export function isAccessControlRequired(opts: Partial): boolean { - return opts.mintable || opts.limitations !== false || opts.custodian || opts.pausable || opts.upgradeable === 'uups'; + return erc20IsAccessControlRequired(opts) || opts.limitations !== false || opts.custodian === true; } export function buildStablecoin(opts: StablecoinOptions): Contract { From 4ebd872fa422f4ce0305ca5579db34d4761d8638 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 17:00:20 -0500 Subject: [PATCH 10/75] Update tests --- packages/core/src/erc20.test.ts | 17 +++-- packages/core/src/erc20.test.ts.md | 93 +++++++++++++++++++++++++++ packages/core/src/erc20.test.ts.snap | Bin 2438 -> 2598 bytes 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/packages/core/src/erc20.test.ts b/packages/core/src/erc20.test.ts index 6ab626ff4..18d26a239 100644 --- a/packages/core/src/erc20.test.ts +++ b/packages/core/src/erc20.test.ts @@ -92,11 +92,13 @@ testERC20('erc20 flashmint', { flashmint: true, }); -// TODO test for error -// testERC20('erc20 bridgeable', { -// bridgeable: true, -// access: 'ownable', -// }); +testERC20('erc20 bridgeable', { + bridgeable: true, +}); + +testERC20('erc20 bridgeable ownable', { + bridgeable: true, +}); testERC20('erc20 bridgeable roles', { bridgeable: true, @@ -112,6 +114,11 @@ testERC20('erc20 bridgeable superchain', { bridgeable: 'superchain', }); +testERC20('erc20 bridgeable superchain ownable', { + bridgeable: 'superchain', + access: 'ownable', +}); + testERC20('erc20 bridgeable superchain roles', { bridgeable: 'superchain', access: 'roles', diff --git a/packages/core/src/erc20.test.ts.md b/packages/core/src/erc20.test.ts.md index 35b90e926..5ab6af6d0 100644 --- a/packages/core/src/erc20.test.ts.md +++ b/packages/core/src/erc20.test.ts.md @@ -436,6 +436,70 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## erc20 bridgeable + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, Ownable {␊ + address public immutable TOKEN_BRIDGE;␊ + error Unauthorized();␊ + ␊ + constructor(address initialOwner, address tokenBridge)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + Ownable(initialOwner)␊ + {␊ + require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");␊ + TOKEN_BRIDGE = tokenBridge;␊ + }␊ + ␊ + function _checkTokenBridge(address caller) internal view override {␊ + if (caller != TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + }␊ + ` + +## erc20 bridgeable ownable + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, Ownable {␊ + address public immutable TOKEN_BRIDGE;␊ + error Unauthorized();␊ + ␊ + constructor(address initialOwner, address tokenBridge)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + Ownable(initialOwner)␊ + {␊ + require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");␊ + TOKEN_BRIDGE = tokenBridge;␊ + }␊ + ␊ + function _checkTokenBridge(address caller) internal view override {␊ + if (caller != TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + }␊ + ` + ## erc20 bridgeable roles > Snapshot 1 @@ -532,6 +596,35 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## erc20 bridgeable superchain ownable + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, Ownable {␊ + address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ + error Unauthorized();␊ + ␊ + constructor(address initialOwner)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + Ownable(initialOwner)␊ + {}␊ + ␊ + function _checkTokenBridge(address caller) internal pure override {␊ + if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + }␊ + ` + ## erc20 bridgeable superchain roles > Snapshot 1 diff --git a/packages/core/src/erc20.test.ts.snap b/packages/core/src/erc20.test.ts.snap index 007518e0368dd061cdb6106672b4a0487ac097ff..f7a9d568280ebb0846be806168ba34b6d7d2aecd 100644 GIT binary patch literal 2598 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 IUp#mK03BxU7XSbN literal 2438 zcmV;133>KGRzVlJkO0k`(<;UWJ!Aij&wJm8z* z9xVC=MIVa@00000000B+TuF~3w-uhn0|OfP5Wt5RMgWd{DUGF;tn?UzX?NguciR?b zdO*qK5Fn^3*1{^5 zwq7JnS082|k$ilt_uj|%J+kzDzh_hPlz;aF5?I*ivM`Y9HB`>%5c|rHmW!kx2I5`9z)#O%rk6l)WbgAGw}7kORj#9JDNkI0u+u zfuX&3P7tdFz5KrdXN=qBB*uu*IhPHZU%jpb|Mxv&3QS4hw8*Fd*X!BX1eDmrK$=w9 z|Le*=Yr!{J0Unt|MBGae(rkjG0Rnw$+w>fhlUOPTkRd?N5M$Uv95D2ahZ(X!ZwL;h zkFR7D>3XgO1&W`nZ{|9PJ_%X}9wwswg$yf_Ml9QhUPSQO4*({5Imy z6d0mBKOK_vh63@Qwxf^>fCUl(_BW0Xw-34pdoQ-ZIygn92~XQkJ~pbUhH7oCQV2&D z>O;>K8@*xKpr21?cyO=K8lMy1wN zk5trSlm?-)5^9$NypiHc@Qc9jeI58YkiZjUY2dG}z~4{i2Y)-EiW9hbFLEhQLOA61zvjd zfR`m=?#l%;H^Ta|)rFD-mLzZzjG{6PV#x95)ucXm|D<5k@0Yu(xWuL4#Cv^H84f>L z;fPp>)xk%tRtr1^AGN^a$G}1+cA(9TTHf4DF*l%nP!|6e*W&rYu5UGc3UTjS#c1qa zX|$W$f|qQQ4e&#^6G4Z1M2y}#gTekF*}1T;82ReRy5jw3iraoTkMoEHt}EUgcFkPq z+v)5cX$yU+h8YTdK{~QXC~2Jan2E%Zko#_M_s>mV0`z_Hs90hTZ%$G}##y zT1@x45;lPl~&FUPsOVy<^p%R68Q4sau zLlE4@BA(Mjti*s414<0I1sHIyLV&;y;sQFZ=1Ac03IP0dxsL=&0JtFlh=aoPcbB9J z?z?^L?y5(xKCR`QIczY3J!&O((_FcnQ+t4kXjnKXMmGq$5Dgm>6e!Xl&_N9cUm(kb z9H|O!zS!G*-rd>T+D^1|y%b0#TKcDqU?T0`9rKtMiV(fIc*l5qQ*UxFY|Hjy22nTj;l% zow!G%uM4)}ypn0{^5u#j=K#0(dgLbxyh!byJJ7upH{FkxCHg<1$Aja830p) z@a(rWM_?|P@G@tPzFh%W28aN#;~)z|f$BA|4l@2|Lb3^M`xjUYwvY{n28`N`T7;(Y zhGd8V=CyjbS*{vgho5Xg0gc*kTF+L$s-<>{0H))K$DncUN_Glx0^l+S5ED&>)KDo<%x!8+rV>A7_>s55DXITLWXpQ z91k`sGt#DjJDS?e^zkeZGmf;JS#UdcPGR${BqhkT}Cg4@}hwvM0;Uj#)YNtG33{v z-Om(VPZ=bxxYQyd@fAI>;IdKDQlZy+0}gUlKih#riRalHS Date: Fri, 31 Jan 2025 17:02:54 -0500 Subject: [PATCH 11/75] Test error condition --- packages/core/src/erc20.test.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/core/src/erc20.test.ts b/packages/core/src/erc20.test.ts index 18d26a239..061582ef5 100644 --- a/packages/core/src/erc20.test.ts +++ b/packages/core/src/erc20.test.ts @@ -1,5 +1,5 @@ import test from 'ava'; -import { erc20 } from '.'; +import { erc20, OptionsError } from '.'; import { buildERC20, ERC20Options } from './erc20'; import { printContract } from './print'; @@ -129,9 +129,25 @@ testERC20('erc20 bridgeable superchain managed', { access: 'managed', }); -// TODO test and catch error when bridgeable and upgradeable are both true +test('erc20 bridgeable, upgradeable not allowed', async t => { + let error = t.throws(() => buildERC20({ + name: 'MyToken', + symbol: 'MTK', + bridgeable: true, + upgradeable: 'transparent', + })); + t.is((error as OptionsError).messages.bridgeable, 'Bridgeable does not currently support use in upgradeable contracts'); +}); -// TODO test and catch error when bridgeable is 'superchain' and upgradeable is true +test('erc20 bridgeable superchain, upgradeable not allowed', async t => { + let error = t.throws(() => buildERC20({ + name: 'MyToken', + symbol: 'MTK', + bridgeable: 'superchain', + upgradeable: 'transparent', + })); + t.is((error as OptionsError).messages.bridgeable, 'Bridgeable does not currently support use in upgradeable contracts'); +}); testERC20('erc20 full upgradeable transparent', { premint: '2000', From 9e20d68bfd0f1eab0461d26b9511f2a716b15c43 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 17:22:50 -0500 Subject: [PATCH 12/75] Disable Upgradeable when Bridgeable --- packages/ui/src/ERC20Controls.svelte | 4 +-- packages/ui/src/UpgradeabilitySection.svelte | 27 +++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/ui/src/ERC20Controls.svelte b/packages/ui/src/ERC20Controls.svelte index 24043b501..4f925b2d1 100644 --- a/packages/ui/src/ERC20Controls.svelte +++ b/packages/ui/src/ERC20Controls.svelte @@ -107,7 +107,7 @@

- - -
From 62f612f7e40f849bec9076ee92fdca4dc7fb7a9f Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 31 Jan 2025 18:43:03 -0500 Subject: [PATCH 19/75] Move section, fix grammar --- packages/ui/src/ERC20Controls.svelte | 59 +++++++++---------- packages/ui/src/RealWorldAssetControls.svelte | 2 +- packages/ui/src/StablecoinControls.svelte | 2 +- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/packages/ui/src/ERC20Controls.svelte b/packages/ui/src/ERC20Controls.svelte index 98ade2f6b..55733556d 100644 --- a/packages/ui/src/ERC20Controls.svelte +++ b/packages/ui/src/ERC20Controls.svelte @@ -98,36 +98,6 @@
-
-

- - -

- -
- -
- -
- * Experimental: These features are not audited and subject to change -
- -
-

@@ -160,6 +130,35 @@

+
+

+ + +

+ +
+ +
+ +
+ * Experimental: This feature is not audited and is subject to change +
+
+ diff --git a/packages/ui/src/RealWorldAssetControls.svelte b/packages/ui/src/RealWorldAssetControls.svelte index 171e1c03d..1c7eef4ad 100644 --- a/packages/ui/src/RealWorldAssetControls.svelte +++ b/packages/ui/src/RealWorldAssetControls.svelte @@ -22,7 +22,7 @@
- * Experimental: Some of the following features are not audited and subject to change + * Experimental: Some of the following features are not audited and are subject to change
diff --git a/packages/ui/src/StablecoinControls.svelte b/packages/ui/src/StablecoinControls.svelte index a7363a4e1..49b24a499 100644 --- a/packages/ui/src/StablecoinControls.svelte +++ b/packages/ui/src/StablecoinControls.svelte @@ -20,7 +20,7 @@
- * Experimental: Some of the following features are not audited and subject to change + * Experimental: Some of the following features are not audited and are subject to change
From c69331624042d9b23c8e6ab01aa7d716637f0169 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 11:22:59 -0500 Subject: [PATCH 20/75] Update lockfile --- yarn.lock | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0c990aae4..50421359d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== +"@axelar-network/axelar-gmp-sdk-solidity@^5.10.0": + version "5.10.0" + resolved "https://registry.yarnpkg.com/@axelar-network/axelar-gmp-sdk-solidity/-/axelar-gmp-sdk-solidity-5.10.0.tgz#9679b0634e4db6eb345aac800df6dd3a38d2e242" + integrity sha512-s8SImALvYB+5AeiT3tbfWNBI2Mhqw1x91i/zM3DNpVUCnAR2HKtsB9T84KnUn/OJjOVgb4h0lv7q9smeYniRPw== + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" @@ -464,17 +469,16 @@ "@openzeppelin/community-contracts@https://github.com/OpenZeppelin/openzeppelin-community-contracts": version "0.0.1" - resolved "https://github.com/OpenZeppelin/openzeppelin-community-contracts#e3406d834031e7a83b2ceb395d6620fbe22ba6ce" + resolved "https://github.com/OpenZeppelin/openzeppelin-community-contracts#4d029e17c22d8ece6eb94604e55306c7017cbdb2" dependencies: - "@openzeppelin/contracts" "^5.0.2" - "@openzeppelin/contracts-upgradeable" "^5.0.2" + "@axelar-network/axelar-gmp-sdk-solidity" "^5.10.0" -"@openzeppelin/contracts-upgradeable@^5.0.2", "@openzeppelin/contracts-upgradeable@^5.1.0": +"@openzeppelin/contracts-upgradeable@^5.1.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.2.0.tgz#caf9a6eaf4f16d7f90f9b45a6db4e7b125f4b13b" integrity sha512-mZIu9oa4tQTlGiOJHk6D3LdJlqFqF6oNOSn6S6UVJtzfs9UsY9/dhMEbAVTwElxUtJnjpf6yA062+oBp+eOyPg== -"@openzeppelin/contracts@^5.0.2", "@openzeppelin/contracts@^5.1.0": +"@openzeppelin/contracts@^5.1.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.2.0.tgz#bd020694218202b811b0ea3eec07277814c658da" integrity sha512-bxjNie5z89W1Ea0NZLZluFh8PrFNn9DH8DQlujEok2yjsOlraUPKID5p1Wk3qdNbf6XkQ1Os2RvfiHrrXLHWKA== From dc645f19a194e8b7dc2e23999c17c1be30f7f8ab Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 11:41:06 -0500 Subject: [PATCH 21/75] Update workflow --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 70d51847e..ed987bc59 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,9 @@ jobs: if: matrix.package == 'core' uses: foundry-rs/foundry-toolchain@v1 - name: Install dependencies - run: yarn install --network-concurrency 1 + run: yarn install + - name: Install husky (for community-contracts repo) + run: yarn global add husky - name: Compile TypeScript run: yarn tsc working-directory: packages/${{matrix.package}} From 24502aedff8e1b30fffe8853bd666c0a7b45dece Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 11:43:38 -0500 Subject: [PATCH 22/75] Update workflow --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ed987bc59..e8fc7756d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,10 +23,10 @@ jobs: - name: Install Foundry if: matrix.package == 'core' uses: foundry-rs/foundry-toolchain@v1 - - name: Install dependencies - run: yarn install - name: Install husky (for community-contracts repo) run: yarn global add husky + - name: Install dependencies + run: yarn install - name: Compile TypeScript run: yarn tsc working-directory: packages/${{matrix.package}} From c48e4b746599b3c75cf3eb1d98045f96aa9c94fa Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 11:51:59 -0500 Subject: [PATCH 23/75] Update netlify.toml --- netlify.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/netlify.toml b/netlify.toml index eb5616b93..0d85a2e76 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,12 +1,9 @@ [build] -command = "yarn --cwd packages/ui build" +command = "yarn global add husky && yarn --cwd packages/ui build" publish = "packages/ui/public" edge_functions = "packages/ui/api" -[build.environment] - YARN_FLAGS = "--network-concurrency 1" - [[edge_functions]] path = "/ai" function = "ai" \ No newline at end of file From 32ba77862907397b87c4b1b7c8db833a1361a819 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 12:00:23 -0500 Subject: [PATCH 24/75] Move husky to prepare --- netlify.toml | 2 +- packages/core/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/netlify.toml b/netlify.toml index 0d85a2e76..1dada69e3 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,5 +1,5 @@ [build] -command = "yarn global add husky && yarn --cwd packages/ui build" +command = "yarn --cwd packages/ui build" publish = "packages/ui/public" edge_functions = "packages/ui/api" diff --git a/packages/core/package.json b/packages/core/package.json index ae5744f89..b459c2ba7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -14,7 +14,7 @@ "!**/*.test.*" ], "scripts": { - "prepare": "tsc && node dist/scripts/prepare.js", + "prepare": "yarn global add husky && tsc && node dist/scripts/prepare.js", "prepublish": "rimraf dist *.tsbuildinfo && hardhat clean", "test": "ava", "test:watch": "ava --watch", From 03b47a87bc4c0ef761592eec5ad819c0626b01b1 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 12:05:01 -0500 Subject: [PATCH 25/75] Move husky to devDependencies --- packages/core/package.json | 5 +++-- yarn.lock | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index b459c2ba7..730e88cc2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -14,7 +14,7 @@ "!**/*.test.*" ], "scripts": { - "prepare": "yarn global add husky && tsc && node dist/scripts/prepare.js", + "prepare": "husky && tsc && node dist/scripts/prepare.js", "prepublish": "rimraf dist *.tsbuildinfo && hardhat clean", "test": "ava", "test:watch": "ava --watch", @@ -34,6 +34,7 @@ "semver": "^7.6.0", "solidity-ast": "^0.4.18", "ts-node": "^10.4.0", - "typescript": "^5.0.0" + "typescript": "^5.0.0", + "husky": "^9.1.7" } } diff --git a/yarn.lock b/yarn.lock index 50421359d..0a8ef8484 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2664,6 +2664,11 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +husky@^9.1.7: + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" From 08f8ccdd25061a3bf017bf211ee424ecd20f9fd0 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 12:06:09 -0500 Subject: [PATCH 26/75] Revert workflow --- .github/workflows/test.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e8fc7756d..6845f84d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,8 +23,6 @@ jobs: - name: Install Foundry if: matrix.package == 'core' uses: foundry-rs/foundry-toolchain@v1 - - name: Install husky (for community-contracts repo) - run: yarn global add husky - name: Install dependencies run: yarn install - name: Compile TypeScript From b9d0efa3f444c26807e78df08a4d36eacfd70883 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 12:07:33 -0500 Subject: [PATCH 27/75] Update ui devDependencies --- packages/ui/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ui/package.json b/packages/ui/package.json index ff020ee05..e0a25fee8 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -33,7 +33,8 @@ "svelte-preprocess": "^5.0.0", "tailwindcss": "^3.0.15", "tslib": "^2.0.0", - "typescript": "^5.0.0" + "typescript": "^5.0.0", + "husky": "^9.1.7" }, "dependencies": { "file-saver": "^2.0.5", From e49b4caf86b6317499b91e0970cff6722e251ce6 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 12:57:24 -0500 Subject: [PATCH 28/75] Test use fork --- packages/core/package.json | 7 +++---- packages/ui/package.json | 3 +-- yarn.lock | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 730e88cc2..a95f72387 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -14,7 +14,7 @@ "!**/*.test.*" ], "scripts": { - "prepare": "husky && tsc && node dist/scripts/prepare.js", + "prepare": "tsc && node dist/scripts/prepare.js", "prepublish": "rimraf dist *.tsbuildinfo && hardhat clean", "test": "ava", "test:watch": "ava --watch", @@ -22,7 +22,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/community-contracts": "https://github.com/ericglau/openzeppelin-community-contracts", "@openzeppelin/contracts": "^5.1.0", "@openzeppelin/contracts-upgradeable": "^5.1.0", "@types/node": "^18.0.0", @@ -34,7 +34,6 @@ "semver": "^7.6.0", "solidity-ast": "^0.4.18", "ts-node": "^10.4.0", - "typescript": "^5.0.0", - "husky": "^9.1.7" + "typescript": "^5.0.0" } } diff --git a/packages/ui/package.json b/packages/ui/package.json index e0a25fee8..ff020ee05 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -33,8 +33,7 @@ "svelte-preprocess": "^5.0.0", "tailwindcss": "^3.0.15", "tslib": "^2.0.0", - "typescript": "^5.0.0", - "husky": "^9.1.7" + "typescript": "^5.0.0" }, "dependencies": { "file-saver": "^2.0.5", diff --git a/yarn.lock b/yarn.lock index 0a8ef8484..876baece9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -467,9 +467,9 @@ "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" -"@openzeppelin/community-contracts@https://github.com/OpenZeppelin/openzeppelin-community-contracts": +"@openzeppelin/community-contracts@https://github.com/ericglau/openzeppelin-community-contracts": version "0.0.1" - resolved "https://github.com/OpenZeppelin/openzeppelin-community-contracts#4d029e17c22d8ece6eb94604e55306c7017cbdb2" + resolved "https://github.com/ericglau/openzeppelin-community-contracts#6a1c66e39002fadfbc1b7b707d63ca03c60fce79" dependencies: "@axelar-network/axelar-gmp-sdk-solidity" "^5.10.0" From f627cea1e3ad03e5cf3bb664f2df962c67110ea4 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 13:35:33 -0500 Subject: [PATCH 29/75] Simplify test matrix --- packages/core/src/generate/erc20.ts | 6 ++-- packages/core/src/generate/stablecoin.ts | 38 +++++++++++++++++++++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/packages/core/src/generate/erc20.ts b/packages/core/src/generate/erc20.ts index 84bed36e0..24ecceafe 100644 --- a/packages/core/src/generate/erc20.ts +++ b/packages/core/src/generate/erc20.ts @@ -7,7 +7,9 @@ import { generateAlternatives } from './alternatives'; const booleans = [true, false]; -export const blueprint = { +export const bridgeableOptions = [ ...booleans, 'superchain' ] as const; + +const blueprint = { name: ['MyToken'], symbol: ['MTK'], burnable: booleans, @@ -17,7 +19,7 @@ export const blueprint = { votes: [ ...booleans, ...clockModeOptions ] as const, flashmint: booleans, premint: ['1'], - bridgeable: [ ...booleans, 'superchain' ] as const, + bridgeable: bridgeableOptions, access: accessOptions, upgradeable: upgradeableOptions, info: infoOptions, diff --git a/packages/core/src/generate/stablecoin.ts b/packages/core/src/generate/stablecoin.ts index 9c36a4799..b99078b04 100644 --- a/packages/core/src/generate/stablecoin.ts +++ b/packages/core/src/generate/stablecoin.ts @@ -1,18 +1,48 @@ +import { accessOptions } from '../set-access-control'; +import { infoOptions } from '../set-info'; import type { StablecoinOptions } from '../stablecoin'; import { generateAlternatives } from './alternatives'; -import { blueprint as erc20Blueprint } from './erc20'; +import { bridgeableOptions } from './erc20'; const booleans = [true, false]; -const blueprint = { - ...erc20Blueprint, +const erc20Basic = { name: ['MyStablecoin'], symbol: ['MST'], + burnable: [false] as const, + pausable: [false] as const, + mintable: [false] as const, + permit: [false] as const, + votes: [false] as const, + flashmint: [false] as const, + premint: ['1'], + bridgeable: [false] as const, + access: [false] as const, + info: [{}] as const, +} + +const erc20Full = { + name: ['MyStablecoin'], + symbol: ['MST'], + burnable: [true] as const, + pausable: [true] as const, + mintable: [true] as const, + permit: [true] as const, + votes: ['timestamp'] as const, + flashmint: [true] as const, + premint: ['1'], + bridgeable: bridgeableOptions, + access: accessOptions, + info: infoOptions, +}; + +const stablecoinExtensions = { limitations: [false, 'allowlist', 'blocklist'] as const, custodian: booleans, upgradeable: [false] as const, }; export function* generateStablecoinOptions(): Generator> { - yield* generateAlternatives(blueprint); + yield* generateAlternatives({ ...erc20Basic, ...stablecoinExtensions }); + yield* generateAlternatives({ ...erc20Full, ...stablecoinExtensions }); } From 93cadf7c4225063879ca8a1401ec90f08d371754 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 13:35:42 -0500 Subject: [PATCH 30/75] Update lock --- yarn.lock | 5 ----- 1 file changed, 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 876baece9..bfb293001 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2664,11 +2664,6 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" -husky@^9.1.7: - version "9.1.7" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" - integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== - iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" From 35acf7fb7be6cb63818b817851870473aad0f59c Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Mon, 3 Feb 2025 17:15:52 -0500 Subject: [PATCH 31/75] Use latest Community Contracts --- packages/core/package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index a95f72387..ae5744f89 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -22,7 +22,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/ericglau/openzeppelin-community-contracts", + "@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", diff --git a/yarn.lock b/yarn.lock index bfb293001..48390e451 100644 --- a/yarn.lock +++ b/yarn.lock @@ -467,9 +467,9 @@ "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" -"@openzeppelin/community-contracts@https://github.com/ericglau/openzeppelin-community-contracts": +"@openzeppelin/community-contracts@https://github.com/OpenZeppelin/openzeppelin-community-contracts": version "0.0.1" - resolved "https://github.com/ericglau/openzeppelin-community-contracts#6a1c66e39002fadfbc1b7b707d63ca03c60fce79" + resolved "https://github.com/OpenZeppelin/openzeppelin-community-contracts#3b1a9faa527386b12795305dc919f68d3e934be2" dependencies: "@axelar-network/axelar-gmp-sdk-solidity" "^5.10.0" From bd5c2f08f9c31a4d8d61febad8c06f697fc0d926 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 5 Feb 2025 17:06:28 -0500 Subject: [PATCH 32/75] Fix merge --- packages/core/solidity/src/erc20.test.ts.snap | Bin 1968 -> 2594 bytes packages/core/src/erc20.test.ts.snap | Bin 2583 -> 0 bytes packages/core/src/stablecoin.test.ts.snap | Bin 1683 -> 0 bytes packages/core/src/stablecoin.ts | 167 ------------------ 4 files changed, 167 deletions(-) delete mode 100644 packages/core/src/erc20.test.ts.snap delete mode 100644 packages/core/src/stablecoin.test.ts.snap delete mode 100644 packages/core/src/stablecoin.ts diff --git a/packages/core/solidity/src/erc20.test.ts.snap b/packages/core/solidity/src/erc20.test.ts.snap index c81f7040b3c1f8e83bb45d14b9421e0f20d70fc4..b6a315ebffa1ab064096359786b861280cefcacc 100644 GIT binary patch literal 2594 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 E0N0266951J literal 1968 zcmV;h2T%AxRzVO9| zEhR=fqqT)+q=}^QdhPlUdhD(LApI4+_1IgX$KHA@6ng2cP$)B_`OvIpy}P#8yYcvt zFe~ZRt9c(idLK!lY>nhneebod?>{Pi2tgaUpw_x+7) z?_Tr%=H9vX-t}+i>UFTWzVu~v6&r|fR9!I<5x9d9dkk7DTZMWZEK=Kn0=F#$x>)Ri zH3yNek>el>6R=2$V9*d8ynIk=)EWhc!Ce~yPAzO=(E~3VwMVsPbG}f(wnLc!$IBaw z&Bh7nFlvM1Q|cgcB(2qr&{|#4eMIVh)!^S6r&e)ZHL{MFjm0RY(4jztV@h~EVL{q1 zgl#~px8*egm;=9B1te;N;{pHx7?g0qTtiS+DhK7IqHI{KfMRRwd9j>q7nhd7@k!yN zAR|WnSb?_72y9zO6SRMop#3%5LHkUO^DJQtZA=3wLSH6<5eK?lkCB_#6^#6IW2P~( zF2{MMC`ua>z({C&tveL5p$3LH_%2OfD8e8fEdFj;((!7E@sFC?H<^a7_X%q*>N2c3KYFr zFU%DXJ_%X@E+(S+;2}7GmW$%og^56nKr8wn?6;(guzZhEW$rqN)xyq$PQA{8PQu|v zTygk;N*2N7X4FDl!yCUSyz$e`OW=(Ke?IsPsWs%}QQGLH_*LYg5jaG7e>x^<_XOgf zG{Y(96AL5)tS@YDE^q8?tgSACCtx2L2HbBxcvvbX3X0|VLM9!Vr~_R~ESNSX@#OL6 z?g;cWh=5{F*kzE24Qip%((xHu&J1p{JrrEN}wW742}epX-=@mm2Pa%tTaQ zdUqigfw>4AhNGxVgBY^Cel@Aj+@A_J{XW~fic_-{90GwM13MTIao(E7i)SgaUIF(T zjRv?2?l-{QyTC*SwxPvK<$g#o1rmUEKz=|lO9upA)bwe__18+!*!4VUlUt@|Y$5jP zL$_K%o4P~{US9piUL#pKbMG<4>cG9n8;=#(-n)!5iz(iFoE&$Jy&2eAd9kJ43``V^ zu^H&6EK|1`m>5$fbWxwHjxxv6rpqJEH%qSR{@C-?d=^&o{UBrqRA@QzS0!RU&-gj+ z#VqB1$rs)WJd0`HK+5t9N{rL3x&m9g9@HHTO!C3+`ka6@a|+iV{CM(K^^^Dkh}@)V zQWS7(^mu?#H^Z+mG(kXP3k(UD5e`anxM`n*a_PEsCU7D%FY;$SxCi_@Tg0{7h~*rR zb3o1kSAYY$Dg_8^BQBurXpRm3Pzd0+**-SN31C755KRihTV3Lvau4`l#Fw z=AfYDuTixKrhQxLoLYOBh^mSG4eKgFhoWj>f_z7+1lp)-<3nT`kR#Q>#nrXN=R2*n zrRCU5$4!t_?4@@SNp^vaY|45XXNxv9(UZu_;>>RRUqwokrxYCv@;y)MY832$3Kjl6 z+Y0uXH_#R)XJW(1$n3-%q*?&4*c*jRRkCoK@{o8r!o~Q14>Yk_Wm!GME(Lj|Ql#>~BBc`bJS%t;;(gkza{Do66FDDLPkMx!TIrR<5?DNp1C0)5WW;X%Z*t zA3o3sk|~xOGI~LI-)}ffq5K$4A57WrON^Ye>y1w`QI9>ybMq^loBt24Q!SF3RR92Z CWxR<1 diff --git a/packages/core/src/erc20.test.ts.snap b/packages/core/src/erc20.test.ts.snap deleted file mode 100644 index 4fc0046e10e7eceb7fef5f8b6a6b3177ef684cfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2583 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 diff --git a/packages/core/src/stablecoin.test.ts.snap b/packages/core/src/stablecoin.test.ts.snap deleted file mode 100644 index 4770f427f16c01af215014a985ad894abf7af02f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1683 zcmV;E25k93RzV}#+WvkR|!XkG)qG;DaIG}15);wh2 zpy#1O87y+91hJHaZyz*TjaJDMWXB~SxkGKL`tWV5@u)F3H(x4I*W*IL(elRPTYGRLxoII&SW#C5NVgW-LSowjr3A{TqQqG{U?{4(Rqz{?pr%nY zQe}ihej4jGN5>`of6r%@qCCuDtW?4CyAHL0GpDa5BjbbLcGPBG|7B3XXJ?Txtui9b zCT#5@^tj{j1Il)cssths_&y3jZImGJg--?A(Cx!!l=6)ML$-a-CJN0Q2T`v5l z`R4M*_Qu-kGAzIzS{B)xd+@MQPTeS1=SxEoWn+){j%wR3Wyvzqt9V>woeHId6FY)1 zwZR>%EG<86KVRM2ZZCCKo@sMy8JnV|HP9>NT`e{?pIbT98dRvB4}v4*ra+8=2t$GB z5=M5=&OzdQ28p%HLt-a1@r+0e9TLq<-zgf;gT`nQ$J}_eeYML4RsAtZmKn2hir6`} zVFINR)KX|qj-Y&vDR*M-+|8)~j5^YNpJC36Vjt;Vdnuq;?0IuX#=&yM^aMFQL5>G5 zmEJE2bc4Zj_DC~-WO(&!u}hcNrv{y5bP&0UD|Z?anT?_b_gk$N+=KfqxOWe1w5UrQ zS*e~(frFDN0K5mS>6?h6WWkV%auCTOZz6uo1oGwVG>~uj@m<&lwB}6SQ;fLWXKM6g zS9cCNMU6)nG~@goSl1b&qH>U;7OJv-{6~@lWv#s0;W9r5P6-K?Exxy93ly|k* z*!+F%IO}du`s7Ao)Eaz|-Vf+mnC=7$xD!b4>@8m^Zc~!;b;+#{GLd|**p-OI*wJBX zuIn?Z`t?NjYymdH*JT5e8aBExE}GrR>)DW;hS$-XmJ=J2Z7PlB#ytJ1#+;;KpW=Zz zMuR}*3nrn`<=jcLF}$HW!@>gaVAKMa2+XuxV2ywTemhj=JQHrWG9>xF&UWj8NpYdO(LD{RcyMNd?+qmPjg{%x_T+P?sJt}L;Nd4*55Cq zhInPG85!*_g9$v3v=$gpe#V(~x~i|JBb#B{$b zYc7Lh_z=6|AcgTw6wFyYa(B??=*S+L9vKrFG5XztCINgBK9iX5c2P{ZFy+FO3vVG8 z?&feoQ5U5mu9s6W|0hF*zl&WlpHks+s9;u#6+D5G&((&Ms)IED>``8^THmPX=UBsJ z?TNFD=f000FwPC@_x diff --git a/packages/core/src/stablecoin.ts b/packages/core/src/stablecoin.ts deleted file mode 100644 index e91eb809b..000000000 --- a/packages/core/src/stablecoin.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { Contract, ContractBuilder } from './contract'; -import { Access, setAccessControl, requireAccessControl } from './set-access-control'; -import { defineFunctions } from './utils/define-functions'; -import { printContract } from './print'; -import { buildERC20, ERC20Options, defaults as erc20defaults, withDefaults as withERC20Defaults, functions as erc20functions, isAccessControlRequired as erc20IsAccessControlRequired } from './erc20'; - -export interface StablecoinOptions extends ERC20Options { - limitations?: false | "allowlist" | "blocklist"; - custodian?: boolean; -} - -export const defaults: Required = { - ...erc20defaults, - name: 'MyStablecoin', - symbol: 'MST', - limitations: false, - custodian: false, -} as const; - -function withDefaults(opts: StablecoinOptions): Required { - return { - ...withERC20Defaults(opts), - name: opts.name ?? defaults.name, - symbol: opts.symbol ?? defaults.symbol, - limitations: opts.limitations ?? defaults.limitations, - custodian: opts.custodian ?? defaults.custodian, - }; -} - -export function printStablecoin(opts: StablecoinOptions = defaults): string { - return printContract(buildStablecoin(opts)); -} - -export function isAccessControlRequired(opts: Partial): boolean { - return erc20IsAccessControlRequired(opts) || opts.limitations !== false || opts.custodian === true; -} - -export function buildStablecoin(opts: StablecoinOptions): Contract { - const allOpts = withDefaults(opts); - - // Upgradeability is not yet available for the community contracts - allOpts.upgradeable = false; - - const c = buildERC20(allOpts); - - if (allOpts.custodian) { - addCustodian(c, allOpts.access); - } - - if (allOpts.limitations) { - addLimitations(c, allOpts.access, allOpts.limitations); - } - - return c; -} - -function addLimitations(c: ContractBuilder, access: Access, mode: boolean | 'allowlist' | 'blocklist') { - const type = mode === 'allowlist'; - const ERC20Limitation = { - name: type ? 'ERC20Allowlist' : 'ERC20Blocklist', - path: `@openzeppelin/community-contracts/contracts/token/ERC20/extensions/${type ? 'ERC20Allowlist' : 'ERC20Blocklist'}.sol`, - }; - - c.addParent(ERC20Limitation); - c.addOverride(ERC20Limitation, functions._update); - c.addOverride(ERC20Limitation, functions._approve); - - const [addFn, removeFn] = type - ? [functions.allowUser, functions.disallowUser] - : [functions.blockUser, functions.unblockUser]; - - requireAccessControl(c, addFn, access, 'LIMITER', 'limiter'); - c.addFunctionCode(`_${type ? 'allowUser' : 'blockUser'}(user);`, addFn); - - requireAccessControl(c, removeFn, access, 'LIMITER', 'limiter'); - c.addFunctionCode(`_${type ? 'disallowUser' : 'unblockUser'}(user);`, removeFn); -} - -function addCustodian(c: ContractBuilder, access: Access) { - const ERC20Custodian = { - name: 'ERC20Custodian', - path: '@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Custodian.sol', - }; - - c.addParent(ERC20Custodian); - c.addOverride(ERC20Custodian, functions._update); - c.addOverride(ERC20Custodian, functions._isCustodian); - - if (access === false) { - access = 'ownable'; - } - - setAccessControl(c, access); - - switch (access) { - case 'ownable': { - c.setFunctionBody([`return user == owner();`], functions._isCustodian); - break; - } - case 'roles': { - const roleOwner = 'custodian'; - const roleId = 'CUSTODIAN_ROLE'; - const addedConstant = c.addVariable(`bytes32 public constant ${roleId} = keccak256("${roleId}");`); - if (addedConstant) { - c.addConstructorArgument({type: 'address', name: roleOwner}); - c.addConstructorCode(`_grantRole(${roleId}, ${roleOwner});`); - } - c.setFunctionBody([`return hasRole(${roleId}, user);`], functions._isCustodian); - break; - } - case 'managed': { - c.addImportOnly({ - name: 'AuthorityUtils', - path: `@openzeppelin/contracts/access/manager/AuthorityUtils.sol`, - }); - const logic = [ - `(bool immediate,) = AuthorityUtils.canCallWithDelay(authority(), user, address(this), bytes4(_msgData()[0:4]));`, - `return immediate;` - ] - c.setFunctionBody(logic, functions._isCustodian); - break; - } - } -} - -const functions = { - ...erc20functions, - ...defineFunctions({ - _isCustodian: { - kind: 'internal' as const, - args: [ - { name: 'user', type: 'address' }, - ], - returns: ['bool'], - mutability: 'view' as const - }, - - allowUser: { - kind: 'public' as const, - args: [ - { name: 'user', type: 'address' } - ], - }, - - disallowUser: { - kind: 'public' as const, - args: [ - { name: 'user', type: 'address' } - ], - }, - - blockUser: { - kind: 'public' as const, - args: [ - { name: 'user', type: 'address' } - ], - }, - - unblockUser: { - kind: 'public' as const, - args: [ - { name: 'user', type: 'address' } - ], - }, - }) -}; - From 74351a79588cae069a671f88de1b577fd76b342a Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 5 Feb 2025 18:18:29 -0500 Subject: [PATCH 33/75] Change Bridgeable to use radio buttons --- packages/ui/src/solidity/ERC20Controls.svelte | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/ui/src/solidity/ERC20Controls.svelte b/packages/ui/src/solidity/ERC20Controls.svelte index b9953733c..5021163b1 100644 --- a/packages/ui/src/solidity/ERC20Controls.svelte +++ b/packages/ui/src/solidity/ERC20Controls.svelte @@ -18,13 +18,6 @@ }; $: requireAccessControl = erc20.isAccessControlRequired(opts); - - $: superchainSelected = opts.bridgeable === 'superchain'; - - const toggleSuperchain = () => { - // Set the inverse - opts.bridgeable = superchainSelected ? true : 'superchain'; - };
@@ -145,8 +138,16 @@
-

@@ -146,7 +170,7 @@ - Read more.', trigger: 'manual', placement: 'bottom', maxWidth: '22em', allowHTML: true, + interactive: true, }); }); From c3937f3e1d19d0c2666f04b1ba5f5e4748a278e0 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 12 Feb 2025 17:51:31 -0500 Subject: [PATCH 40/75] Change grammar --- packages/ui/src/solidity/ERC20Controls.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/solidity/ERC20Controls.svelte b/packages/ui/src/solidity/ERC20Controls.svelte index 984067678..a3a4ac4b6 100644 --- a/packages/ui/src/solidity/ERC20Controls.svelte +++ b/packages/ui/src/solidity/ERC20Controls.svelte @@ -181,7 +181,7 @@
- * Experimental: This feature is not audited and is subject to change + * Experimental: These features are not audited and are subject to change

From 5b12099767a5c3eebffb10058753561442a3b8b9 Mon Sep 17 00:00:00 2001 From: makiopen Date: Thu, 13 Feb 2025 13:13:23 +0100 Subject: [PATCH 41/75] experimental, tooltip and disabled messages --- packages/ui/src/solidity/ERC20Controls.svelte | 11 ++++++----- packages/ui/src/solidity/UpgradeabilitySection.svelte | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/ui/src/solidity/ERC20Controls.svelte b/packages/ui/src/solidity/ERC20Controls.svelte index a3a4ac4b6..8bcae3977 100644 --- a/packages/ui/src/solidity/ERC20Controls.svelte +++ b/packages/ui/src/solidity/ERC20Controls.svelte @@ -161,6 +161,9 @@ +
+ * Experimental: These features are not audited and are subject to change +
-
- * Experimental: These features are not audited and are subject to change -
+ diff --git a/packages/ui/src/solidity/UpgradeabilitySection.svelte b/packages/ui/src/solidity/UpgradeabilitySection.svelte index b8c6b696c..a800b7535 100644 --- a/packages/ui/src/solidity/UpgradeabilitySection.svelte +++ b/packages/ui/src/solidity/UpgradeabilitySection.svelte @@ -41,7 +41,7 @@ - +
Upgradeability is not available with Cross-chain bridging.
-
Upgradeability is not available with Cross-chain bridging.
+
Upgradeability is not currently supported with Cross-Chain Bridging.
- - diff --git a/packages/ui/src/solidity/RealWorldAssetControls.svelte b/packages/ui/src/solidity/RealWorldAssetControls.svelte index 83cbb4085..596e61c7d 100644 --- a/packages/ui/src/solidity/RealWorldAssetControls.svelte +++ b/packages/ui/src/solidity/RealWorldAssetControls.svelte @@ -7,6 +7,7 @@ import AccessControlSection from './AccessControlSection.svelte'; import InfoSection from './InfoSection.svelte'; import ToggleRadio from '../common/inputs/ToggleRadio.svelte'; + import OPIcon from '../common/icons/OPIcon.svelte'; export let opts: Required = { kind: 'RealWorldAsset', @@ -18,6 +19,31 @@ }; $: requireAccessControl = realWorldAsset.isAccessControlRequired(opts); + + // Show notice when SuperchainERC20 is enabled + import tippy, { Instance as TippyInstance } from 'tippy.js'; + import { onMount } from 'svelte'; + + let superchainLabel: HTMLElement; + let superchainTooltip: TippyInstance; + onMount(() => { + superchainTooltip = tippy(superchainLabel, { + content: 'Important: Requires deploying your contract to the same address on every chain in the Superchain. Read more.', + trigger: 'manual', + placement: 'bottom', + maxWidth: '22em', + allowHTML: true, + interactive: true, + }); + }); + + let wasSuperchain = false; + $: { + if (!wasSuperchain && opts.bridgeable === 'superchain') { + superchainTooltip.show(); + } + wasSuperchain = opts.bridgeable === 'superchain'; + }
@@ -169,6 +195,42 @@
+
+

+ + +

+
+ * Experimental: These features are not audited and are subject to change +
+ +
+ + + +
+
+ diff --git a/packages/ui/src/solidity/StablecoinControls.svelte b/packages/ui/src/solidity/StablecoinControls.svelte index b931ca610..d335f3e3f 100644 --- a/packages/ui/src/solidity/StablecoinControls.svelte +++ b/packages/ui/src/solidity/StablecoinControls.svelte @@ -7,6 +7,7 @@ import AccessControlSection from './AccessControlSection.svelte'; import InfoSection from './InfoSection.svelte'; import ToggleRadio from '../common/inputs/ToggleRadio.svelte'; + import OPIcon from '../common/icons/OPIcon.svelte'; export let opts: Required = { kind: 'Stablecoin', @@ -16,6 +17,31 @@ }; $: requireAccessControl = stablecoin.isAccessControlRequired(opts); + + // Show notice when SuperchainERC20 is enabled + import tippy, { Instance as TippyInstance } from 'tippy.js'; + import { onMount } from 'svelte'; + + let superchainLabel: HTMLElement; + let superchainTooltip: TippyInstance; + onMount(() => { + superchainTooltip = tippy(superchainLabel, { + content: 'Important: Requires deploying your contract to the same address on every chain in the Superchain. Read more.', + trigger: 'manual', + placement: 'bottom', + maxWidth: '22em', + allowHTML: true, + interactive: true, + }); + }); + + let wasSuperchain = false; + $: { + if (!wasSuperchain && opts.bridgeable === 'superchain') { + superchainTooltip.show(); + } + wasSuperchain = opts.bridgeable === 'superchain'; + }
@@ -167,6 +193,42 @@
+
+

+ + +

+
+ * Experimental: These features are not audited and are subject to change +
+ +
+ + + +
+
+ From 62d1240cfd4a1df07e8cda761c3538de855f0e49 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 18 Feb 2025 16:10:06 -0500 Subject: [PATCH 49/75] Adjust experimental markers on Stablecoin and RWA UIs --- .../ui/src/solidity/RealWorldAssetControls.svelte | 11 ++++------- packages/ui/src/solidity/StablecoinControls.svelte | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/ui/src/solidity/RealWorldAssetControls.svelte b/packages/ui/src/solidity/RealWorldAssetControls.svelte index 596e61c7d..45e349c2b 100644 --- a/packages/ui/src/solidity/RealWorldAssetControls.svelte +++ b/packages/ui/src/solidity/RealWorldAssetControls.svelte @@ -123,7 +123,7 @@ diff --git a/packages/ui/src/solidity/RealWorldAssetControls.svelte b/packages/ui/src/solidity/RealWorldAssetControls.svelte index 9f713cc5a..4641387e7 100644 --- a/packages/ui/src/solidity/RealWorldAssetControls.svelte +++ b/packages/ui/src/solidity/RealWorldAssetControls.svelte @@ -216,7 +216,7 @@ SuperchainERC20*   - Uses the predeployed SuperchainTokenBridge contract on OP Chains as the authorized token bridge. + Uses the predeployed SuperchainTokenBridge contract as the authorized token bridge. Only available on chains in the Superchain. diff --git a/packages/ui/src/solidity/StablecoinControls.svelte b/packages/ui/src/solidity/StablecoinControls.svelte index eae569e8d..4f77380a5 100644 --- a/packages/ui/src/solidity/StablecoinControls.svelte +++ b/packages/ui/src/solidity/StablecoinControls.svelte @@ -214,7 +214,7 @@ SuperchainERC20*   - Uses the predeployed SuperchainTokenBridge contract on OP Chains as the authorized token bridge. + Uses the predeployed SuperchainTokenBridge contract as the authorized token bridge. Only available on chains in the Superchain. diff --git a/packages/ui/src/solidity/superchain-tooltip.ts b/packages/ui/src/solidity/superchain-tooltip.ts index e85bb9da2..9e656806a 100644 --- a/packages/ui/src/solidity/superchain-tooltip.ts +++ b/packages/ui/src/solidity/superchain-tooltip.ts @@ -2,7 +2,7 @@ * Tippy.js properties for the Superchain tooltip. */ export const superchainTooltipProps: { [prop: string]: string | boolean } = { - content: 'Important: Only available on OP Chains. Requires deploying your contract to the same address on every chain in the Superchain. Read more.', + content: 'Important: Only available on chains in the Superchain. Requires deploying your contract to the same address on every chain in the Superchain. Read more.', trigger: 'manual', placement: 'bottom', maxWidth: '22em', diff --git a/packages/ui/src/solidity/wiz-functions.ts b/packages/ui/src/solidity/wiz-functions.ts index 63a8d0977..ddd145e3f 100644 --- a/packages/ui/src/solidity/wiz-functions.ts +++ b/packages/ui/src/solidity/wiz-functions.ts @@ -39,7 +39,7 @@ export const erc20Function = { // 'false' gets converted to false votes: { type: 'string', enum: ['false', 'blocknumber', 'timestamp'], description: 'Whether to keep track of historical balances for voting in on-chain governance. Voting durations can be expressed as block numbers or timestamps.'}, flashmint: { type: 'boolean', description: 'Whether to include built-in flash loans to allow lending tokens without requiring collateral as long as they\'re returned in the same transaction.' }, - crossChainBridging: { type: 'string', enum: ['false', 'custom', 'superchain'], description: 'Whether to allow authorized bridge contracts to mint and burn tokens for cross-chain transfers. Options are to use custom bridges on any chain, or the SuperchainERC20 standard with the predeployed SuperchainTokenBridge on OP Chains. Emphasize that these features are experimental, not audited and are subject to change. The SuperchainERC20 feature is only available on OP Chains, and requires deploying your contract to the same address on every chain in the Superchain.' }, + crossChainBridging: { type: 'string', enum: ['false', 'custom', 'superchain'], description: 'Whether to allow authorized bridge contracts to mint and burn tokens for cross-chain transfers. Options are to use custom bridges on any chain, or the SuperchainERC20 standard with the predeployed SuperchainTokenBridge. Emphasize that these features are experimental, not audited and are subject to change. The SuperchainERC20 feature is only available on chains in the Superchain, and requires deploying your contract to the same address on every chain in the Superchain.' }, ...commonOptions }, required: ['name', 'symbol'], From b0c7ef814ddcd0fe3ff328c748a5dddc0da4f073 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 25 Feb 2025 14:19:41 -0500 Subject: [PATCH 60/75] Check chainId on premint when bridgeable --- packages/core/solidity/src/erc20.ts | 37 +++++++++++++++++-- packages/core/solidity/src/generate/erc20.ts | 1 + .../core/solidity/src/generate/stablecoin.ts | 2 + packages/core/solidity/src/index.ts | 2 +- packages/ui/src/solidity/App.svelte | 2 +- packages/ui/src/solidity/ERC20Controls.svelte | 23 +++++++++++- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/packages/core/solidity/src/erc20.ts b/packages/core/solidity/src/erc20.ts index 4551977d4..872bd6b65 100644 --- a/packages/core/solidity/src/erc20.ts +++ b/packages/core/solidity/src/erc20.ts @@ -19,6 +19,7 @@ export interface ERC20Options extends CommonOptions { burnable?: boolean; pausable?: boolean; premint?: string; + premintChainId?: string; mintable?: boolean; permit?: boolean; /** @@ -36,6 +37,7 @@ export const defaults: Required = { burnable: false, pausable: false, premint: '0', + premintChainId: '', mintable: false, permit: true, votes: false, @@ -53,6 +55,7 @@ export function withDefaults(opts: ERC20Options): Required { burnable: opts.burnable ?? defaults.burnable, pausable: opts.pausable ?? defaults.pausable, premint: opts.premint || defaults.premint, + premintChainId: opts.premintChainId || defaults.premintChainId, mintable: opts.mintable ?? defaults.mintable, permit: opts.permit ?? defaults.permit, votes: opts.votes ?? defaults.votes, @@ -87,7 +90,7 @@ export function buildERC20(opts: ERC20Options): ContractBuilder { } if (allOpts.premint) { - addPremint(c, allOpts.premint); + addPremint(c, allOpts.premint, allOpts.premintChainId, allOpts.crossChainBridging); } if (allOpts.mintable) { @@ -153,7 +156,13 @@ function addBurnable(c: ContractBuilder) { export const premintPattern = /^(\d*)(?:\.(\d+))?(?:e(\d+))?$/; -function addPremint(c: ContractBuilder, amount: string) { +export const chainIdPattern = /^(?!$)[1-9]\d*$/; + +export function isValidChainId(str: string): boolean { + return chainIdPattern.test(str); +} + +function addPremint(c: ContractBuilder, amount: string, premintChainId: string, crossChainBridging: CrossChainBridging) { const m = amount.match(premintPattern); if (m) { const integer = m[1]?.replace(/^0+/, '') ?? ''; @@ -165,8 +174,30 @@ function addPremint(c: ContractBuilder, amount: string) { const zeroes = new Array(Math.max(0, -decimalPlace)).fill('0').join(''); const units = integer + decimals + zeroes; const exp = decimalPlace <= 0 ? 'decimals()' : `(decimals() - ${decimalPlace})`; + c.addConstructorArgument({type: 'address', name: 'recipient'}); - c.addConstructorCode(`_mint(recipient, ${units} * 10 ** ${exp});`); + + const mintLine = `_mint(recipient, ${units} * 10 ** ${exp});`; + + if (crossChainBridging) { + if (premintChainId === '') { + throw new OptionsError({ + premintChainId: 'Chain ID is required when using Premint with Cross-Chain Bridging' + }); + } + + if (!isValidChainId(premintChainId)) { + throw new OptionsError({ + premintChainId: 'Not a valid chain ID' + }); + } + + c.addConstructorCode(`if (block.chainid == ${premintChainId}) {`); + c.addConstructorCode(` ${mintLine}`); + c.addConstructorCode(`}`); + } else { + c.addConstructorCode(mintLine); + } } } } diff --git a/packages/core/solidity/src/generate/erc20.ts b/packages/core/solidity/src/generate/erc20.ts index 720c2e10a..fcfc1847d 100644 --- a/packages/core/solidity/src/generate/erc20.ts +++ b/packages/core/solidity/src/generate/erc20.ts @@ -17,6 +17,7 @@ const blueprint = { votes: [ ...booleans, ...clockModeOptions ] as const, flashmint: booleans, premint: ['1'], + premintChainId: ['10'], crossChainBridging: crossChainBridgingOptions, access: accessOptions, upgradeable: upgradeableOptions, diff --git a/packages/core/solidity/src/generate/stablecoin.ts b/packages/core/solidity/src/generate/stablecoin.ts index 7e150e5ce..9a0ea6a2f 100644 --- a/packages/core/solidity/src/generate/stablecoin.ts +++ b/packages/core/solidity/src/generate/stablecoin.ts @@ -16,6 +16,7 @@ const erc20Basic = { votes: [false] as const, flashmint: [false] as const, premint: ['1'], + premintChainId: [''], crossChainBridging: [false] as const, access: [false] as const, info: [{}] as const, @@ -31,6 +32,7 @@ const erc20Full = { votes: ['timestamp'] as const, flashmint: [true] as const, premint: ['1'], + premintChainId: ['10'], crossChainBridging: crossChainBridgingOptions, access: accessOptions, info: infoOptions, diff --git a/packages/core/solidity/src/index.ts b/packages/core/solidity/src/index.ts index b6e0ed24c..72b57ed10 100644 --- a/packages/core/solidity/src/index.ts +++ b/packages/core/solidity/src/index.ts @@ -10,7 +10,7 @@ export type { Access } from './set-access-control'; export type { Upgradeable } from './set-upgradeable'; export type { Info } from './set-info'; -export { premintPattern } from './erc20'; +export { premintPattern, chainIdPattern } from './erc20'; export { defaults as infoDefaults } from './set-info'; export type { OptionsErrorMessages } from './error'; diff --git a/packages/ui/src/solidity/App.svelte b/packages/ui/src/solidity/App.svelte index 981e22492..e227b8e74 100644 --- a/packages/ui/src/solidity/App.svelte +++ b/packages/ui/src/solidity/App.svelte @@ -338,7 +338,7 @@
- +
diff --git a/packages/ui/src/solidity/ERC20Controls.svelte b/packages/ui/src/solidity/ERC20Controls.svelte index 37cb5b096..973adca9b 100644 --- a/packages/ui/src/solidity/ERC20Controls.svelte +++ b/packages/ui/src/solidity/ERC20Controls.svelte @@ -1,14 +1,16 @@
@@ -61,6 +70,16 @@ + + {#if showChainId} +

+ + Chain ID of the network on which to premint tokens. +

+ {/if}
From e6fd6f4d9fef17766f499cb8b784262df337f04c Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 25 Feb 2025 14:23:47 -0500 Subject: [PATCH 61/75] Add premint input check --- packages/core/solidity/src/erc20.ts | 4 ++++ packages/ui/src/solidity/ERC20Controls.svelte | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/core/solidity/src/erc20.ts b/packages/core/solidity/src/erc20.ts index 872bd6b65..c37f49571 100644 --- a/packages/core/solidity/src/erc20.ts +++ b/packages/core/solidity/src/erc20.ts @@ -199,6 +199,10 @@ function addPremint(c: ContractBuilder, amount: string, premintChainId: string, c.addConstructorCode(mintLine); } } + } else { + throw new OptionsError({ + premint: 'Not a valid number' + }); } } diff --git a/packages/ui/src/solidity/ERC20Controls.svelte b/packages/ui/src/solidity/ERC20Controls.svelte index 973adca9b..5b56a1b0a 100644 --- a/packages/ui/src/solidity/ERC20Controls.svelte +++ b/packages/ui/src/solidity/ERC20Controls.svelte @@ -68,7 +68,7 @@ Premint Create an initial amount of tokens for the deployer. - + {#if showChainId} From f554f23779591c394b81ff840e97099910d19401 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 25 Feb 2025 14:59:57 -0500 Subject: [PATCH 62/75] Update tests --- packages/core/solidity/src/erc20.test.ts | 28 ++++++ packages/core/solidity/src/erc20.test.ts.md | 94 +++++++++++++++++- packages/core/solidity/src/erc20.test.ts.snap | Bin 2832 -> 2973 bytes packages/core/solidity/src/error.ts | 2 +- packages/core/solidity/src/stablecoin.test.ts | 2 + .../core/solidity/src/stablecoin.test.ts.md | 4 +- .../core/solidity/src/stablecoin.test.ts.snap | Bin 2033 -> 2058 bytes 7 files changed, 127 insertions(+), 3 deletions(-) diff --git a/packages/core/solidity/src/erc20.test.ts b/packages/core/solidity/src/erc20.test.ts index ac66995f7..7e1c05596 100644 --- a/packages/core/solidity/src/erc20.test.ts +++ b/packages/core/solidity/src/erc20.test.ts @@ -150,6 +150,33 @@ test('erc20 crossChainBridging superchain, upgradeable not allowed', async t => t.is((error as OptionsError).messages.crossChainBridging, 'Upgradeability is not currently supported with Cross-Chain Bridging'); }); +test('erc20 crossChainBridging superchain, premintChainId required', async t => { + let error = t.throws(() => buildERC20({ + name: 'MyToken', + symbol: 'MTK', + crossChainBridging: 'superchain', + premint: '2000', + })); + t.is((error as OptionsError).messages.premintChainId, 'Chain ID is required when using Premint with Cross-Chain Bridging'); +}); + +testERC20('erc20 premint ignores chainId when not crossChainBridging', { + premint: '2000', + premintChainId: '10', +}); + +testERC20('erc20 premint chainId crossChainBridging custom', { + premint: '2000', + premintChainId: '10', + crossChainBridging: 'custom', +}); + +testERC20('erc20 premint chainId crossChainBridging superchain', { + premint: '2000', + premintChainId: '10', + crossChainBridging: 'superchain', +}); + testERC20('erc20 full crossChainBridging custom non-upgradeable', { premint: '2000', access: 'roles', @@ -160,6 +187,7 @@ testERC20('erc20 full crossChainBridging custom non-upgradeable', { votes: true, flashmint: true, crossChainBridging: 'custom', + premintChainId: '10', }); testERC20('erc20 full upgradeable transparent', { diff --git a/packages/core/solidity/src/erc20.test.ts.md b/packages/core/solidity/src/erc20.test.ts.md index 61b0b0784..610f4a73d 100644 --- a/packages/core/solidity/src/erc20.test.ts.md +++ b/packages/core/solidity/src/erc20.test.ts.md @@ -716,6 +716,96 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## erc20 premint ignores chainId when not crossChainBridging + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit {␊ + constructor(address recipient)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + {␊ + _mint(recipient, 2000 * 10 ** decimals());␊ + }␊ + }␊ + ` + +## erc20 premint chainId crossChainBridging custom + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable {␊ + address public immutable TOKEN_BRIDGE;␊ + error Unauthorized();␊ + ␊ + constructor(address recipient, address tokenBridge)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + {␊ + if (block.chainid == 10) {␊ + _mint(recipient, 2000 * 10 ** decimals());␊ + }␊ + require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");␊ + TOKEN_BRIDGE = tokenBridge;␊ + }␊ + ␊ + function _checkTokenBridge(address caller) internal view override {␊ + if (caller != TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + }␊ + ` + +## erc20 premint chainId crossChainBridging superchain + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable {␊ + address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ + error Unauthorized();␊ + ␊ + constructor(address recipient)␊ + ERC20("MyToken", "MTK")␊ + ERC20Permit("MyToken")␊ + {␊ + if (block.chainid == 10) {␊ + _mint(recipient, 2000 * 10 ** decimals());␊ + }␊ + }␊ + ␊ + /**␊ + * @dev Checks if the caller is the predeployed SuperchainTokenBridge. Reverts otherwise.␊ + *␊ + * IMPORTANT: The predeployed SuperchainTokenBridge is only available on chains in the Superchain.␊ + */␊ + function _checkTokenBridge(address caller) internal pure override {␊ + if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + }␊ + ` + ## erc20 full crossChainBridging custom non-upgradeable > Snapshot 1 @@ -746,7 +836,9 @@ Generated by [AVA](https://avajs.dev). {␊ _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ _grantRole(PAUSER_ROLE, pauser);␊ - _mint(recipient, 2000 * 10 ** decimals());␊ + if (block.chainid == 10) {␊ + _mint(recipient, 2000 * 10 ** decimals());␊ + }␊ _grantRole(MINTER_ROLE, minter);␊ _grantRole(TOKEN_BRIDGE_ROLE, tokenBridge);␊ }␊ diff --git a/packages/core/solidity/src/erc20.test.ts.snap b/packages/core/solidity/src/erc20.test.ts.snap index 7f6154bd37a2f8439bc01dcdd6e8e844ee416d0b..4121dde1dd2358d630cb03ea8b35db213aaa4444 100644 GIT binary patch literal 2973 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 diff --git a/packages/core/solidity/src/error.ts b/packages/core/solidity/src/error.ts index 2235dfd68..8b3d2b8e3 100644 --- a/packages/core/solidity/src/error.ts +++ b/packages/core/solidity/src/error.ts @@ -2,6 +2,6 @@ export type OptionsErrorMessages = { [prop in string]?: string }; export class OptionsError extends Error { constructor(readonly messages: OptionsErrorMessages) { - super("Invalid options for Governor"); + super("Invalid options"); } } diff --git a/packages/core/solidity/src/stablecoin.test.ts b/packages/core/solidity/src/stablecoin.test.ts index eb7e76e1b..e985dedeb 100644 --- a/packages/core/solidity/src/stablecoin.test.ts +++ b/packages/core/solidity/src/stablecoin.test.ts @@ -116,6 +116,7 @@ testStablecoin('stablecoin full', { votes: true, flashmint: true, crossChainBridging: 'custom', + premintChainId: '10', limitations: 'allowlist', custodian: true, }); @@ -136,6 +137,7 @@ testAPIEquivalence('stablecoin API full', { votes: true, flashmint: true, crossChainBridging: 'custom', + premintChainId: '10', limitations: 'allowlist', custodian: true }); diff --git a/packages/core/solidity/src/stablecoin.test.ts.md b/packages/core/solidity/src/stablecoin.test.ts.md index 96db561e1..66f593f4f 100644 --- a/packages/core/solidity/src/stablecoin.test.ts.md +++ b/packages/core/solidity/src/stablecoin.test.ts.md @@ -600,7 +600,9 @@ Generated by [AVA](https://avajs.dev). {␊ _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ _grantRole(PAUSER_ROLE, pauser);␊ - _mint(recipient, 2000 * 10 ** decimals());␊ + if (block.chainid == 10) {␊ + _mint(recipient, 2000 * 10 ** decimals());␊ + }␊ _grantRole(MINTER_ROLE, minter);␊ _grantRole(TOKEN_BRIDGE_ROLE, tokenBridge);␊ _grantRole(CUSTODIAN_ROLE, custodian);␊ diff --git a/packages/core/solidity/src/stablecoin.test.ts.snap b/packages/core/solidity/src/stablecoin.test.ts.snap index 914dfbf313710645f7603a00265102b46385eea2..b1a3f2b9aca562158fd8e995ffdd5085fd3ac010 100644 GIT binary patch literal 2058 zcmV+l2=(_tRzVXz4j7B9R)BN+t~kXwN;gKySUZ|4eT^_O`$t_qN9Z1qu|RBucbtC3Zd>&De(o zlE@z)`5u3Ke0==5-}9JrAb$J>B#|BjJuHZWgv31$97ZS+6bE9!r1*i0l zZ~Ws%^t*ZY#yhvZyV+`??Psh1Tv#U#Pyq`a7pNqC0{k)Rc6KVQ7FuC`fF~BNVMLDmiwfKwmv-wwvur!12D1kzgKii9AMMwVR(b7Z;Z*72*esOLVff zwX)cLiTa%RsQM`jfPS5zwVV{KCD{ScmMR+mZ3^a9mrRgnz=SBBo7_QcPuT}H4s|{4`Ztqm<`N~5@>geQU zA%}yH!1e!(V46rI}QlZN=i>gQc0&8D5-s#5n|WnAOs?mNP@l1BMQ8( zN=3gS1J#9+mTCnMb~9FGPF_~j|9(gvNmy*dP^+UL?0LjNjC#ikG7&!d?ImTF)SF>| zke&rXmoh+FEwnQL)MuW@jtJe?r~+XQh#dmw#07ykJP!#67xj+Oc4G3)Awl-Sz{L{u z7)M%fp!7+y1_}w4i;q4=hu8}t8#6*BaEd+sB5k*3({(bAy08cX;LWu0xY4MwxRJEG znm=B=Zy}I)!gJ<*dCw97DB99}V{p#%a&PG_Jrqzb?zy@x z<8ZiQzJr|aASWX(nfI4C_)+5)AL-^F24DTJ+@Z_s6@yMqf`dZ>0#sh!hA2{RO}EoP z58CZEx{n^T(f#|#1&8?96SexNnH-Ip31WTJo}X5f{Inv{@0>xMx$a27Xl>kX*CLgYKgCPA`eb7TBLRYp&qAQrV+;xK|9mJ5s{;Hcjo5tcRKZrfmz zdv{CCB+F?>FPcd-@TJGn4VpO z9J?MeX^kQN$6(gqW)VZYw$Tg&`^#tm&jYOhhLATHbxubOCGkWnE;~JSs`f8D=u$ey zP{VK$Y(bSiOs>d;iRo8AM%(Z)a-~X&^_wB+y?WB!VVRRHdn|e)Oe{q4*@9vM^kKXv z(a`S!pYy_;7v{Y18uG$>7G99V2O+T^SR&^CH(24n<&K!oSz$J;pl6B`tw32y+n7*w zWabY)u?4HuhniZ)n%Zhd_A-Kb1489O6jSPXut4F3T<{15CCCEBJ}mg;1-K3tU<$ah zzPa+nUUzeKEt4_`bIg@V8RZevedL4B__0OUs?S__qNS{scE|NP@?<_t)%UO%L?_9X z+@iM(di<;0N5h{*9qkf&E{4<~*X-~)dC=lr-eEM$+fL|tqh|B=_lDVg^Y%QCXXd9- zPdRb-p(wIBb&ysg&*IL(Y_bHdfJ(}Fm!h=3;@B%1GoN=^EaeQs=YjA6)w6wCjy|cO6S>CWT zV}3hL=JiguWAAwW%hdOxv*%pKzL~U`_f`*p##WKNbTXqzUwOnQ*E-vA{GDs%dG}GW zjd2E;P~t{8I1k$SZ3MDibXY9B=ny-x7GcJxUJex;vCl?cBlbF`u{APn*^B3Gs-g8* zqU-2am!>+j&2t9e9PDK3&}}=|^9pjnP7JfVH^5??t`nd-;&2FDTKVYmbJ9`)hYhRX zRP+ofCnLsJzoguj;)Y(KM3>A57+L4XF5~4rwY~717_(C%3?e^HbRuE;*nyf_t{=wI oMK3z;guxPeYQvr{Gp+tc~uLAY0Oo9~Y zYO=?oj30{#00000000B+TT5>nHxSMfMb!d9u0_x?I!UQ4DQ*%3F#^=FokECZ1%4E5 z4>73Skxh7)+>l&9VgzW;y%gxJxAf2S)?;r4dhD&o0tE^b`{FJoYHi66c@ybiV|U4q zL(cHya5#M1>pINZ5kLI`l1K-LgKCi79*4hiaoK-q$(1&=qK@s^8`U=Fc~JU}m+^@sJ@*|}1QxE|vY9WJdd%r;-6 z9%n8pf5|+cuVS=@m7p~w+X31Li$;Izf;r_m9ppK1m&j3|U|#|igi+DRAjH_Eqz-By ztf@gnM4+&24P~mJ!xBOWS&RzFeM>T4sYc%`*Z>;a$k`uI(%JvU5d3R zQvIQ>&uQ>5sK_fHYKr`~*ou4-_wyvGOfW8tp(FxLz-~P33$xu^yQ$gDm1~8zo9A&q zPo&ux;~eZJ!S3uG%i6JJfe?+j^k^g%cdCZs+D927wrvhVAVP^G*y-$1;MK5H@XIq$ zRVZ$$k^^Bjr(i?=Tl1(7TGXVs>t)Z4zUoU&Orzn3m^P8<1%yMn|=VF9tT2| z(m)yww7w0f#~g?45xS*N1;QK<+Xc>v4FYj^=@Sk%>K>rA*yQVdf^7PpjU}it4zylF z$&+L?|7h*zqA9GeRYBiXHVLX}4n1bv%x$u<$+L^`!Br(V(%Yk)*qdKlVR0 z5J)uPIdec5xa4<@OMaaMm&}KAB&^7sV@@coj%nJzkK8mWuV{m4VwdiL1o6deGWkNX z!BnE>^BZeRtDCExjD&@?Fa&@jWl%j0tVc(JSwo7O_jlx+xDrFr> zN-0llaZKeZbD*-g^mKk>d3|$!vE5n;#jR;F#Z#-VR;G8gL|8L#8Ca_yp?WeB%!Qj0 zVnT>$C?UF-;w`WZlsKnRVr_Di*p5UzCM8B4;tj3tlp0S$jqxCk=y=Wha+`4?4@P7% zto0L|gT@U$(&c|NzWS@!q05UEgHB9>gGD?7RG!_2C{S-jwNpcPo6RP= zgYGubojb?|i@4YkmFl3G>mn6v?9>tkkg7EHATL;GF9X`FY$$4#6y}f zt#sIBK9%`Pb67d36c^49dM5Up8}z)|(oFf$)oIXkf*dz?6tdk~SvN)@Gatr?LWVxi z1&%^ydRI$?HT%A!%)5T*>PU0&W!4`EM`7v-6wnjMdjFO$B(n)NWT0I8MAPI)#g0}i zBpn@w=DI#5@?a*#J)VLU@VnxGWSWg1R2P+ZayAahQS_Scv^V*tBp8FpHqPZ)!|(`+A|7 zWIpNWX)}oees`Hfb+K4X6595L0NzIzbfE&mtR#Ei^Z>@ZI8%-X`LK?_31d!*;>VBS7i^yW!Iy+Fh09_8Ft-e z(ilVhLu1z8CJ{rtu+a<+`|Dr;PXZkR^dYY>Y8{R0OX7$|RCavo4BJ2TpiAKxBOHd) zU<(@RL+6TAn23JWW3UY$B3GiMNWUq9+N;Oi?Uy;;vPYuF!bC#kpDlz;fIg4bBeOB8F5T7wqskeo*3_-C;D#+K%rygJyH%g=RLL8`C_ViJwM2;l$p8 zyvXL*L0W}8i8}|A$r3mRDkC;psKksn3$o@*;BgNn}>1S zyu3V&_0F@UmCYxst;MgF3`hf?6FlIYakN2kbZzbx*p(w%TG&`y?<}_FR}9VQ-;R=b zxz%o&JD&YA_PyxzIg_!kCoN{Z)g7RbRirPi)F_fy4spqa&UPGr=Ng%AFwExOU_i&s zr0gp=U~aYS0GsRRwo^+7-&{OvA~mI!0^Ke@zpT@~U7NKH*3NpW4%N1W9VaKHD{YDN zQ04YE7Q=KM162`+UEtD4FK3@(mI&BySUHEB$H*WVFuv*;rK;pN^bX~%q)Yn1vORQF zF76@hsi(N;of5tmxMiXh2-CwBRKnHwUL;-cqGgX5`!G3LssCgMgM{-jF9tFwWLCQ3 P266re=e#mfolpP(=@{e_ From b5d87cbc075dead30f173f442f55243fbde06ab9 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 25 Feb 2025 15:18:32 -0500 Subject: [PATCH 63/75] Add tests, change premint and cross chain bridging implementation order --- packages/core/solidity/src/erc20.test.ts.md | 60 +++++++++--------- packages/core/solidity/src/erc20.test.ts.snap | Bin 2973 -> 2967 bytes packages/core/solidity/src/erc20.ts | 16 ++--- .../core/solidity/src/stablecoin.test.ts.md | 22 +++---- .../core/solidity/src/stablecoin.test.ts.snap | Bin 2058 -> 2059 bytes 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/packages/core/solidity/src/erc20.test.ts.md b/packages/core/solidity/src/erc20.test.ts.md index 610f4a73d..f1406b697 100644 --- a/packages/core/solidity/src/erc20.test.ts.md +++ b/packages/core/solidity/src/erc20.test.ts.md @@ -451,7 +451,7 @@ Generated by [AVA](https://avajs.dev). import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable {␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Permit {␊ address public immutable TOKEN_BRIDGE;␊ error Unauthorized();␊ ␊ @@ -482,7 +482,7 @@ Generated by [AVA](https://avajs.dev). import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, Ownable {␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Permit, Ownable {␊ address public immutable TOKEN_BRIDGE;␊ error Unauthorized();␊ ␊ @@ -514,7 +514,7 @@ Generated by [AVA](https://avajs.dev). import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessControl {␊ + contract MyToken is ERC20, ERC20Bridgeable, AccessControl, ERC20Permit {␊ bytes32 public constant TOKEN_BRIDGE_ROLE = keccak256("TOKEN_BRIDGE_ROLE");␊ error Unauthorized();␊ ␊ @@ -557,13 +557,13 @@ Generated by [AVA](https://avajs.dev). import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessManaged {␊ + contract MyToken is ERC20, ERC20Bridgeable, AccessManaged, ERC20Permit {␊ error Unauthorized();␊ ␊ constructor(address initialAuthority)␊ ERC20("MyToken", "MTK")␊ - ERC20Permit("MyToken")␊ AccessManaged(initialAuthority)␊ + ERC20Permit("MyToken")␊ {}␊ ␊ function _checkTokenBridge(address caller) internal view override {␊ @@ -585,7 +585,7 @@ Generated by [AVA](https://avajs.dev). import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable {␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Permit {␊ address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ error Unauthorized();␊ ␊ @@ -615,7 +615,7 @@ Generated by [AVA](https://avajs.dev). import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, Ownable {␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Permit, Ownable {␊ address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ error Unauthorized();␊ ␊ @@ -649,7 +649,7 @@ Generated by [AVA](https://avajs.dev). import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessControl {␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Permit, AccessControl {␊ address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ error Unauthorized();␊ ␊ @@ -695,7 +695,7 @@ Generated by [AVA](https://avajs.dev). import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable, AccessManaged {␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Permit, AccessManaged {␊ address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ error Unauthorized();␊ ␊ @@ -749,19 +749,19 @@ Generated by [AVA](https://avajs.dev). import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable {␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Permit {␊ address public immutable TOKEN_BRIDGE;␊ error Unauthorized();␊ ␊ - constructor(address recipient, address tokenBridge)␊ + constructor(address tokenBridge, address recipient)␊ ERC20("MyToken", "MTK")␊ ERC20Permit("MyToken")␊ {␊ + require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");␊ + TOKEN_BRIDGE = tokenBridge;␊ if (block.chainid == 10) {␊ _mint(recipient, 2000 * 10 ** decimals());␊ }␊ - require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");␊ - TOKEN_BRIDGE = tokenBridge;␊ }␊ ␊ function _checkTokenBridge(address caller) internal view override {␊ @@ -782,7 +782,7 @@ Generated by [AVA](https://avajs.dev). import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ ␊ - contract MyToken is ERC20, ERC20Permit, ERC20Bridgeable {␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Permit {␊ address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;␊ error Unauthorized();␊ ␊ @@ -824,23 +824,27 @@ Generated by [AVA](https://avajs.dev). import {ERC20Votes} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";␊ import {Nonces} from "@openzeppelin/contracts/utils/Nonces.sol";␊ ␊ - contract MyToken is ERC20, ERC20Burnable, ERC20Pausable, AccessControl, ERC20Permit, ERC20Votes, ERC20FlashMint, ERC20Bridgeable {␊ - bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");␊ - bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");␊ + contract MyToken is ERC20, ERC20Bridgeable, AccessControl, ERC20Burnable, ERC20Pausable, ERC20Permit, ERC20Votes, ERC20FlashMint {␊ bytes32 public constant TOKEN_BRIDGE_ROLE = keccak256("TOKEN_BRIDGE_ROLE");␊ error Unauthorized();␊ + bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");␊ + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");␊ ␊ - constructor(address defaultAdmin, address pauser, address recipient, address minter, address tokenBridge)␊ + constructor(address defaultAdmin, address tokenBridge, address recipient, address pauser, address minter)␊ ERC20("MyToken", "MTK")␊ ERC20Permit("MyToken")␊ {␊ _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ - _grantRole(PAUSER_ROLE, pauser);␊ + _grantRole(TOKEN_BRIDGE_ROLE, tokenBridge);␊ if (block.chainid == 10) {␊ _mint(recipient, 2000 * 10 ** decimals());␊ }␊ + _grantRole(PAUSER_ROLE, pauser);␊ _grantRole(MINTER_ROLE, minter);␊ - _grantRole(TOKEN_BRIDGE_ROLE, tokenBridge);␊ + }␊ + ␊ + function _checkTokenBridge(address caller) internal view override {␊ + if (!hasRole(TOKEN_BRIDGE_ROLE, caller)) revert Unauthorized();␊ }␊ ␊ function pause() public onlyRole(PAUSER_ROLE) {␊ @@ -854,10 +858,6 @@ Generated by [AVA](https://avajs.dev). function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {␊ _mint(to, amount);␊ }␊ - ␊ - function _checkTokenBridge(address caller) internal view override {␊ - if (!hasRole(TOKEN_BRIDGE_ROLE, caller)) revert Unauthorized();␊ - }␊ ␊ // The following functions are overrides required by Solidity.␊ ␊ @@ -871,7 +871,7 @@ Generated by [AVA](https://avajs.dev). function supportsInterface(bytes4 interfaceId)␊ public␊ view␊ - override(AccessControl, ERC20Bridgeable)␊ + override(ERC20Bridgeable, AccessControl)␊ returns (bool)␊ {␊ return super.supportsInterface(interfaceId);␊ @@ -915,7 +915,7 @@ Generated by [AVA](https://avajs.dev). _disableInitializers();␊ }␊ ␊ - function initialize(address defaultAdmin, address pauser, address recipient, address minter)␊ + function initialize(address recipient, address defaultAdmin, address pauser, address minter)␊ initializer public␊ {␊ __ERC20_init("MyToken", "MTK");␊ @@ -926,9 +926,9 @@ Generated by [AVA](https://avajs.dev). __ERC20Votes_init();␊ __ERC20FlashMint_init();␊ ␊ + _mint(recipient, 2000 * 10 ** decimals());␊ _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ _grantRole(PAUSER_ROLE, pauser);␊ - _mint(recipient, 2000 * 10 ** decimals());␊ _grantRole(MINTER_ROLE, minter);␊ }␊ ␊ @@ -993,7 +993,7 @@ Generated by [AVA](https://avajs.dev). _disableInitializers();␊ }␊ ␊ - function initialize(address defaultAdmin, address pauser, address recipient, address minter, address upgrader)␊ + function initialize(address recipient, address defaultAdmin, address pauser, address minter, address upgrader)␊ initializer public␊ {␊ __ERC20_init("MyToken", "MTK");␊ @@ -1005,9 +1005,9 @@ Generated by [AVA](https://avajs.dev). __ERC20FlashMint_init();␊ __UUPSUpgradeable_init();␊ ␊ + _mint(recipient, 2000 * 10 ** decimals());␊ _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ _grantRole(PAUSER_ROLE, pauser);␊ - _mint(recipient, 2000 * 10 ** decimals());␊ _grantRole(MINTER_ROLE, minter);␊ _grantRole(UPGRADER_ROLE, upgrader);␊ }␊ @@ -1075,7 +1075,7 @@ Generated by [AVA](https://avajs.dev). _disableInitializers();␊ }␊ ␊ - function initialize(address initialAuthority, address recipient)␊ + function initialize(address recipient, address initialAuthority)␊ initializer public␊ {␊ __ERC20_init("MyToken", "MTK");␊ diff --git a/packages/core/solidity/src/erc20.test.ts.snap b/packages/core/solidity/src/erc20.test.ts.snap index 4121dde1dd2358d630cb03ea8b35db213aaa4444..46d1507eb6781af7d5e6e201009dfd18670ed07b 100644 GIT binary patch literal 2967 zcmV;I3uyE~RzVD-mHL1PtwWs_N;~(8ck1k?-I@Q zL;c{*wwx-bV|A6Q#&&ggW*CXpUXZwPf$Q=YaOAc}Zb(R6xFK;_326@?goK2&s&~2K zs#MZ>R5I0v86~zqe=dLD&%f`pUHPQb)=l+{{qF0(M;vn;z0m-N`&&P%Kf@{_4Aom2A{=)xq7T7N>u9Ob z0Gp;^L5|xx0vDKf!JdW4PmpCH9TTu=5>BDY8Tj!2N^_;TWKno(K)_5LYnb=Ihs~7- zE32!ImX@$#nUsT<+XtJg%~zm9O#@UOn-(H3d}$3ekk;Vl86pk0s`u{-Gxf?NQOG`` z2Ij+vLYEv7hE2j6F$uoxrJxPi=^Z(Z0A|3gRs*rx;N=nk0H`KmoZ2cksZ#aIm5Sf6 zQUjHpqoyj@gU1utJMy;|~TjJR_J+BPMyts}{#{ZE**f6n)$J@LnRm1zrP6u~G0 zU8Z3p7POh%MsD2@Y~N%Z9Xd`p+*Aa(?z!2g2$&jSoD4b8wLavs-rhk&On0E#f-ltRJ}OdTm(+wX52KRY_v*xG6B zx=PjrO?)>>w2F_Qm?mO)@1j52*1M3Le2E1^EuKNGO&Z}Xj1 zEKDjmFa(NJY+*$BxMLb;K9x{<4cu!sn_wB-Yl7uvpdl3-P-jZD-z2DD62R<$a)V%= zHVB+qlhceF9|@C2ZtB% z?yK%A<0+BKi(IbG32Aan}VSzV$`xnuUBxr-LP_MqBt%wB=wu2CzYnf9gBnW=X%;dKqW3F|sRm%OfH zf?P%F1RAJr;7g>bkRegQ&1ZX?PfvFCwzeZJEjtEMk(SO*Bsm2JGECZ&C|fa14XuY- zR^~SG|2jgVze~~4A?rG^t|Wr}zW{}w&vyj-zBAArOs<56p^)Ol$o_{=vvJ4Fm*4OV zMWrTVn_Y;>6Nu7anq2H=wAwk^L)NZv^!jsmA^I&n_%9nM}l*1$cK`PU`~-X zvK&l!SkPNBuwmFGtl)lY`dQ2iqRVAWBUNjtTS**StWQl9h*aN8oin=Cq@~ zvM8}0z}xG=P?To11}ZIb4t1;v!w70rV#!FMd_AtTd?h$hyGT7dimHX~E;=;R2>mG?#a23`}iohYij-GwYo3183vh#7yLfZ3K~>a67qpaWH;xE8hM zjmY_;rHvAgry8*&G;f>1*C}y%zmjq7Mj&zNS1i6OAaH$=u2_Ue_m7=q;IM*)#wEs& z9pf{ubqtBg#k%n^2JCbJ!r{wE!;qs|6|94VJ*tpwLS6qM=G`r%!=3_za-|x8Yq&ls zyo*`2=B=G;%89{Fw;+c~^{35;Yd^2X77iD+!;W+Fzjspc$Hg<%`AUL4w*>6@PZ>bY zn_hX8JWEz@KR2$rJ*o$#283wJ`U zYSvk@5(}q}g=H=;S1vCX4^GeLeJU&!e^{h^Ub$q9dCBk}b8(l9(KCAkSaP1kU&)te z$(O$)-iODh#H5IM!)j^ZqKllflw5+7<;xTn^<@gHd0(b**$}NKu$o~`DE?Qlna|4P z^c*jEvpJA7DZiNJd7}W>z3T?vMvey7*TKDJ{J8%J?&`TLDD0W0cXLBX<{sB?1Q_|a z%u6p0j1-6{PYPU%DQq*A1K%8j$>oZZdpDewEyvt&%@wMy9`MDkti zMSmSru4Bj3U>G3pJLAEq?~^LlVd-MO^L~0S;Tr#L)0AEoO~7l$&|MmL z9-u);ktU#mOm-I0o`4Dx(dkrt68$Fyr;_yvbe@!(=)2|ZI^q|@_GwY`vgh-BL5MV7 z7;#|nFrt49(uhLP#b3r^O%t(1e~H9c5=)DuO>%z6d6T)osFH2i2j&W#Vx~Uz{QEBmezB;oKm~(l{9o>-6UpBchY_3sLD&NhF)b zm*$wFC+-BDI2HS&mq*EZffaf6`^y7cl9US;mD=95tAsZF)m$@6lMxzQSYgzyO)%M? z%L1c@K4pwCCox7&u$4k*@!onR=-jtNO@_h0nZn?0+mf8ve&bsLb^pp6C3P>Udr93( z>OOnw9&~Yhyni@i2k}uP#4KQZPy>lE7ARoIl5xEM!NJCsREkivh=E7+*&jt2iX=jj zs6xWJ7baLqR1|E!7THA^*`!4_QB)G{Hu-iE_D#@5%dm80Ai|+jH!C6ulo4hkY7j7e z&l}6=>UD~)-pPor(l0yR`I!)9?aXe2#J@>$wJ1w^2da#=%4n;Mw#sO$NYPe5G)+F* zDtK^`ep9h<;f6nZUU{G1b02;TVDc0>zgeO3@Y*XFp1#XvjES?$g-?^HM;ese{59t0 NUjWPhA*a2P000!Lv2g$Z literal 2973 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 literal 2058 zcmV+l2=(_tRzVXz4j7B9R)BN+t~kXwN;gKySUZ|4eT^_O`$t_qN9Z1qu|RBucbtC3Zd>&De(o zlE@z)`5u3Ke0==5-}9JrAb$J>B#|BjJuHZWgv31$97ZS+6bE9!r1*i0l zZ~Ws%^t*ZY#yhvZyV+`??Psh1Tv#U#Pyq`a7pNqC0{k)Rc6KVQ7FuC`fF~BNVMLDmiwfKwmv-wwvur!12D1kzgKii9AMMwVR(b7Z;Z*72*esOLVff zwX)cLiTa%RsQM`jfPS5zwVV{KCD{ScmMR+mZ3^a9mrRgnz=SBBo7_QcPuT}H4s|{4`Ztqm<`N~5@>geQU zA%}yH!1e!(V46rI}QlZN=i>gQc0&8D5-s#5n|WnAOs?mNP@l1BMQ8( zN=3gS1J#9+mTCnMb~9FGPF_~j|9(gvNmy*dP^+UL?0LjNjC#ikG7&!d?ImTF)SF>| zke&rXmoh+FEwnQL)MuW@jtJe?r~+XQh#dmw#07ykJP!#67xj+Oc4G3)Awl-Sz{L{u z7)M%fp!7+y1_}w4i;q4=hu8}t8#6*BaEd+sB5k*3({(bAy08cX;LWu0xY4MwxRJEG znm=B=Zy}I)!gJ<*dCw97DB99}V{p#%a&PG_Jrqzb?zy@x z<8ZiQzJr|aASWX(nfI4C_)+5)AL-^F24DTJ+@Z_s6@yMqf`dZ>0#sh!hA2{RO}EoP z58CZEx{n^T(f#|#1&8?96SexNnH-Ip31WTJo}X5f{Inv{@0>xMx$a27Xl>kX*CLgYKgCPA`eb7TBLRYp&qAQrV+;xK|9mJ5s{;Hcjo5tcRKZrfmz zdv{CCB+F?>FPcd-@TJGn4VpO z9J?MeX^kQN$6(gqW)VZYw$Tg&`^#tm&jYOhhLATHbxubOCGkWnE;~JSs`f8D=u$ey zP{VK$Y(bSiOs>d;iRo8AM%(Z)a-~X&^_wB+y?WB!VVRRHdn|e)Oe{q4*@9vM^kKXv z(a`S!pYy_;7v{Y18uG$>7G99V2O+T^SR&^CH(24n<&K!oSz$J;pl6B`tw32y+n7*w zWabY)u?4HuhniZ)n%Zhd_A-Kb1489O6jSPXut4F3T<{15CCCEBJ}mg;1-K3tU<$ah zzPa+nUUzeKEt4_`bIg@V8RZevedL4B__0OUs?S__qNS{scE|NP@?<_t)%UO%L?_9X z+@iM(di<;0N5h{*9qkf&E{4<~*X-~)dC=lr-eEM$+fL|tqh|B=_lDVg^Y%QCXXd9- zPdRb-p(wIBb&ysg&*IL(Y_bHdfJ(}Fm!h=3;@B%1GoN=^EaeQs=YjA6)w6wCjy|cO6S>CWT zV}3hL=JiguWAAwW%hdOxv*%pKzL~U`_f`*p##WKNbTXqzUwOnQ*E-vA{GDs%dG}GW zjd2E;P~t{8I1k$SZ3MDibXY9B=ny-x7GcJxUJex;vCl?cBlbF`u{APn*^B3Gs-g8* zqU-2am!>+j&2t9e9PDK3&}}=|^9pjnP7JfVH^5??t`nd-;&2FDTKVYmbJ9`)hYhRX zRP+ofCnLsJzoguj;)Y(KM3>A57+L4XF5~4rwY~717_(C%3?e^HbRuE;*nyf_t{=wI oMK3z;guxP Date: Tue, 25 Feb 2025 15:19:13 -0500 Subject: [PATCH 64/75] Update changelog --- packages/core/solidity/CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/core/solidity/CHANGELOG.md b/packages/core/solidity/CHANGELOG.md index 4db5a7710..6ca2bcb17 100644 --- a/packages/core/solidity/CHANGELOG.md +++ b/packages/core/solidity/CHANGELOG.md @@ -1,9 +1,17 @@ # Changelog +## Unreleased + +- Add ERC20 Cross-Chain Bridging, SuperchainERC20. ([#436](https://github.com/OpenZeppelin/contracts-wizard/pull/436)) +**Note:** Cross-Chain Bridging is experimental and may be subject to change. + +- **Potentially breaking changes**: + - Change order of constructor argument `recipient` when using `premint`. + ## 0.5.1 (2025-02-05) - **Potentially breaking changes**: - - Add constructor argument `recipient` when using `premint` in `erc20`, `stablecoin`, and `realWorldAsset`. + - Add constructor argument `recipient` when using `premint` in `erc20`, `stablecoin`, and `realWorldAsset`. ([#435](https://github.com/OpenZeppelin/contracts-wizard/pull/435)) ## 0.5.0 (2025-01-23) From 457d102992d00937244ffb522cf1eb75c3b0d106 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 25 Feb 2025 15:27:40 -0500 Subject: [PATCH 65/75] Fix lint --- packages/core/solidity/src/erc20.test.ts | 60 ++++++++----- packages/core/solidity/src/erc20.ts | 88 ++++++++++++------- packages/core/solidity/src/error.ts | 2 +- .../core/solidity/src/generate/stablecoin.ts | 2 +- .../ui/src/solidity/superchain-tooltip.ts | 5 +- packages/ui/src/solidity/wiz-functions.ts | 22 ++++- 6 files changed, 119 insertions(+), 60 deletions(-) diff --git a/packages/core/solidity/src/erc20.test.ts b/packages/core/solidity/src/erc20.test.ts index 4ec5d6f61..b4b1b4e56 100644 --- a/packages/core/solidity/src/erc20.test.ts +++ b/packages/core/solidity/src/erc20.test.ts @@ -1,5 +1,6 @@ import test from 'ava'; -import { erc20, OptionsError } from '.'; +import type { OptionsError } from '.'; +import { erc20 } from '.'; import type { ERC20Options } from './erc20'; import { buildERC20 } from './erc20'; @@ -137,33 +138,48 @@ testERC20('erc20 crossChainBridging superchain managed', { }); test('erc20 crossChainBridging custom, upgradeable not allowed', async t => { - let error = t.throws(() => buildERC20({ - name: 'MyToken', - symbol: 'MTK', - crossChainBridging: 'custom', - upgradeable: 'transparent', - })); - t.is((error as OptionsError).messages.crossChainBridging, 'Upgradeability is not currently supported with Cross-Chain Bridging'); + const error = t.throws(() => + buildERC20({ + name: 'MyToken', + symbol: 'MTK', + crossChainBridging: 'custom', + upgradeable: 'transparent', + }), + ); + t.is( + (error as OptionsError).messages.crossChainBridging, + 'Upgradeability is not currently supported with Cross-Chain Bridging', + ); }); test('erc20 crossChainBridging superchain, upgradeable not allowed', async t => { - let error = t.throws(() => buildERC20({ - name: 'MyToken', - symbol: 'MTK', - crossChainBridging: 'superchain', - upgradeable: 'transparent', - })); - t.is((error as OptionsError).messages.crossChainBridging, 'Upgradeability is not currently supported with Cross-Chain Bridging'); + const error = t.throws(() => + buildERC20({ + name: 'MyToken', + symbol: 'MTK', + crossChainBridging: 'superchain', + upgradeable: 'transparent', + }), + ); + t.is( + (error as OptionsError).messages.crossChainBridging, + 'Upgradeability is not currently supported with Cross-Chain Bridging', + ); }); test('erc20 crossChainBridging superchain, premintChainId required', async t => { - let error = t.throws(() => buildERC20({ - name: 'MyToken', - symbol: 'MTK', - crossChainBridging: 'superchain', - premint: '2000', - })); - t.is((error as OptionsError).messages.premintChainId, 'Chain ID is required when using Premint with Cross-Chain Bridging'); + const error = t.throws(() => + buildERC20({ + name: 'MyToken', + symbol: 'MTK', + crossChainBridging: 'superchain', + premint: '2000', + }), + ); + t.is( + (error as OptionsError).messages.premintChainId, + 'Chain ID is required when using Premint with Cross-Chain Bridging', + ); }); testERC20('erc20 premint ignores chainId when not crossChainBridging', { diff --git a/packages/core/solidity/src/erc20.ts b/packages/core/solidity/src/erc20.ts index c3fc8b5d9..df7246a76 100644 --- a/packages/core/solidity/src/erc20.ts +++ b/packages/core/solidity/src/erc20.ts @@ -1,17 +1,21 @@ import { ContractBuilder } from './contract'; -import { Access, setAccessControl, requireAccessControl } from './set-access-control'; +import type { Access } from './set-access-control'; +import { setAccessControl, requireAccessControl } from './set-access-control'; import { addPauseFunctions } from './add-pausable'; import { defineFunctions } from './utils/define-functions'; -import { CommonOptions, withCommonDefaults, defaults as commonDefaults } from './common-options'; -import { setUpgradeable, Upgradeable } from './set-upgradeable'; +import type { CommonOptions } from './common-options'; +import { withCommonDefaults, defaults as commonDefaults } from './common-options'; +import type { Upgradeable } from './set-upgradeable'; +import { setUpgradeable } from './set-upgradeable'; import { setInfo } from './set-info'; import { printContract } from './print'; -import { ClockMode, clockModeDefault, setClockMode } from './set-clock-mode'; +import type { ClockMode } from './set-clock-mode'; +import { clockModeDefault, setClockMode } from './set-clock-mode'; import { supportsInterface } from './common-functions'; import { OptionsError } from './error'; export const crossChainBridgingOptions = [false, 'custom', 'superchain'] as const; -export type CrossChainBridging = typeof crossChainBridgingOptions[number]; +export type CrossChainBridging = (typeof crossChainBridgingOptions)[number]; export interface ERC20Options extends CommonOptions { name: string; @@ -159,7 +163,12 @@ export function isValidChainId(str: string): boolean { return chainIdPattern.test(str); } -function addPremint(c: ContractBuilder, amount: string, premintChainId: string, crossChainBridging: CrossChainBridging) { +function addPremint( + c: ContractBuilder, + amount: string, + premintChainId: string, + crossChainBridging: CrossChainBridging, +) { const m = amount.match(premintPattern); if (m) { const integer = m[1]?.replace(/^0+/, '') ?? ''; @@ -172,20 +181,20 @@ function addPremint(c: ContractBuilder, amount: string, premintChainId: string, const units = integer + decimals + zeroes; const exp = decimalPlace <= 0 ? 'decimals()' : `(decimals() - ${decimalPlace})`; - c.addConstructorArgument({type: 'address', name: 'recipient'}); + c.addConstructorArgument({ type: 'address', name: 'recipient' }); const mintLine = `_mint(recipient, ${units} * 10 ** ${exp});`; if (crossChainBridging) { if (premintChainId === '') { throw new OptionsError({ - premintChainId: 'Chain ID is required when using Premint with Cross-Chain Bridging' + premintChainId: 'Chain ID is required when using Premint with Cross-Chain Bridging', }); } if (!isValidChainId(premintChainId)) { throw new OptionsError({ - premintChainId: 'Not a valid chain ID' + premintChainId: 'Not a valid chain ID', }); } @@ -198,7 +207,7 @@ function addPremint(c: ContractBuilder, amount: string, premintChainId: string, } } else { throw new OptionsError({ - premint: 'Not a valid number' + premint: 'Not a valid number', }); } } @@ -250,7 +259,12 @@ function addFlashMint(c: ContractBuilder) { }); } -function addCrossChainBridging(c: ContractBuilder, crossChainBridging: 'custom' | 'superchain', upgradeable: Upgradeable, access: Access) { +function addCrossChainBridging( + c: ContractBuilder, + crossChainBridging: 'custom' | 'superchain', + upgradeable: Upgradeable, + access: Access, +) { const ERC20Bridgeable = { name: 'ERC20Bridgeable', path: `@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol`, @@ -261,7 +275,7 @@ function addCrossChainBridging(c: ContractBuilder, crossChainBridging: 'custom' if (upgradeable) { throw new OptionsError({ - crossChainBridging: 'Upgradeability is not currently supported with Cross-Chain Bridging' + crossChainBridging: 'Upgradeability is not currently supported with Cross-Chain Bridging', }); } @@ -273,9 +287,10 @@ function addCrossChainBridging(c: ContractBuilder, crossChainBridging: 'custom' case 'superchain': addSuperchainERC20(c); break; - default: + default: { const _: never = crossChainBridging; throw new Error('Unknown value for `crossChainBridging`'); + } } c.addVariable('error Unauthorized();'); } @@ -302,7 +317,11 @@ function addCustomBridging(c: ContractBuilder, access: Access) { c.addConstructorArgument({ type: 'address', name: roleOwner }); c.addConstructorCode(`_grantRole(${roleId}, ${roleOwner});`); } - c.setFunctionBody([`if (!hasRole(${roleId}, caller)) revert Unauthorized();`], functions._checkTokenBridge, 'view'); + c.setFunctionBody( + [`if (!hasRole(${roleId}, caller)) revert Unauthorized();`], + functions._checkTokenBridge, + 'view', + ); break; } case 'managed': { @@ -311,10 +330,14 @@ function addCustomBridging(c: ContractBuilder, access: Access) { name: 'AuthorityUtils', path: `@openzeppelin/contracts/access/manager/AuthorityUtils.sol`, }); - c.setFunctionBody([ - `(bool immediate,) = AuthorityUtils.canCallWithDelay(authority(), caller, address(this), bytes4(_msgData()[0:4]));`, - `if (!immediate) revert Unauthorized();` - ], functions._checkTokenBridge, 'view'); + c.setFunctionBody( + [ + `(bool immediate,) = AuthorityUtils.canCallWithDelay(authority(), caller, address(this), bytes4(_msgData()[0:4]));`, + `if (!immediate) revert Unauthorized();`, + ], + functions._checkTokenBridge, + 'view', + ); break; } default: { @@ -326,14 +349,21 @@ function addCustomBridging(c: ContractBuilder, access: Access) { function addSuperchainERC20(c: ContractBuilder) { c.addVariable('address internal constant SUPERCHAIN_TOKEN_BRIDGE = 0x4200000000000000000000000000000000000028;'); - c.setFunctionBody(['if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], functions._checkTokenBridge, 'pure'); - c.setFunctionComments([ - '/**', - ' * @dev Checks if the caller is the predeployed SuperchainTokenBridge. Reverts otherwise.', - ' *', - ' * IMPORTANT: The predeployed SuperchainTokenBridge is only available on chains in the Superchain.', - ' */', - ], functions._checkTokenBridge); + c.setFunctionBody( + ['if (caller != SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();'], + functions._checkTokenBridge, + 'pure', + ); + c.setFunctionComments( + [ + '/**', + ' * @dev Checks if the caller is the predeployed SuperchainTokenBridge. Reverts otherwise.', + ' *', + ' * IMPORTANT: The predeployed SuperchainTokenBridge is only available on chains in the Superchain.', + ' */', + ], + functions._checkTokenBridge, + ); } export const functions = defineFunctions({ @@ -388,8 +418,6 @@ export const functions = defineFunctions({ _checkTokenBridge: { kind: 'internal' as const, - args: [ - { name: 'caller', type: 'address' }, - ], - } + args: [{ name: 'caller', type: 'address' }], + }, }); diff --git a/packages/core/solidity/src/error.ts b/packages/core/solidity/src/error.ts index 8b3d2b8e3..a26433319 100644 --- a/packages/core/solidity/src/error.ts +++ b/packages/core/solidity/src/error.ts @@ -2,6 +2,6 @@ export type OptionsErrorMessages = { [prop in string]?: string }; export class OptionsError extends Error { constructor(readonly messages: OptionsErrorMessages) { - super("Invalid options"); + super('Invalid options'); } } diff --git a/packages/core/solidity/src/generate/stablecoin.ts b/packages/core/solidity/src/generate/stablecoin.ts index 9a0ea6a2f..8eba148fd 100644 --- a/packages/core/solidity/src/generate/stablecoin.ts +++ b/packages/core/solidity/src/generate/stablecoin.ts @@ -20,7 +20,7 @@ const erc20Basic = { crossChainBridging: [false] as const, access: [false] as const, info: [{}] as const, -} +}; const erc20Full = { name: ['MyStablecoin'], diff --git a/packages/ui/src/solidity/superchain-tooltip.ts b/packages/ui/src/solidity/superchain-tooltip.ts index 9e656806a..ff466d3a0 100644 --- a/packages/ui/src/solidity/superchain-tooltip.ts +++ b/packages/ui/src/solidity/superchain-tooltip.ts @@ -2,10 +2,11 @@ * Tippy.js properties for the Superchain tooltip. */ export const superchainTooltipProps: { [prop: string]: string | boolean } = { - content: 'Important: Only available on chains in the Superchain. Requires deploying your contract to the same address on every chain in the Superchain. Read more.', + content: + 'Important: Only available on chains in the Superchain. Requires deploying your contract to the same address on every chain in the Superchain. Read more.', trigger: 'manual', placement: 'bottom', maxWidth: '22em', allowHTML: true, interactive: true, -} \ No newline at end of file +}; diff --git a/packages/ui/src/solidity/wiz-functions.ts b/packages/ui/src/solidity/wiz-functions.ts index 54f13e9ce..d8832fa36 100644 --- a/packages/ui/src/solidity/wiz-functions.ts +++ b/packages/ui/src/solidity/wiz-functions.ts @@ -71,10 +71,24 @@ export const erc20Function = { 'Whether without paying gas, token holders will be able to allow third parties to transfer from their account.', }, // 'false' gets converted to false - votes: { type: 'string', enum: ['false', 'blocknumber', 'timestamp'], description: 'Whether to keep track of historical balances for voting in on-chain governance. Voting durations can be expressed as block numbers or timestamps.'}, - flashmint: { type: 'boolean', description: 'Whether to include built-in flash loans to allow lending tokens without requiring collateral as long as they\'re returned in the same transaction.' }, - crossChainBridging: { type: 'string', enum: ['false', 'custom', 'superchain'], description: 'Whether to allow authorized bridge contracts to mint and burn tokens for cross-chain transfers. Options are to use custom bridges on any chain, or the SuperchainERC20 standard with the predeployed SuperchainTokenBridge. Emphasize that these features are experimental, not audited and are subject to change. The SuperchainERC20 feature is only available on chains in the Superchain, and requires deploying your contract to the same address on every chain in the Superchain.' }, - ...commonOptions + votes: { + type: 'string', + enum: ['false', 'blocknumber', 'timestamp'], + description: + 'Whether to keep track of historical balances for voting in on-chain governance. Voting durations can be expressed as block numbers or timestamps.', + }, + flashmint: { + type: 'boolean', + description: + "Whether to include built-in flash loans to allow lending tokens without requiring collateral as long as they're returned in the same transaction.", + }, + crossChainBridging: { + type: 'string', + enum: ['false', 'custom', 'superchain'], + description: + 'Whether to allow authorized bridge contracts to mint and burn tokens for cross-chain transfers. Options are to use custom bridges on any chain, or the SuperchainERC20 standard with the predeployed SuperchainTokenBridge. Emphasize that these features are experimental, not audited and are subject to change. The SuperchainERC20 feature is only available on chains in the Superchain, and requires deploying your contract to the same address on every chain in the Superchain.', + }, + ...commonOptions, }, required: ['name', 'symbol'], }, From 3150588a0660c41153153dbdfb22a571de6af01c Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 25 Feb 2025 15:34:10 -0500 Subject: [PATCH 66/75] Fix svelte-check --- packages/ui/src/solidity/ERC20Controls.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/solidity/ERC20Controls.svelte b/packages/ui/src/solidity/ERC20Controls.svelte index 5b56a1b0a..4c153b156 100644 --- a/packages/ui/src/solidity/ERC20Controls.svelte +++ b/packages/ui/src/solidity/ERC20Controls.svelte @@ -77,7 +77,7 @@  Chain ID: - Chain ID of the network on which to premint tokens. + Chain ID of the network on which to premint tokens.

{/if}
From ffa6021c90b75ada325d5f4c33b4a29383ab99c4 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 25 Feb 2025 15:48:34 -0500 Subject: [PATCH 67/75] Update snapshots --- .../core/solidity/src/zip-foundry.test.ts.md | 16 ++++++++-------- .../solidity/src/zip-foundry.test.ts.snap | Bin 3480 -> 3485 bytes .../core/solidity/src/zip-hardhat.test.ts.md | 14 +++++++------- .../solidity/src/zip-hardhat.test.ts.snap | Bin 2299 -> 2297 bytes 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/core/solidity/src/zip-foundry.test.ts.md b/packages/core/solidity/src/zip-foundry.test.ts.md index 3c6d2afd8..ed8fbdc07 100644 --- a/packages/core/solidity/src/zip-foundry.test.ts.md +++ b/packages/core/solidity/src/zip-foundry.test.ts.md @@ -108,11 +108,11 @@ Generated by [AVA](https://avajs.dev). // TODO: Set addresses for the variables below, then uncomment the following section:␊ /*␊ vm.startBroadcast();␊ + address recipient = ;␊ address defaultAdmin = ;␊ address pauser = ;␊ - address recipient = ;␊ address minter = ;␊ - MyToken instance = new MyToken(defaultAdmin, pauser, recipient, minter);␊ + MyToken instance = new MyToken(recipient, defaultAdmin, pauser, minter);␊ console.log("Contract deployed to %s", address(instance));␊ vm.stopBroadcast();␊ */␊ @@ -136,13 +136,13 @@ Generated by [AVA](https://avajs.dev). bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");␊ bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");␊ ␊ - constructor(address defaultAdmin, address pauser, address recipient, address minter)␊ + constructor(address recipient, address defaultAdmin, address pauser, address minter)␊ ERC20("My Token", "MTK")␊ ERC20Permit("My Token")␊ {␊ + _mint(recipient, 2000 * 10 ** decimals());␊ _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ _grantRole(PAUSER_ROLE, pauser);␊ - _mint(recipient, 2000 * 10 ** decimals());␊ _grantRole(MINTER_ROLE, minter);␊ }␊ ␊ @@ -187,11 +187,11 @@ Generated by [AVA](https://avajs.dev). MyToken public instance;␊ ␊ function setUp() public {␊ - address defaultAdmin = vm.addr(1);␊ - address pauser = vm.addr(2);␊ - address recipient = vm.addr(3);␊ + address recipient = vm.addr(1);␊ + address defaultAdmin = vm.addr(2);␊ + address pauser = vm.addr(3);␊ address minter = vm.addr(4);␊ - instance = new MyToken(defaultAdmin, pauser, recipient, minter);␊ + instance = new MyToken(recipient, defaultAdmin, pauser, minter);␊ }␊ ␊ function testName() public view {␊ diff --git a/packages/core/solidity/src/zip-foundry.test.ts.snap b/packages/core/solidity/src/zip-foundry.test.ts.snap index 803c20175524ea099b63f6108f9459a9f75573bf..d67a784c0f26d67a2035ea8095e5cfdb4fba0630 100644 GIT binary patch literal 3485 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 LG^??CIe`EGC*Py@ literal 3480 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 GfdBxwp{(No diff --git a/packages/core/solidity/src/zip-hardhat.test.ts.md b/packages/core/solidity/src/zip-hardhat.test.ts.md index 17b7438f5..a7d55801f 100644 --- a/packages/core/solidity/src/zip-hardhat.test.ts.md +++ b/packages/core/solidity/src/zip-hardhat.test.ts.md @@ -26,13 +26,13 @@ Generated by [AVA](https://avajs.dev). bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");␊ bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");␊ ␊ - constructor(address defaultAdmin, address pauser, address recipient, address minter)␊ + constructor(address recipient, address defaultAdmin, address pauser, address minter)␊ ERC20("My Token", "MTK")␊ ERC20Permit("My Token")␊ {␊ + _mint(recipient, 2000 * 10 ** decimals());␊ _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);␊ _grantRole(PAUSER_ROLE, pauser);␊ - _mint(recipient, 2000 * 10 ** decimals());␊ _grantRole(MINTER_ROLE, minter);␊ }␊ ␊ @@ -106,7 +106,7 @@ Generated by [AVA](https://avajs.dev). const ContractFactory = await ethers.getContractFactory("MyToken");␊ ␊ // TODO: Set addresses for the contract arguments below␊ - const instance = await ContractFactory.deploy(defaultAdmin, pauser, recipient, minter);␊ + const instance = await ContractFactory.deploy(recipient, defaultAdmin, pauser, minter);␊ await instance.waitForDeployment();␊ ␊ console.log(\`Contract deployed to ${await instance.getAddress()}\`);␊ @@ -126,12 +126,12 @@ Generated by [AVA](https://avajs.dev). it("Test contract", async function () {␊ const ContractFactory = await ethers.getContractFactory("MyToken");␊ ␊ - const defaultAdmin = (await ethers.getSigners())[0].address;␊ - const pauser = (await ethers.getSigners())[1].address;␊ - const recipient = (await ethers.getSigners())[2].address;␊ + const recipient = (await ethers.getSigners())[0].address;␊ + const defaultAdmin = (await ethers.getSigners())[1].address;␊ + const pauser = (await ethers.getSigners())[2].address;␊ const minter = (await ethers.getSigners())[3].address;␊ ␊ - const instance = await ContractFactory.deploy(defaultAdmin, pauser, recipient, minter);␊ + const instance = await ContractFactory.deploy(recipient, defaultAdmin, pauser, minter);␊ await instance.waitForDeployment();␊ ␊ expect(await instance.name()).to.equal("My Token");␊ diff --git a/packages/core/solidity/src/zip-hardhat.test.ts.snap b/packages/core/solidity/src/zip-hardhat.test.ts.snap index 231d727b36f907a67f823f6b68da22f925af94cf..9169ca98da84033b8731f2922b7ef744c4beb1b8 100644 GIT binary patch delta 1743 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 From cf6e0d54bf6d49815777bd5069b5badeb9708e54 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 26 Feb 2025 10:39:51 -0500 Subject: [PATCH 68/75] Hide action buttons if error --- packages/ui/src/solidity/App.svelte | 49 +++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/packages/ui/src/solidity/App.svelte b/packages/ui/src/solidity/App.svelte index e227b8e74..449fc1378 100644 --- a/packages/ui/src/solidity/App.svelte +++ b/packages/ui/src/solidity/App.svelte @@ -93,6 +93,9 @@ $: code = printContract(contract); $: highlightedCode = injectHyperlinks(hljs.highlight('solidity', code).value); + $: hasErrors = errors[tab] !== undefined; + $: showDeployModal = !hasErrors && showDeployModal; + $: if (showDeployModal) { let deterministicReason: string | undefined; if (opts && opts.kind === 'ERC20' && opts.crossChainBridging === 'superchain') { @@ -259,6 +262,49 @@
+ {#if hasErrors} +
+ + +
+

There are errors in the input options.

+

Fix them to continue.

+
+
+ + +
+

There are errors in the input options.

+

Fix them to continue.

+
+
+
+ {:else}
+ {/if}
@@ -361,6 +408,7 @@
+ {#if !hasErrors}
+ {/if}
         {@html highlightedCode}
       
From d0b918a28edf3edb0510ce5111ed16171b5c5b90 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 26 Feb 2025 12:05:45 -0500 Subject: [PATCH 69/75] Prevent code text selection if error --- packages/ui/src/solidity/App.svelte | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/solidity/App.svelte b/packages/ui/src/solidity/App.svelte index 449fc1378..d565d5007 100644 --- a/packages/ui/src/solidity/App.svelte +++ b/packages/ui/src/solidity/App.svelte @@ -434,7 +434,7 @@
{/if}
-        {@html highlightedCode}
+        {@html highlightedCode}
       
@@ -504,6 +504,11 @@ --blur: 0px; } } + +.no-select { + user-select: none; +} + .button-bg{ animation: conic-effect 12s ease-in-out infinite; animation-delay: 4.2s; From dcc7d7dd612b4f4c42e6f102dd3f777235f6ba4c Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 27 Feb 2025 11:33:56 -0500 Subject: [PATCH 70/75] Group by Superchain in network selection --- packages/ui/src/common/post-message.ts | 1 + packages/ui/src/solidity/App.svelte | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/common/post-message.ts b/packages/ui/src/common/post-message.ts index 3a23aa9af..9535c7b93 100644 --- a/packages/ui/src/common/post-message.ts +++ b/packages/ui/src/common/post-message.ts @@ -20,6 +20,7 @@ export interface DefenderDeployMessage { kind: 'oz-wizard-defender-deploy'; sources: SolcInputSources; enforceDeterministicReason?: string; + groupNetworksBy?: 'superchain'; } export function postMessage(msg: Message) { diff --git a/packages/ui/src/solidity/App.svelte b/packages/ui/src/solidity/App.svelte index d565d5007..97b667f3b 100644 --- a/packages/ui/src/solidity/App.svelte +++ b/packages/ui/src/solidity/App.svelte @@ -97,14 +97,18 @@ $: showDeployModal = !hasErrors && showDeployModal; $: if (showDeployModal) { - let deterministicReason: string | undefined; - if (opts && opts.kind === 'ERC20' && opts.crossChainBridging === 'superchain') { - deterministicReason = 'SuperchainERC20 requires deploying your contract to the same address on every chain in the Superchain.'; + let enforceDeterministicReason: string | undefined; + let groupNetworksBy: 'superchain' | undefined; + if (opts !== undefined && (opts.kind === 'ERC20' || opts.kind === 'Stablecoin' || opts.kind === 'RealWorldAsset' ) && opts.crossChainBridging === 'superchain') { + enforceDeterministicReason = 'SuperchainERC20 requires deploying your contract to the same address on every chain in the Superchain.'; + groupNetworksBy = 'superchain'; } + postMessageToIframe('defender-deploy', { kind: 'oz-wizard-defender-deploy', sources: getSolcSources(contract), - enforceDeterministicReason: deterministicReason, + enforceDeterministicReason, + groupNetworksBy, }); } From c7e88cb15e0084f7ec0679ed14b7fb08f93ccdae Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 27 Feb 2025 15:53:06 -0500 Subject: [PATCH 71/75] Extract if condition into variable --- packages/ui/src/solidity/App.svelte | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/solidity/App.svelte b/packages/ui/src/solidity/App.svelte index 97b667f3b..1f3829f3d 100644 --- a/packages/ui/src/solidity/App.svelte +++ b/packages/ui/src/solidity/App.svelte @@ -99,7 +99,11 @@ $: if (showDeployModal) { let enforceDeterministicReason: string | undefined; let groupNetworksBy: 'superchain' | undefined; - if (opts !== undefined && (opts.kind === 'ERC20' || opts.kind === 'Stablecoin' || opts.kind === 'RealWorldAsset' ) && opts.crossChainBridging === 'superchain') { + + const isSuperchainERC20 = opts !== undefined && + (opts.kind === 'ERC20' || opts.kind === 'Stablecoin' || opts.kind === 'RealWorldAsset') && + opts.crossChainBridging === 'superchain'; + if (isSuperchainERC20) { enforceDeterministicReason = 'SuperchainERC20 requires deploying your contract to the same address on every chain in the Superchain.'; groupNetworksBy = 'superchain'; } From d4f2dac374a8c850ab100960334579cf654e3e0b Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 5 Mar 2025 18:09:34 -0500 Subject: [PATCH 72/75] Add testcase for bridging ownable mintable --- packages/core/solidity/src/erc20.test.ts | 7 ++++ packages/core/solidity/src/erc20.test.ts.md | 37 ++++++++++++++++++ packages/core/solidity/src/erc20.test.ts.snap | Bin 2965 -> 3012 bytes 3 files changed, 44 insertions(+) diff --git a/packages/core/solidity/src/erc20.test.ts b/packages/core/solidity/src/erc20.test.ts index b4b1b4e56..4a01966e8 100644 --- a/packages/core/solidity/src/erc20.test.ts +++ b/packages/core/solidity/src/erc20.test.ts @@ -108,6 +108,13 @@ testERC20('erc20 crossChainBridging custom ownable', { access: 'ownable', }); +testERC20('erc20 crossChainBridging custom ownable mintable', { + crossChainBridging: 'custom', + access: 'ownable', + mintable: true, + burnable: true, +}); + testERC20('erc20 crossChainBridging custom roles', { crossChainBridging: 'custom', access: 'roles', diff --git a/packages/core/solidity/src/erc20.test.ts.md b/packages/core/solidity/src/erc20.test.ts.md index dcc42521a..92d8c0343 100644 --- a/packages/core/solidity/src/erc20.test.ts.md +++ b/packages/core/solidity/src/erc20.test.ts.md @@ -501,6 +501,43 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## erc20 crossChainBridging custom ownable mintable + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.22;␊ + ␊ + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊ + import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊ + import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";␊ + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊ + import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";␊ + ␊ + contract MyToken is ERC20, ERC20Bridgeable, ERC20Burnable, Ownable, ERC20Permit {␊ + address public immutable TOKEN_BRIDGE;␊ + error Unauthorized();␊ + ␊ + constructor(address tokenBridge, address initialOwner)␊ + ERC20("MyToken", "MTK")␊ + Ownable(initialOwner)␊ + ERC20Permit("MyToken")␊ + {␊ + require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");␊ + TOKEN_BRIDGE = tokenBridge;␊ + }␊ + ␊ + function _checkTokenBridge(address caller) internal view override {␊ + if (caller != TOKEN_BRIDGE) revert Unauthorized();␊ + }␊ + ␊ + function mint(address to, uint256 amount) public onlyOwner {␊ + _mint(to, amount);␊ + }␊ + }␊ + ` + ## erc20 crossChainBridging custom roles > Snapshot 1 diff --git a/packages/core/solidity/src/erc20.test.ts.snap b/packages/core/solidity/src/erc20.test.ts.snap index 8bf407ad33c58a115242fa28c563ea9f838cacbb..e1d383f5f424b9efb18d3b5f6e14886387c31778 100644 GIT binary patch literal 3012 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 From 0f3cc82ff551f2846a1c11b8c425e3c6cd834c32 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 5 Mar 2025 18:13:10 -0500 Subject: [PATCH 73/75] Update testcase name --- packages/core/solidity/src/erc20.test.ts | 2 +- packages/core/solidity/src/erc20.test.ts.md | 2 +- packages/core/solidity/src/erc20.test.ts.snap | Bin 3012 -> 3016 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/solidity/src/erc20.test.ts b/packages/core/solidity/src/erc20.test.ts index 4a01966e8..14a2caa46 100644 --- a/packages/core/solidity/src/erc20.test.ts +++ b/packages/core/solidity/src/erc20.test.ts @@ -108,7 +108,7 @@ testERC20('erc20 crossChainBridging custom ownable', { access: 'ownable', }); -testERC20('erc20 crossChainBridging custom ownable mintable', { +testERC20('erc20 crossChainBridging custom ownable mintable burnable', { crossChainBridging: 'custom', access: 'ownable', mintable: true, diff --git a/packages/core/solidity/src/erc20.test.ts.md b/packages/core/solidity/src/erc20.test.ts.md index 92d8c0343..81a604339 100644 --- a/packages/core/solidity/src/erc20.test.ts.md +++ b/packages/core/solidity/src/erc20.test.ts.md @@ -501,7 +501,7 @@ Generated by [AVA](https://avajs.dev). }␊ ` -## erc20 crossChainBridging custom ownable mintable +## erc20 crossChainBridging custom ownable mintable burnable > Snapshot 1 diff --git a/packages/core/solidity/src/erc20.test.ts.snap b/packages/core/solidity/src/erc20.test.ts.snap index e1d383f5f424b9efb18d3b5f6e14886387c31778..c17d6fdaa5082271f36c353eef3badf5bd4313cc 100644 GIT binary patch delta 2809 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

=gq)K!Uw)~Lf6DL- Date: Thu, 13 Mar 2025 16:16:39 -0400 Subject: [PATCH 74/75] Bump versions for publishing --- packages/core/solidity/CHANGELOG.md | 2 +- packages/core/solidity/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/solidity/CHANGELOG.md b/packages/core/solidity/CHANGELOG.md index 6c6bf69a0..746dde13a 100644 --- a/packages/core/solidity/CHANGELOG.md +++ b/packages/core/solidity/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 0.5.3 (2025-03-13) - Add ERC20 Cross-Chain Bridging, SuperchainERC20. ([#436](https://github.com/OpenZeppelin/contracts-wizard/pull/436)) **Note:** Cross-Chain Bridging is experimental and may be subject to change. diff --git a/packages/core/solidity/package.json b/packages/core/solidity/package.json index 968fd114a..9b48718a3 100644 --- a/packages/core/solidity/package.json +++ b/packages/core/solidity/package.json @@ -1,6 +1,6 @@ { "name": "@openzeppelin/wizard", - "version": "0.5.2", + "version": "0.5.3", "description": "A boilerplate generator to get started with OpenZeppelin Contracts", "license": "AGPL-3.0-only", "repository": "https://github.com/OpenZeppelin/contracts-wizard", From 9fab82c4035d485db8ea165f62e7409457c9dd14 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 13 Mar 2025 16:20:56 -0400 Subject: [PATCH 75/75] Update widths for other langs --- packages/ui/src/stellar/App.svelte | 2 +- packages/ui/src/stylus/App.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/stellar/App.svelte b/packages/ui/src/stellar/App.svelte index 8271b93fe..1fbea68de 100644 --- a/packages/ui/src/stellar/App.svelte +++ b/packages/ui/src/stellar/App.svelte @@ -127,7 +127,7 @@

-
+
diff --git a/packages/ui/src/stylus/App.svelte b/packages/ui/src/stylus/App.svelte index a93bd36fc..12e5cceb3 100644 --- a/packages/ui/src/stylus/App.svelte +++ b/packages/ui/src/stylus/App.svelte @@ -141,7 +141,7 @@
-
+