@gnus.ai/upgrade-safe-transpiler-diamond
Version:
Solidity preprocessor used to generate OpenZeppelin Contracts Upgrade Safe using Diamond Pattern (EIP-2535).
79 lines (66 loc) • 2.94 kB
text/typescript
import {ContractDefinition, SourceUnit} from 'solidity-ast';
import { findAll } from 'solidity-ast/utils';
import { getNodeBounds } from '../solc/ast-utils';
import { Transformation, TransformHelper } from './type';
import { TransformerTools } from '../transform';
import { hasConstructorOverride, hasOverride } from "../utils/upgrades-overrides";
import { Node } from "solidity-ast/node";
import { relativePath } from "../utils/relative-path";
import path from "path";
import {
getNodeCount,
getScopedContractName,
getScopedContractsForVariables,
getUniqueIdentifierVarsUsed
} from './utils/get-identifiers-used';
import {getContractsImportPath, renameContract, renamePath} from "../rename";
export function* addDiamondAccess(sourceUnit: SourceUnit,
tools: TransformerTools,
): Generator<Transformation> {
const { resolver } = tools;
const contractScopes = new Map<number, string>();
const contractPaths = new Map<string, Set<string>>();
const suContractNameSet = new Set<string>();
const { dir, name, ext } = path.parse(sourceUnit.absolutePath);
const suContractPath = `${dir}/${name}Storage${ext}`;
for (const contractNode of findAll('ContractDefinition', sourceUnit)) {
if (getNodeCount('VariableDeclaration', contractNode, (node) => {
return node.stateVariable && !node.constant &&
!hasOverride(node, 'state-variable-assignment') &&
!hasOverride(node, 'state-variable-immutable');
} ) > 0) {
if (!contractPaths.has(suContractPath)) {
contractPaths.set(suContractPath, suContractNameSet);
}
suContractNameSet.add(contractNode.name + 'Storage');
}
for (const [_, identifierVar] of getUniqueIdentifierVarsUsed(contractNode, tools)) {
const { identifier, varDecl } = identifierVar;
const scopedContractName = getScopedContractName(varDecl.scope, contractPaths, contractScopes, tools);
const storageLayoutAccess = scopedContractName + `.layout().`;
const idBounds = getNodeBounds(identifier);
yield {
start: idBounds.start,
length: idBounds.length,
kind: 'set-storage-access-var-inits',
transform: source => storageLayoutAccess + source,
};
}
}
let last: Node | undefined;
for (const node of findAll('PragmaDirective', sourceUnit)) {
last = node;
}
for (const node of findAll('ImportDirective', sourceUnit)) {
last = node;
}
const after = last ? getNodeBounds(last) : {start: 0, length: 0};
const start = after.start + after.length;
const importsText = getContractsImportPath(contractPaths, dir, '');
yield {
start,
length: 0,
kind: 'append-storage-imports',
text: importsText,
};
}