Skip to content

Commit

Permalink
Dev (#3)
Browse files Browse the repository at this point in the history
* initial version

* Base version (#1)

* Base version

* Added BaseFactory

* Refactored code

* Set CoreProperties upgradeable

* fixes

* refactor logic

* updated

* removed scripts

* Updated package.json

* fixes

* added more tests

* added config

* changed swap params

* changed package-lock.json

* changed package-lock.json

* changed ci

* changed package-lock.json

---------

Co-authored-by: Oleksandr Fedorenko <[email protected]>

* added beacon & refactored (#4)

* added beacon & refactored

* fix event

* typo

* context

* upd enum

* tiny adjustments & cov 100%

* factories dir & isUpgradeable for all pools

* fixed lint

* factory ifaces folder

---------

Co-authored-by: Ruslan Kasheparov <[email protected]>
Co-authored-by: Ruslan Kasheparov <[email protected]>
Co-authored-by: Oleksandr Fedorenko <[email protected]>
  • Loading branch information
4 people authored May 20, 2024
1 parent 9ee3db6 commit 228f369
Show file tree
Hide file tree
Showing 109 changed files with 36,950 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[*]
charset = utf-8
end_of_line = lf
indent_style = space
insert_final_newline = true
[*.ts]
indent_size = 2
max_line_length = 120
[*.sol]
indent_size = 4
max_line_length = 99
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Deployer private key
PRIVATE_KEY=YOUR PRIVATE KEY

# RPC Endpoints
INFURA_KEY=INFURA PROJECT ID
ALCHEMY_KEY=ALCHEMY PROJECT ID

# Additional keys
ETHERSCAN_KEY=ETHERSCAN API KEY
BSCSCAN_KEY=BSCSCAN API KEY
POLYGONSCAN_KEY=POLYGONSCAN API KEY
COINMARKETCAP_KEY=COINMARKETCAP API KEY
22 changes: 22 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-floating-promises": "error"
},
"env": {
"browser": true,
"es2021": true
}
}
15 changes: 15 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: setup

description: setup

runs:
using: composite
steps:
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: "18.16.x"
cache: npm
- name: Install packages
run: npm install
shell: bash
23 changes: 23 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: "checks"

on:
push:
branches:
- master
pull_request:
branches:
- master
- dev

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v3
- name: Setup
uses: ./.github/actions/setup
- name: Run lint
run: npm run lint
- name: Run tests
run: npm run test
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
node_modules
.env
.DS_Store

# Hardhat files
cache
artifacts
coverage.json
coverage

# Typechain generated files
generated-types

# Migration files
.storage.json

# IDE files
.idea
.vscode
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npm run lint-fix && git add -u
13 changes: 13 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
node_modules
.env
.DS_Store
package-lock.json

# Hardhat files
cache
artifacts
coverage.json
coverage

# Typechain generated files
generated-types
27 changes: 27 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"overrides": [
{
"files": "*.sol",
"options": {
"plugins": ["prettier-plugin-solidity"],
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false
}
},
{
"files": "*.ts",
"options": {
"plugins": ["@trivago/prettier-plugin-sort-imports"],
"printWidth": 120,
"tabWidth": 2,
"singleQuote": true,
"importOrder": ["^[./]", "^@/(.*)$"],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true
}
}
]
}
4 changes: 4 additions & 0 deletions .solcover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
skipFiles: ['mock', 'interfaces', '@layerzerolabs'],
configureYulOptimizer: true,
};
15 changes: 15 additions & 0 deletions .solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "solhint:recommended",
"plugins": ["prettier"],
"rules": {
"reentrancy": "off",
"prettier/prettier": "error",
"modifier-name-mixedcase": "off",
"no-empty-blocks": "off",
"func-visibility": "off",
"max-states-count": "off",
"not-rely-on-time": "off",
"compiler-version": "off",
"no-inline-assembly": "off"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// SPDX-License-Identifier: LZBL-1.2

pragma solidity ^0.8.20;

import {BytesLib} from "solidity-bytes-utils/contracts/BytesLib.sol";

import {BitMap256} from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/BitMaps.sol";
import {CalldataBytesLib} from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol";

library DVNOptions {
using CalldataBytesLib for bytes;
using BytesLib for bytes;

uint8 internal constant WORKER_ID = 2;
uint8 internal constant OPTION_TYPE_PRECRIME = 1;

error DVN_InvalidDVNIdx();
error DVN_InvalidDVNOptions(uint256 cursor);

/// @dev group dvn options by its idx
/// @param _options [dvn_id][dvn_option][dvn_id][dvn_option]...
/// dvn_option = [option_size][dvn_idx][option_type][option]
/// option_size = len(dvn_idx) + len(option_type) + len(option)
/// dvn_id: uint8, dvn_idx: uint8, option_size: uint16, option_type: uint8, option: bytes
/// @return dvnOptions the grouped options, still share the same format of _options
/// @return dvnIndices the dvn indices
function groupDVNOptionsByIdx(
bytes memory _options
) internal pure returns (bytes[] memory dvnOptions, uint8[] memory dvnIndices) {
if (_options.length == 0) return (dvnOptions, dvnIndices);

uint8 numDVNs = getNumDVNs(_options);

// if there is only 1 dvn, we can just return the whole options
if (numDVNs == 1) {
dvnOptions = new bytes[](1);
dvnOptions[0] = _options;

dvnIndices = new uint8[](1);
dvnIndices[0] = _options.toUint8(3); // dvn idx
return (dvnOptions, dvnIndices);
}

// otherwise, we need to group the options by dvn_idx
dvnIndices = new uint8[](numDVNs);
dvnOptions = new bytes[](numDVNs);
unchecked {
uint256 cursor = 0;
uint256 start = 0;
uint8 lastDVNIdx = 255; // 255 is an invalid dvn_idx

while (cursor < _options.length) {
++cursor; // skip worker_id

// optionLength asserted in getNumDVNs (skip check)
uint16 optionLength = _options.toUint16(cursor);
cursor += 2;

// dvnIdx asserted in getNumDVNs (skip check)
uint8 dvnIdx = _options.toUint8(cursor);

// dvnIdx must equal to the lastDVNIdx for the first option
// so it is always skipped in the first option
// this operation slices out options whenever the scan finds a different lastDVNIdx
if (lastDVNIdx == 255) {
lastDVNIdx = dvnIdx;
} else if (dvnIdx != lastDVNIdx) {
uint256 len = cursor - start - 3; // 3 is for worker_id and option_length
bytes memory opt = _options.slice(start, len);
_insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, opt);

// reset the start and lastDVNIdx
start += len;
lastDVNIdx = dvnIdx;
}

cursor += optionLength;
}

// skip check the cursor here because the cursor is asserted in getNumDVNs
// if we have reached the end of the options, we need to process the last dvn
uint256 size = cursor - start;
bytes memory op = _options.slice(start, size);
_insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, op);

// revert dvnIndices to start from 0
for (uint8 i = 0; i < numDVNs; ++i) {
--dvnIndices[i];
}
}
}

function _insertDVNOptions(
bytes[] memory _dvnOptions,
uint8[] memory _dvnIndices,
uint8 _dvnIdx,
bytes memory _newOptions
) internal pure {
// dvnIdx starts from 0 but default value of dvnIndices is 0,
// so we tell if the slot is empty by adding 1 to dvnIdx
if (_dvnIdx == 255) revert DVN_InvalidDVNIdx();
uint8 dvnIdxAdj = _dvnIdx + 1;

for (uint256 j = 0; j < _dvnIndices.length; ++j) {
uint8 index = _dvnIndices[j];
if (dvnIdxAdj == index) {
_dvnOptions[j] = abi.encodePacked(_dvnOptions[j], _newOptions);
break;
} else if (index == 0) {
// empty slot, that means it is the first time we see this dvn
_dvnIndices[j] = dvnIdxAdj;
_dvnOptions[j] = _newOptions;
break;
}
}
}

/// @dev get the number of unique dvns
/// @param _options the format is the same as groupDVNOptionsByIdx
function getNumDVNs(bytes memory _options) internal pure returns (uint8 numDVNs) {
uint256 cursor = 0;
BitMap256 bitmap;

// find number of unique dvn_idx
unchecked {
while (cursor < _options.length) {
++cursor; // skip worker_id

uint16 optionLength = _options.toUint16(cursor);
cursor += 2;
if (optionLength < 2) revert DVN_InvalidDVNOptions(cursor); // at least 1 byte for dvn_idx and 1 byte for option_type

uint8 dvnIdx = _options.toUint8(cursor);

// if dvnIdx is not set, increment numDVNs
// max num of dvns is 255, 255 is an invalid dvn_idx
// The order of the dvnIdx is not required to be sequential, as enforcing the order may weaken
// the composability of the options. e.g. if we refrain from enforcing the order, an OApp that has
// already enforced certain options can append additional options to the end of the enforced
// ones without restrictions.
if (dvnIdx == 255) revert DVN_InvalidDVNIdx();
if (!bitmap.get(dvnIdx)) {
++numDVNs;
bitmap = bitmap.set(dvnIdx);
}

cursor += optionLength;
}
}
if (cursor != _options.length) revert DVN_InvalidDVNOptions(cursor);
}

/// @dev decode the next dvn option from _options starting from the specified cursor
/// @param _options the format is the same as groupDVNOptionsByIdx
/// @param _cursor the cursor to start decoding
/// @return optionType the type of the option
/// @return option the option
/// @return cursor the cursor to start decoding the next option
function nextDVNOption(
bytes calldata _options,
uint256 _cursor
) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) {
unchecked {
// skip worker id
cursor = _cursor + 1;

// read option size
uint16 size = _options.toU16(cursor);
cursor += 2;

// read option type
optionType = _options.toU8(cursor + 1); // skip dvn_idx

// startCursor and endCursor are used to slice the option from _options
uint256 startCursor = cursor + 2; // skip option type and dvn_idx
uint256 endCursor = cursor + size;
option = _options[startCursor:endCursor];
cursor += size;
}
}
}
39 changes: 39 additions & 0 deletions contracts/@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OApp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import {OAppSender, MessagingFee, MessagingReceipt} from "./OAppSender.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import {OAppReceiver, Origin} from "./OAppReceiver.sol";
import {OAppCore} from "./OAppCore.sol";

/**
* @title OApp
* @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
*/
abstract contract OApp is OAppSender, OAppReceiver {
/**
* @dev Constructor to initialize the OApp with the provided endpoint and owner.
* @param _endpoint The address of the LOCAL LayerZero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}

/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol implementation.
* @return receiverVersion The version of the OAppReceiver.sol implementation.
*/
function oAppVersion()
public
pure
virtual
override(OAppSender, OAppReceiver)
returns (uint64 senderVersion, uint64 receiverVersion)
{
return (SENDER_VERSION, RECEIVER_VERSION);
}
}
Loading

0 comments on commit 228f369

Please sign in to comment.