superfuse-wizard
Version:
Interactive smart contract generator based on Superchain 's interoperability standard.
269 lines (209 loc) • 6.88 kB
text/typescript
import type { Contract, BaseFunction} from './contract';
import { ContractBuilder } from './contract';
import type { Access } from './set-access-control';
import {setAccessControl, requireAccessControl } from './set-access-control';
import { withCommonDefaults, defaults as commonDefaults } from "../shared/option-l2-native-superchain-ERC20";
import type { SharedL2NativeSuperchainERC20Options } from "../shared/option-l2-native-superchain-ERC20";
import { printContract } from "./print";
import { setInfo } from "./set-info";
import type { ClockMode} from './set-clock-mode';
import { clockModeDefault, setClockMode } from './set-clock-mode';
import { supportsInterface } from './common-functions';
import { defineFunctions } from '../utils/define-functions';
export function isAccessControlRequired(opts: Partial<SharedL2NativeSuperchainERC20Options>): boolean {
return opts.mintable == true
}
function withDefaults(opts: SharedL2NativeSuperchainERC20Options): Required<SharedL2NativeSuperchainERC20Options> {
return {
...opts,
...withCommonDefaults(opts),
ownerAddress: opts.ownerAddress || commonDefaults.ownerAddress,
burnable: opts.burnable ?? commonDefaults.burnable,
pausable: opts.pausable ?? commonDefaults.pausable,
premint: opts.premint || commonDefaults.premint,
mintable: opts.mintable ?? commonDefaults.mintable,
minterAddress: opts.minterAddress || commonDefaults.minterAddress,
permit: opts.permit ?? commonDefaults.permit,
votes: opts.votes ?? commonDefaults.votes,
flashmint: opts.flashmint ?? commonDefaults.flashmint,
};
}
export function printL2NativeSuperchainERC20(opts: SharedL2NativeSuperchainERC20Options = commonDefaults): string {
return printContract(buildL2NativeSuperchainERC20(opts));
}
export function buildL2NativeSuperchainERC20(opts: SharedL2NativeSuperchainERC20Options): Contract {
const allOpts = withDefaults(opts);
const c = new ContractBuilder(allOpts.contractName);
const { access, upgradeable, contractInfo } = allOpts;
addBase(c);
setERC7802Logic(c);
// if (allOpts.burnable) {
// addBurnable(c);
// }
// if (allOpts.pausable) {
// addPausableExtension(c, access);
// }
// if (allOpts.premint) {
// addPremint(c, allOpts.premint);
// }
if (allOpts.mintable) {
addMintable(c, access);
}
// // Note: Votes requires Permit
// if (allOpts.permit || allOpts.votes) {
// addPermit(c);
// }
// if (allOpts.votes) {
// const clockMode = allOpts.votes === true ? clockModeDefault : allOpts.votes;
// addVotes(c, clockMode);
// }
// if (allOpts.flashmint) {
// addFlashMint(c);
// }
setAccessControl(c, access);
// setUpgradeable(c, upgradeable, access);
addBaseConstructors(c);
setInfo(c, contractInfo);
return c;
}
function addBase(c: ContractBuilder) {
//name
c.addModifier('virtual override', functions.name);
c.addFunctionCode(`return _name;`, functions.name);
//symbol
c.addModifier('virtual override', functions.symbol);
c.addFunctionCode(`return _symbol;`, functions.symbol);
//decimals
c.addModifier('override', functions.decimals);
c.addFunctionCode(`return _decimals;`, functions.decimals);
}
function addBaseConstructors(c: ContractBuilder) {
c.addVariable(`string private _name;`);
c.addVariable(`string private _symbol;`);
c.addVariable(`uint8 private immutable _decimals;`);
c.addConstructorCode(`_name = name_;
_symbol = symbol_;
_decimals = decimals_;`);
c.addConstructorArgument({
type: {
name: 'string memory',
transpiled: false,
},
name: 'name_',
});
c.addConstructorArgument({
type: {
name: 'string memory',
transpiled: false,
},
name: 'symbol_',
});
c.addConstructorArgument({
type: {
name: 'uint8',
transpiled: false,
},
name: 'decimals_',
});
}
function setERC7802Logic(c: ContractBuilder) {
const SuperchainERC20 = {
name: 'SuperchainERC20',
path: '@superfuse-core/L2/SuperchainERC20.sol',
};
c.addParent(
SuperchainERC20,
[],
);
}
// export const premintPattern = /^(\d*)(?:\.(\d+))?(?:e(\d+))?$/;
// function addAuthorizable(c: ContractBuilder, access: Access) {
// requireAccessControl(c, functions.mintTo, access, 'ADMIN','0', 'initialAdmin');
// c.addFunctionCode('_checkRole(ADMIN_ROLE);', functions._authorizeSetRole);
// }
function addMintable(c: ContractBuilder, access: Access) {
requireAccessControl(c, functions.mintTo, access, 'MINTER','1', 'minter_');
c.addFunctionCode('_mint(to_, amount_);', functions.mintTo);
}
// function addPermit(c: ContractBuilder) {
// // function addPermit(c: ContractBuilder, name: string) {
// const ERC20Permit = {
// name: 'ERC20Permit',
// path: '@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol',
// };
// c.addParent(ERC20Permit, [{ lit: '_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);
// }
const functions = defineFunctions({
name: {
kind: 'public' as const,
args: [
],
returns: ['string memory'],
mutability: 'view' as const,
},
symbol: {
kind: 'public' as const,
args: [
],
returns: ['string memory'],
mutability: 'view' as const,
},
decimals: {
kind: 'public' as const,
args: [
],
returns: ['uint8'],
mutability: 'view' as const,
},
// _authorizeSetRole: {
// kind: 'internal' as const,
// args: [
// { name: '', type: 'address' },
// { name: '', type: 'uint256' },
// { name: '', type: 'bool' },
// ],
// },
mintTo: {
kind: 'external' as const,
args: [
{ name: 'to_', type: 'address' },
{ name: 'amount_', type: 'uint256' },
],
},
nonces: {
kind: 'public' as const,
args: [
{ name: 'owner', type: 'address' },
],
returns: ['uint256'],
mutability: 'view' as const,
},
_update: {
kind: 'internal' as const,
args: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
],
},
});