UNPKG

superfuse-wizard

Version:

Interactive smart contract generator based on Superchain 's interoperability standard.

208 lines (154 loc) 7.12 kB
import type { DeployContract, BaseFunction} from './contract'; import { DeployBuilder } from "./contract"; import type { Access } from './set-access-control'; import { setAccessControl, requireAccessControl } from './set-access-control'; import type { SharedL2NativeSuperchainERC20Options, OpSec} from '../shared/option-l2-native-superchain-ERC20'; import { withCommonDefaults, defaults as commonDefaults } from '../shared/option-l2-native-superchain-ERC20'; import { OptionsError } from "../shared/error"; import { printDeployContract } from "./print"; import { setInfo } from "./set-info"; function withDeloyDefaults(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 printDeployL2NativeSuperchainERC20(opts: SharedL2NativeSuperchainERC20Options = commonDefaults): string { return printDeployContract(buildDeployL2NativeSuperchainERC20(opts)); } export function buildDeployL2NativeSuperchainERC20(opts: SharedL2NativeSuperchainERC20Options): DeployContract { const allOpts = withDeloyDefaults(opts); const c = new DeployBuilder(allOpts.deployName); validateAddress(allOpts.deployerAddress); setOpsec(c, allOpts.opSec); addBase(c, allOpts); const fn : BaseFunction = getDeployFunction(allOpts); addDeployOptions(c, fn); let argCode : string | undefined = undefined; if (allOpts.mintable) { argCode = addMintable(c, allOpts.access, allOpts); } // addVotes(c, fn); setAccessControl(c, fn, allOpts.access, allOpts.contractName, argCode, allOpts.ownerAddress); // setUpgradeable(c, allOpts.upgradeable, allOpts.access); setInfo(c, allOpts.deployInfo); return c; } function validateAddress(address: string) { if (!/^0x[a-fA-F0-9]{40}$/.test(address)) { throw new OptionsError({ address: 'Not a valid address', }); } } function setOpsec(c: DeployBuilder, opsec: OpSec) { switch (opsec) { case 'address': { c.addVariable(`address owner = vm.envAddress("DEPLOYER_ADDRESS");`); break; } case 'key': { c.addVariable(`uint256 ownerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");`); c.addVariable(`address owner = vm.envOr("DEPLOYER_ADDRESS", vm.addr(ownerPrivateKey));`); break; } case 'mnemonic': { c.addVariable(`string mnemonic = vm.envString("MNEMONIC");`); c.addVariable(`uint256 ownerPrivateKey = vm.deriveKey(mnemonic, "m/44'/60'/0'/0/", 1);`); c.addVariable(`address owner = vm.envOr("DEPLOYER_ADDRESS", vm.addr(ownerPrivateKey));`); break; } } } function addBase(c: DeployBuilder, allOpts: Required<SharedL2NativeSuperchainERC20Options>) { const Vm = { name: 'Vm', path: '@forge-std-v1.9.1/Vm.sol', }; c.addImportOnly(Vm); const DeployScript = { name: 'DeployScript', path: '@superfuse-deploy/deployer/DeployScript.sol', }; c.addParent(DeployScript, []); const DefaultDeployerFunction = { name: 'DefaultDeployerFunction', path: '@superfuse-deploy/deployer/DefaultDeployerFunction.sol', }; c.addImportOnly(DefaultDeployerFunction); const DeployOptions = { name: 'DeployOptions', path: '@superfuse-deploy/deployer/DefaultDeployerFunction.sol', }; c.addImportOnly(DeployOptions); const L2NativeSuperchainERC20 = { name: `${allOpts.contractName}`, path: `@main/${allOpts.contractName}.sol`, }; c.addImportOnly(L2NativeSuperchainERC20); c.addOutsidecode(`string constant Artifact_${allOpts.contractName} = "${allOpts.contractName}.sol:${allOpts.contractName}";`) c.addVariable(`${allOpts.contractName} token;`); c.addVariable(`string name = "${allOpts.tokenName}";`); c.addVariable(`string symbol = "${allOpts.tokenSymbol}";`); c.addVariable(`uint8 decimals = ${allOpts.decimals};`); } function addDeployOptions(c: DeployBuilder, fn: BaseFunction) { c.addFunctionCode(`bytes32 _salt = DeployScript.implSalt(); DeployOptions memory options = DeployOptions({salt:_salt});`, fn); } // function addVotes(c: DeployBuilder, fn : BaseFunction) { // c.addVariable('address token;'); // c.addFunctionCode(`IVotes _token = IVotes(token);`, fn); // } function addMintable(c: DeployBuilder, access: Access, allOpts : Required<SharedL2NativeSuperchainERC20Options>) : string { return requireAccessControl(c, access, allOpts.ownerAddress, 'minter', allOpts.minterAddress); } // function addDeployLogic(c: DeployBuilder, fn: BaseFunction, allOpts : Required<SharedL2NativeSuperchainERC20Options>) { // if (allOpts.upgradeable) { // const Upgrades = { // name: 'Upgrades', // path: '@openzeppelin-foundry-upgrades/Upgrades.sol', // }; // c.addImportOnly(Upgrades); // } // // to do fix hardcoded upgradable // if (allOpts.upgradeable == 'transparent' ) { // c.addFunctionCode(`vm.startBroadcast(); // address tokenAddress = Upgrades.deployTransparentProxy("${allOpts.contractFile}", abi.encodeCall(${allOpts.contractName}.initialize, ( name, symbol))); // vm.stopBroadcast(); // // DONT forget to save the address of the token // deployerProcedue.save("${allOpts.contractName}", tokenAddress); // return ${allOpts.contractName}(tokenAddress);`, fn); // } else if (allOpts.upgradeable == 'uups') { // c.addFunctionCode(`vm.startBroadcast(); // address tokenAddress = Upgrades.deployUUPSProxy("${allOpts.contractFile}", abi.encodeCall(${allOpts.contractName}.initialize, ( name, symbol))); // vm.stopBroadcast(); // // DONT forget to save the address of the token // deployerProcedue.save("${allOpts.contractName}", tokenAddress); // return ${allOpts.contractName}(tokenAddress);`, fn); // } else { // // c.addFunctionCode(`bytes32 _salt = DeployScript.implSalt(); // // DeployOptions memory options = DeployOptions({salt:_salt}); // // bytes memory args = abi.encode(name, symbol); // // return ${allOpts.contractName}(DefaultDeployerFunction.deploy(deployer, "${allOpts.contractName}", Artifact_${allOpts.contractName}, args, options));`, fn); // setAccessControl(c, fn, allOpts.access, allOpts.mintable, allOpts.contractName, allOpts.ownerAddress, allOpts.minterAddress); // } // } function getDeployFunction(allOpts: Required<SharedL2NativeSuperchainERC20Options>) { const fn = { name: 'deploy', args: [], returns: [`${allOpts.contractName}` ], kind: 'external' as const, }; return fn; }