Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/core/solidity/src/erc20.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ testERC20('erc20 mintable with roles', {
access: 'roles',
});

testERC20('erc20 + erc1363', {
erc1363: true,
});

testERC20('erc20 permit', {
permit: true,
});
Expand Down Expand Up @@ -249,6 +253,7 @@ testERC20('erc20 full crossChainBridging custom non-upgradeable', {
burnable: true,
mintable: true,
pausable: true,
erc1363: true,
permit: true,
votes: true,
flashmint: true,
Expand All @@ -262,6 +267,7 @@ testERC20('erc20 full upgradeable transparent', {
burnable: true,
mintable: true,
pausable: true,
erc1363: true,
permit: true,
votes: true,
flashmint: true,
Expand All @@ -274,6 +280,7 @@ testERC20('erc20 full upgradeable uups', {
burnable: true,
mintable: true,
pausable: true,
erc1363: true,
permit: true,
votes: true,
flashmint: true,
Expand All @@ -286,6 +293,7 @@ testERC20('erc20 full upgradeable uups managed', {
burnable: true,
mintable: true,
pausable: true,
erc1363: true,
permit: true,
votes: true,
flashmint: true,
Expand All @@ -304,6 +312,7 @@ testAPIEquivalence('erc20 API full upgradeable', {
burnable: true,
mintable: true,
pausable: true,
erc1363: true,
permit: true,
votes: true,
flashmint: true,
Expand Down
52 changes: 47 additions & 5 deletions packages/core/solidity/src/erc20.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,23 @@ Generated by [AVA](https://avajs.dev).
}␊
`

## erc20 + erc1363

> Snapshot 1

`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts ^5.0.0␊
pragma solidity ^0.8.22;␊
import {ERC1363} from "@openzeppelin/contracts/token/ERC20/extensions/ERC1363.sol";␊
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊
import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊
contract MyToken is ERC20, ERC1363, ERC20Permit {␊
constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") {}␊
}␊
`

## erc20 permit

> Snapshot 1
Expand Down Expand Up @@ -915,6 +932,7 @@ Generated by [AVA](https://avajs.dev).
pragma solidity ^0.8.22;␊
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";␊
import {ERC1363} from "@openzeppelin/contracts/token/ERC20/extensions/ERC1363.sol";␊
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";␊
Expand All @@ -924,7 +942,7 @@ 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, ERC20Bridgeable, AccessControl, ERC20Burnable, ERC20Pausable, ERC20Permit, ERC20Votes, ERC20FlashMint {␊
contract MyToken is ERC20, ERC20Bridgeable, AccessControl, ERC20Burnable, ERC20Pausable, ERC1363, ERC20Permit, ERC20Votes, ERC20FlashMint {␊
bytes32 public constant TOKEN_BRIDGE_ROLE = keccak256("TOKEN_BRIDGE_ROLE");␊
error Unauthorized();␊
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");␊
Expand Down Expand Up @@ -971,7 +989,7 @@ Generated by [AVA](https://avajs.dev).
function supportsInterface(bytes4 interfaceId)␊
public␊
view␊
override(ERC20Bridgeable, AccessControl)␊
override(ERC20Bridgeable, AccessControl, ERC1363)␊
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious how ordering is done. Not a blocker (I'd merge like that) but if we can clarify this in a further PR that would be great.

returns (bool)␊
{␊
return super.supportsInterface(interfaceId);␊
Expand All @@ -997,6 +1015,7 @@ Generated by [AVA](https://avajs.dev).
pragma solidity ^0.8.22;␊
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";␊
import {ERC1363Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC1363Upgradeable.sol";␊
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";␊
import {ERC20BurnableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";␊
import {ERC20FlashMintUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20FlashMintUpgradeable.sol";␊
Expand All @@ -1006,7 +1025,7 @@ Generated by [AVA](https://avajs.dev).
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";␊
import {NoncesUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/NoncesUpgradeable.sol";␊
contract MyToken is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, ERC20PausableUpgradeable, AccessControlUpgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable, ERC20FlashMintUpgradeable {␊
contract MyToken is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, ERC20PausableUpgradeable, AccessControlUpgradeable, ERC1363Upgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable, ERC20FlashMintUpgradeable {␊
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");␊
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");␊
Expand All @@ -1022,6 +1041,7 @@ Generated by [AVA](https://avajs.dev).
__ERC20Burnable_init();␊
__ERC20Pausable_init();␊
__AccessControl_init();␊
__ERC1363_init();␊
__ERC20Permit_init("MyToken");␊
__ERC20Votes_init();␊
__ERC20FlashMint_init();␊
Expand Down Expand Up @@ -1052,6 +1072,15 @@ Generated by [AVA](https://avajs.dev).
{␊
super._update(from, to, value);␊
}␊
function supportsInterface(bytes4 interfaceId)␊
public␊
view␊
override(AccessControlUpgradeable, ERC1363Upgradeable)␊
returns (bool)␊
{␊
return super.supportsInterface(interfaceId);␊
}␊
function nonces(address owner)␊
public␊
Expand All @@ -1073,6 +1102,7 @@ Generated by [AVA](https://avajs.dev).
pragma solidity ^0.8.22;␊
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";␊
import {ERC1363Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC1363Upgradeable.sol";␊
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";␊
import {ERC20BurnableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";␊
import {ERC20FlashMintUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20FlashMintUpgradeable.sol";␊
Expand All @@ -1083,7 +1113,7 @@ Generated by [AVA](https://avajs.dev).
import {NoncesUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/NoncesUpgradeable.sol";␊
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";␊
contract MyToken is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, ERC20PausableUpgradeable, AccessControlUpgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable, ERC20FlashMintUpgradeable, UUPSUpgradeable {␊
contract MyToken is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, ERC20PausableUpgradeable, AccessControlUpgradeable, ERC1363Upgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable, ERC20FlashMintUpgradeable, UUPSUpgradeable {␊
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");␊
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");␊
bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");␊
Expand All @@ -1100,6 +1130,7 @@ Generated by [AVA](https://avajs.dev).
__ERC20Burnable_init();␊
__ERC20Pausable_init();␊
__AccessControl_init();␊
__ERC1363_init();␊
__ERC20Permit_init("MyToken");␊
__ERC20Votes_init();␊
__ERC20FlashMint_init();␊
Expand Down Expand Up @@ -1138,6 +1169,15 @@ Generated by [AVA](https://avajs.dev).
{␊
super._update(from, to, value);␊
}␊
function supportsInterface(bytes4 interfaceId)␊
public␊
view␊
override(AccessControlUpgradeable, ERC1363Upgradeable)␊
returns (bool)␊
{␊
return super.supportsInterface(interfaceId);␊
}␊
function nonces(address owner)␊
public␊
Expand All @@ -1159,6 +1199,7 @@ Generated by [AVA](https://avajs.dev).
pragma solidity ^0.8.22;␊
import {AccessManagedUpgradeable} from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol";␊
import {ERC1363Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC1363Upgradeable.sol";␊
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";␊
import {ERC20BurnableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";␊
import {ERC20FlashMintUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20FlashMintUpgradeable.sol";␊
Expand All @@ -1169,7 +1210,7 @@ Generated by [AVA](https://avajs.dev).
import {NoncesUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/NoncesUpgradeable.sol";␊
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";␊
contract MyToken is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, ERC20PausableUpgradeable, AccessManagedUpgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable, ERC20FlashMintUpgradeable, UUPSUpgradeable {␊
contract MyToken is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, ERC20PausableUpgradeable, AccessManagedUpgradeable, ERC1363Upgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable, ERC20FlashMintUpgradeable, UUPSUpgradeable {␊
/// @custom:oz-upgrades-unsafe-allow constructor␊
constructor() {␊
_disableInitializers();␊
Expand All @@ -1182,6 +1223,7 @@ Generated by [AVA](https://avajs.dev).
__ERC20Burnable_init();␊
__ERC20Pausable_init();␊
__AccessManaged_init(initialAuthority);␊
__ERC1363_init();␊
__ERC20Permit_init("MyToken");␊
__ERC20Votes_init();␊
__ERC20FlashMint_init();␊
Expand Down
Binary file modified packages/core/solidity/src/erc20.test.ts.snap
Binary file not shown.
16 changes: 16 additions & 0 deletions packages/core/solidity/src/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface ERC20Options extends CommonOptions {
premint?: string;
premintChainId?: string;
mintable?: boolean;
erc1363?: boolean;
permit?: boolean;
/**
* Whether to keep track of historical balances for voting in on-chain governance, and optionally specify the clock mode.
Expand All @@ -44,6 +45,7 @@ export const defaults: Required<ERC20Options> = {
premint: '0',
premintChainId: '',
mintable: false,
erc1363: false,
permit: true,
votes: false,
flashmint: false,
Expand All @@ -62,6 +64,7 @@ export function withDefaults(opts: ERC20Options): Required<ERC20Options> {
premint: opts.premint || defaults.premint,
premintChainId: opts.premintChainId || defaults.premintChainId,
mintable: opts.mintable ?? defaults.mintable,
erc1363: opts.erc1363 ?? defaults.erc1363,
permit: opts.permit ?? defaults.permit,
votes: opts.votes ?? defaults.votes,
flashmint: opts.flashmint ?? defaults.flashmint,
Expand Down Expand Up @@ -106,6 +109,10 @@ export function buildERC20(opts: ERC20Options): ContractBuilder {
addMintable(c, access);
}

if (allOpts.erc1363) {
addERC1363(c);
}

// Note: Votes requires Permit
if (allOpts.permit || allOpts.votes) {
addPermit(c, allOpts.name);
Expand Down Expand Up @@ -247,6 +254,15 @@ function addMintable(c: ContractBuilder, access: Access) {
c.addFunctionCode('_mint(to, amount);', functions.mint);
}

function addERC1363(c: ContractBuilder) {
const ERC1363 = {
name: 'ERC1363',
path: '@openzeppelin/contracts/token/ERC20/extensions/ERC1363.sol',
};
c.addParent(ERC1363);
c.addOverride(ERC1363, supportsInterface);
}

function addPermit(c: ContractBuilder, name: string) {
const ERC20Permit = {
name: 'ERC20Permit',
Expand Down
1 change: 1 addition & 0 deletions packages/core/solidity/src/generate/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const blueprint = {
burnable: booleans,
pausable: booleans,
mintable: booleans,
erc1363: booleans,
permit: booleans,
votes: [...booleans, ...clockModeOptions] as const,
flashmint: booleans,
Expand Down
2 changes: 2 additions & 0 deletions packages/core/solidity/src/generate/stablecoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const erc20Basic = {
burnable: [false] as const,
pausable: [false] as const,
mintable: [false] as const,
erc1363: [false] as const,
permit: [false] as const,
votes: [false] as const,
flashmint: [false] as const,
Expand All @@ -28,6 +29,7 @@ const erc20Full = {
burnable: [true] as const,
pausable: [true] as const,
mintable: [true] as const,
erc1363: [true] as const,
permit: [true] as const,
votes: ['timestamp'] as const,
flashmint: [true] as const,
Expand Down
6 changes: 6 additions & 0 deletions packages/core/solidity/src/stablecoin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ testStablecoin('stablecoin mintable with roles', {
access: 'roles',
});

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

testStablecoin('stablecoin permit', {
permit: true,
});
Expand Down Expand Up @@ -118,6 +122,7 @@ testStablecoin('stablecoin full', {
burnable: true,
mintable: true,
pausable: true,
erc1363: true,
permit: true,
votes: true,
flashmint: true,
Expand All @@ -142,6 +147,7 @@ testAPIEquivalence('stablecoin API full', {
burnable: true,
mintable: true,
pausable: true,
erc1363: true,
permit: true,
votes: true,
flashmint: true,
Expand Down
22 changes: 20 additions & 2 deletions packages/core/solidity/src/stablecoin.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,23 @@ Generated by [AVA](https://avajs.dev).
}␊
`

## stablecoin erc1363

> Snapshot 1

`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Contracts ^5.0.0␊
pragma solidity ^0.8.22;␊
import {ERC1363} from "@openzeppelin/contracts/token/ERC20/extensions/ERC1363.sol";␊
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊
import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";␊
contract MyStablecoin is ERC20, ERC1363, ERC20Permit {␊
constructor() ERC20("MyStablecoin", "MST") ERC20Permit("MyStablecoin") {}␊
}␊
`

## stablecoin permit

> Snapshot 1
Expand Down Expand Up @@ -575,6 +592,7 @@ Generated by [AVA](https://avajs.dev).
pragma solidity ^0.8.22;␊
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";␊
import {ERC1363} from "@openzeppelin/contracts/token/ERC20/extensions/ERC1363.sol";␊
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";␊
import {ERC20Allowlist} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Allowlist.sol";␊
import {ERC20Bridgeable} from "@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol";␊
Expand All @@ -586,7 +604,7 @@ 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 MyStablecoin is ERC20, ERC20Bridgeable, AccessControl, ERC20Burnable, ERC20Pausable, ERC20Permit, ERC20Votes, ERC20FlashMint, ERC20Custodian, ERC20Allowlist {␊
contract MyStablecoin is ERC20, ERC20Bridgeable, AccessControl, ERC20Burnable, ERC20Pausable, ERC1363, ERC20Permit, ERC20Votes, ERC20FlashMint, ERC20Custodian, ERC20Allowlist {␊
bytes32 public constant TOKEN_BRIDGE_ROLE = keccak256("TOKEN_BRIDGE_ROLE");␊
error Unauthorized();␊
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");␊
Expand Down Expand Up @@ -656,7 +674,7 @@ Generated by [AVA](https://avajs.dev).
function supportsInterface(bytes4 interfaceId)␊
public␊
view␊
override(ERC20Bridgeable, AccessControl)␊
override(ERC20Bridgeable, AccessControl, ERC1363)␊
returns (bool)␊
{␊
return super.supportsInterface(interfaceId);␊
Expand Down
Binary file modified packages/core/solidity/src/stablecoin.test.ts.snap
Binary file not shown.
8 changes: 8 additions & 0 deletions packages/ui/src/solidity/ERC20Controls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@
</HelpTooltip>
</label>

<label class:checked={opts.erc1363}>
<input type="checkbox" bind:checked={opts.erc1363}>
Callback
<HelpTooltip link="https://docs.openzeppelin.com/contracts/5.x/api/token/erc20#ERC1363">
Supports code execution after transfers and approvals on recipient contracts in a single transaction.
</HelpTooltip>
</label>

<label class:checked={opts.permit || opts.votes}>
<input type="checkbox" bind:checked={opts.permit}>
Permit
Expand Down
8 changes: 8 additions & 0 deletions packages/ui/src/solidity/RealWorldAssetControls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@
</HelpTooltip>
</label>

<label class:checked={opts.erc1363}>
<input type="checkbox" bind:checked={opts.erc1363}>
Callback
<HelpTooltip link="https://docs.openzeppelin.com/contracts/5.x/api/token/erc20#ERC1363">
Supports code execution after transfers and approvals on recipient contracts in a single transaction.
</HelpTooltip>
</label>

<label class:checked={opts.permit || opts.votes}>
<input type="checkbox" bind:checked={opts.permit}>
Permit
Expand Down
Loading