Skip to content

Commit

Permalink
Stop using magic numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
DimaStebaev committed Sep 18, 2023
1 parent 3fdc4d4 commit 144841c
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 127 deletions.
2 changes: 0 additions & 2 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ module.exports = {
"never"
],

"no-inline-comments": "warn",
"no-magic-numbers": "warn",
"no-mixed-operators": "warn",
"no-negated-condition": "warn",
"no-shadow": "warn",
Expand Down
14 changes: 10 additions & 4 deletions src/contractFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ const updateManifest = async (
libraries,
oldLibraries
);
const indentation = 4;
await fs.writeFile(
await getManifestFile(),
JSON.stringify(
manifest,
null,
4
indentation
)
);
};
Expand Down Expand Up @@ -99,9 +100,14 @@ export const getContractFactoryAndUpdateManifest = async (contract: string) => {
);
};

const getLibrariesNames =
(linkReferences: LinkReferences) => Object.values(linkReferences).
map((libraryObject) => Object.keys(libraryObject)[0]);

export const getLibrariesNames = (linkReferences: LinkReferences) => {
const libraryNames = [];
for (const libraryFile of Object.values(linkReferences)) {
libraryNames.push(...Object.keys(libraryFile));
}
return libraryNames;
};


const getLibrariesToUpgrade = async (
Expand Down
49 changes: 26 additions & 23 deletions src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import {Manifest, hashBytecode} from "@openzeppelin/upgrades-core";
import {artifacts, ethers} from "hardhat";
import {promises as fs} from "fs";
import {SkaleManifestData} from "./types/SkaleManifestData";
import {Artifact, LinkReferences} from "hardhat/types";
import {Artifact} from "hardhat/types";
import {hexDataSlice, hexConcat} from "ethers/lib/utils";
import {getLibrariesNames} from "./contractFactory";

interface LibraryArtifacts {
[key: string]: unknown
Expand Down Expand Up @@ -39,23 +41,32 @@ export const deployLibraries = async (libraryNames: string[]) => {
return libraries;
};

const _linkBytecode = (artifact: Artifact, libraries: Map<string, string>) => {
const firstByteIndex = 0;

const linkBytecode = (artifact: Artifact, libraries: Map<string, string>) => {
let {bytecode} = artifact;
for (const [, fileReferences] of Object.entries(artifact.linkReferences)) {
for (const [
libName,
fixups
] of Object.entries(fileReferences)) {
const addr = libraries.get(libName);
if (addr !== undefined) {
const libAddress = libraries.get(libName);
if (typeof libAddress !== "undefined") {
for (const fixup of fixups) {
bytecode =
bytecode.substr(
0,
2 + fixup.start * 2
) +
addr.substr(2) +
bytecode.substr(2 + (fixup.start + fixup.length) * 2);
const bytecodeBefore = hexDataSlice(
bytecode,
firstByteIndex,
fixup.start
);
const bytecodeAfter = hexDataSlice(
bytecode,
fixup.start + fixup.length
);
bytecode = hexConcat([
bytecodeBefore,
libAddress,
bytecodeAfter
]);
}
}
}
Expand All @@ -69,7 +80,7 @@ export const getLinkedContractFactory = async (
) => {
const
cArtifact = await artifacts.readArtifact(contractName);
const linkedBytecode = _linkBytecode(
const linkedBytecode = linkBytecode(
cArtifact,
libraries
);
Expand Down Expand Up @@ -100,12 +111,13 @@ const updateManifest = async (libraryArtifacts: LibraryArtifacts) => {
manifest.libraries
);
}
const indentation = 4;
await fs.writeFile(
await getManifestFile(),
JSON.stringify(
manifest,
null,
4
indentation
)
);
};
Expand Down Expand Up @@ -142,22 +154,13 @@ const getLibraryArtifacts = async (libraries: Map<string, string>) => {
return libraryArtifacts;
};

const getLibraryNames = (linkReferences: LinkReferences) => {
const libraryNames = [];
for (const key of Object.keys(linkReferences)) {
const libraryName = Object.keys(linkReferences[key])[0];
libraryNames.push(libraryName);
}
return libraryNames;
};

export const getContractFactory = async (contract: string) => {
const {linkReferences} = await artifacts.readArtifact(contract);
if (!Object.keys(linkReferences).length) {
return await ethers.getContractFactory(contract);
}

const libraryNames = getLibraryNames(linkReferences);
const libraryNames = getLibrariesNames(linkReferences);
const libraries = await deployLibraries(libraryNames);
const libraryArtifacts = await getLibraryArtifacts(libraries);

Expand Down
21 changes: 9 additions & 12 deletions src/gnosis-safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,21 @@ import SafeApiKit from "@safe-global/api-kit";
import Safe, {EthersAdapter} from "@safe-global/protocol-kit";
import {
MetaTransactionData,
OperationType,
SafeTransaction,
SafeTransactionDataPartial
} from "@safe-global/safe-core-sdk-types";
import {getNetwork} from "@ethersproject/networks";


enum Network {
MAINNET = 1,
GOERLI = 5,
GANACHE = 1337,
HARDHAT = 31337,
}

// Constants

const URLS = {
"safe_transaction": {
[Network.MAINNET]: "https://safe-transaction-mainnet.safe.global",
[Network.GOERLI]: "https://safe-transaction-goerli.safe.global"
[getNetwork("mainnet").chainId]:
"https://safe-transaction-mainnet.safe.global",
[getNetwork("goerli").chainId]:
"https://safe-transaction-goerli.safe.global"
}
};

Expand Down Expand Up @@ -129,10 +126,10 @@ const estimateSafeTransaction = async (
map((transaction) => safeService.estimateSafeTransaction(
safeAddress,
{
"to": transaction.to,
"value": transaction.value,
"data": transaction.data,
"operation": transaction.operation || 0
"operation": transaction.operation || OperationType.Call,
"to": transaction.to,
"value": transaction.value
}
)));
for (const estimateResponse of gasEstimations) {
Expand Down
98 changes: 41 additions & 57 deletions src/multiSend.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,62 @@
import {BigNumber} from "ethers";

const padWithZeros = (
value: string,
targetLength: number
) => ("0".repeat(targetLength) + value).slice(-targetLength);

const getOperationBytes = (operation: 0 | 1) => {
if (operation === 0) {
return "00";
} else if (operation === 1) {
return "01";
}
throw Error("Operation has an incorrect value");
};

const getToBytes = (to: string) => {
let _to = to;
if (to.startsWith("0x")) {
_to = _to.slice(2);
}
_to = padWithZeros(
_to,
20 * 2
);
return _to;
};
import {OperationType} from "@safe-global/safe-core-sdk-types";
import {BigNumberish, BytesLike} from "ethers";
import {
hexConcat,
hexDataLength,
hexValue,
hexZeroPad,
hexlify
} from "ethers/lib/utils";

interface Transaction {

/*
* Operation as a uint8 with 0 for a call
* or 1 for a delegatecall (=> 1 byte)
*/
operation: 0 | 1,
operation: OperationType,

// To as a address (=> 20 bytes)
to: string,

// Value as a uint256 (=> 32 bytes)
value: BigNumber | number,
value: BigNumberish,

// Data as bytes.
data: string
data: BytesLike
}

export const encodeTransaction = (transaction: Transaction) => {
const _operation = getOperationBytes(transaction.operation);
const OPERATION_BYTES = 1;
const ADDRESS_BYTES = 20;
const UINT256_BYTES = 32;
const TO_BYTES = ADDRESS_BYTES;
const VALUE_BYTES = UINT256_BYTES;
const DATA_LENGTH_BYTES = UINT256_BYTES;

const _to = getToBytes(transaction.to);

const _value = padWithZeros(
BigNumber.from(transaction.value).toHexString().
slice(2),
32 * 2
export const encodeTransaction = (transaction: Transaction) => {
const operation = hexZeroPad(
hexValue(transaction.operation),
OPERATION_BYTES
);

let _data = transaction.data;
if (transaction.data.startsWith("0x")) {
_data = _data.slice(2);
}
if (_data.length % 2 !== 0) {
_data = `0${_data}`;
}

const _dataLength = padWithZeros(
(_data.length / 2).toString(16),
32 * 2
const to = hexZeroPad(
hexValue(transaction.to),
TO_BYTES
);
const value = hexZeroPad(
hexValue(transaction.value),
VALUE_BYTES
);
const data = hexlify(transaction.data);
const dataLength = hexZeroPad(
hexValue(hexDataLength(data)),
DATA_LENGTH_BYTES
);

return `0x${[
_operation,
_to,
_value,
_dataLength,
_data
].join("")}`;
return hexConcat([
operation,
to,
value,
dataLength,
data
]);
};
43 changes: 24 additions & 19 deletions src/submitters/auto-submitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,27 @@ import {
} from "./safe-ima-legacy-marionette-submitter";
import {MARIONETTE_ADDRESS} from "./types/marionette";
import {skaleContracts} from "@skalenetwork/skale-contracts-ethers-v5";
import {EXIT_CODES} from "../exitCodes";

Check failure on line 14 in src/submitters/auto-submitter.ts

View workflow job for this annotation

GitHub Actions / test (16.x)

Cannot find module '../exitCodes' or its corresponding type declarations.

Check failure on line 14 in src/submitters/auto-submitter.ts

View workflow job for this annotation

GitHub Actions / build

Cannot find module '../exitCodes' or its corresponding type declarations.

Check failure on line 14 in src/submitters/auto-submitter.ts

View workflow job for this annotation

GitHub Actions / test (18.x)

Cannot find module '../exitCodes' or its corresponding type declarations.

Check failure on line 14 in src/submitters/auto-submitter.ts

View workflow job for this annotation

GitHub Actions / test (16.x)

Cannot find module '../exitCodes' or its corresponding type declarations.

Check failure on line 14 in src/submitters/auto-submitter.ts

View workflow job for this annotation

GitHub Actions / test (18.x)

Cannot find module '../exitCodes' or its corresponding type declarations.

export class AutoSubmitter extends Submitter {
name = "Auto Submitter";

static marionetteInterface = [
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
];

async submit (transactions: Transaction[]) {
console.log(`Submit via ${this.name}`);
const submitter = await AutoSubmitter.getSubmitter();
Expand Down Expand Up @@ -91,7 +108,7 @@ export class AutoSubmitter extends Submitter {
if (!process.env.IMA) {
console.log(chalk.red("Set target IMA alias" +
" to IMA environment variable"));
process.exit(1);
process.exit(EXIT_CODES.UNKNOWN_IMA);
}
const network =
await skaleContracts.getNetworkByProvider(ethers.provider);
Expand All @@ -103,7 +120,7 @@ export class AutoSubmitter extends Submitter {
if (!process.env.SAFE_ADDRESS) {
console.log(chalk.red("Set Gnosis Safe owner address" +
" to SAFE_ADDRESS environment variable"));
process.exit(1);
process.exit(EXIT_CODES.UNKNOWN_SAFE_ADDRESS);
}
return process.env.SAFE_ADDRESS;
}
Expand Down Expand Up @@ -142,35 +159,23 @@ export class AutoSubmitter extends Submitter {

private static async _versionFunctionExists () {
const bytecode = await hre.ethers.provider.getCode(MARIONETTE_ADDRESS);
const hexPrefixLength = 2;
const selectorLength = 10;

/*
* If the bytecode doesn't include the function selector version()
* is definitely not present
*/
if (!bytecode.includes(ethers.utils.id("version()").slice(
2,
10
hexPrefixLength,
selectorLength
))) {
return false;
}

const marionette = new ethers.Contract(
MARIONETTE_ADDRESS,
[
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
],
AutoSubmitter.marionetteInterface,
hre.ethers.provider
);

Expand Down
Loading

0 comments on commit 144841c

Please sign in to comment.