Skip to content

Commit

Permalink
🔧 Add latest fixes/updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ezynda3 committed Apr 13, 2022
1 parent 69ed7fc commit 3329405
Show file tree
Hide file tree
Showing 38 changed files with 863 additions and 357 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/forge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Forge
on:
push:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- uses: actions/setup-node@v2
- name: Install dev dependencies
run: npm install

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1
with:
version: nightly

- name: Run forge tests
run: forge test -f ${{ secrets.ETH_NODE_URI_MAINNET }} --fork-block-number 14518542
44 changes: 44 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
submodules: recursive

- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: '14'

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"

- uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Installing dependencies
run: yarn install --frozen-lockfile

- name: Linting
run: yarn lint

- name: Formatting
run: yarn format

- name: Running tests
run: yarn test
env:
MNEMONIC: ${{ secrets.MNEMONIC }}
ETH_NODE_URI: ${{ secrets.ETH_NODE_URI }}
ETH_NODE_URI_POLYGON: ${{ secrets.ETH_NODE_URI_POLYGON }}
ETH_NODE_URI_ARBITRUM: ${{ secrets.ETH_NODE_URI_ARBITRUM }}
11 changes: 11 additions & 0 deletions .github/workflows/slither.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: Slither Analysis
on: [push]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: crytic/[email protected]
with:
node-version: 16
continue-on-error: true
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# include .env file and export its env vars
# (-include to ignore error if it does not exist)
-include .env

.PHONY: all test

# deps
update:; forge update

# Build & test
build :; forge build
test :; forge test --fork-url ${ETH_NODE_URI_MAINNET} --fork-block-number ${FORK_NUMBER} -vv
trace :; forge test --fork-url ${ETH_NODE_URI_MAINNET} --fork-block-number ${FORK_NUMBER} -vvv
watch :; forge test --watch src test --fork-url ${ETH_NODE_URI_MAINNET} --fork-block-number ${FORK_NUMBER} -vvvv
clean :; forge clean
snapshot :; forge snapshot
6 changes: 6 additions & 0 deletions config/dexfuncs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import funcSignatures from '../utils/approvedFunctions'

type DEXAllowedFunctionSignatures = string[]

const config: DEXAllowedFunctionSignatures = [...funcSignatures]
export default config
10 changes: 9 additions & 1 deletion deploy/018_deploy_dex_manager_facet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DeployFunction } from 'hardhat-deploy/types'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
import { addOrReplaceFacets } from '../utils/diamond'
import config from '../config/dexs'
import allowedFuncSignatures from '../config/dexfuncs'
import { DexManagerFacet } from '../typechain'

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
Expand All @@ -23,7 +24,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {

await addOrReplaceFacets([dexManagerFacet], diamond.address)

const dexs = config[network.name].map((d) => d.toLowerCase())
const dexs = config[network.name].map((d: string) => d.toLowerCase())
if (dexs && dexs.length) {
console.log('Adding DEXs to whitelist...')
const dexMgr = <DexManagerFacet>(
Expand All @@ -38,6 +39,13 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
} else {
await dexMgr.batchAddDex(dexs)
}

// Approve function signatures
await dexMgr.batchSetFunctionApprovalBySignature(
allowedFuncSignatures,
true
)

console.log('Done!')
}
}
Expand Down
2 changes: 1 addition & 1 deletion diamondABI/diamond.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
"void:deploy": "hardhat deploy",
"test": "npm run compile && cross-env TS_NODE_TRANSPILE_ONLY=1 mocha --bail --recursive test",
"test:fix": "npm run lint:fix; npm run format:fix; npm run test",
"test:forge": "forge test",
"test:forge": "make test",
"test:forge:fix": "npm run lint:fix; npm run format:fix; forge test",
"gas": "cross-env REPORT_GAS=true hardhat test",
"coverage": "cross-env HARDHAT_DEPLOY_FIXTURE=true hardhat coverage",
"dev": "hardhat node --watch --export contractsInfo.json",
Expand Down
2 changes: 2 additions & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ ds-test/=lib/ds-test/src/
solmate/=lib/solmate/src/
forge-std/=lib/forge-std/src/
@openzeppelin/=node_modules/@openzeppelin/
uniswap/=lib/v2-periphery/contracts/
hardhat/=node_modules/hardhat
16 changes: 16 additions & 0 deletions src/Errors/GenericErrors.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

error InvalidAmount();
error TokenAddressIsZero();
error CannotBridgeToSameNetwork();
error ZeroPostSwapBalance();
error InvalidBridgeConfigLength();
error NoSwapDataProvided();
error NativeValueWithERC();
error ContractCallNotAllowed();
error NullAddrIsNotAValidSpender();
error NullAddrIsNotAnERC20Token();
error NoTransferToNullAddress();
error NativeAssetTransferFailed();
error InvalidContract();
116 changes: 56 additions & 60 deletions src/Facets/AnyswapFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ import { IAnyswapRouter } from "../Interfaces/IAnyswapRouter.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
import { LibAsset, IERC20 } from "../Libraries/LibAsset.sol";
import { IAnyswapToken } from "../Interfaces/IAnyswapToken.sol";
import { LibDiamond } from "../Libraries/LibDiamond.sol";
import "./Swapper.sol";
import { ReentrancyGuard } from "../Helpers/ReentrancyGuard.sol";
import { TokenAddressIsZero, InvalidAmount, CannotBridgeToSameNetwork, NativeValueWithERC } from "../Errors/GenericErrors.sol";
import { Swapper, LibSwap } from "../Helpers/Swapper.sol";

/**
* @title Anyswap Facet
* @author LI.FI (https://li.fi)
* @notice Provides functionality for bridging through Multichain (Prev. AnySwap)
*/
contract AnyswapFacet is ILiFi, Swapper {
contract AnyswapFacet is ILiFi, Swapper, ReentrancyGuard {
/* ========== Types ========== */

struct AnyswapData {
Expand All @@ -32,39 +33,25 @@ contract AnyswapFacet is ILiFi, Swapper {
* @param _lifiData data used purely for tracking and analytics
* @param _anyswapData data specific to Anyswap
*/
function startBridgeTokensViaAnyswap(LiFiData memory _lifiData, AnyswapData calldata _anyswapData)
function startBridgeTokensViaAnyswap(LiFiData calldata _lifiData, AnyswapData calldata _anyswapData)
external
payable
nonReentrant
{
require(_anyswapData.token != address(0), "AnySwap token address cannot be 0");
address underlyingToken = IAnyswapToken(_anyswapData.token).underlying();
if (underlyingToken != IAnyswapRouter(_anyswapData.router).wNATIVE()) {
if (underlyingToken == address(0)) {
underlyingToken = _anyswapData.token;
}

uint256 _fromTokenBalance = LibAsset.getOwnBalance(underlyingToken);
LibAsset.transferFromERC20(underlyingToken, msg.sender, address(this), _anyswapData.amount);

require(
LibAsset.getOwnBalance(underlyingToken) - _fromTokenBalance == _anyswapData.amount,
"ERR_INVALID_AMOUNT"
);
} else {
require(msg.value == _anyswapData.amount, "ERR_INVALID_AMOUNT");
}

_startBridge(_anyswapData);
// Multichain (formerly Anyswap) tokens can wrap other tokens
(address underlyingToken, bool isNative) = _getUnderlyingToken(_anyswapData.token, _anyswapData.router);
if (!isNative) LibAsset.depositAsset(underlyingToken, _anyswapData.amount);
_startBridge(_anyswapData, underlyingToken, isNative);

emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
underlyingToken,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
_anyswapData.recipient,
_anyswapData.amount,
_anyswapData.toChainId,
block.timestamp
);
}
Expand All @@ -79,67 +66,76 @@ contract AnyswapFacet is ILiFi, Swapper {
LiFiData calldata _lifiData,
LibSwap.SwapData[] calldata _swapData,
AnyswapData memory _anyswapData
) external payable {
require(_anyswapData.token != address(0), "AnySwap token address cannot be 0");
address underlyingToken = IAnyswapToken(_anyswapData.token).underlying();

if (underlyingToken == address(0)) {
underlyingToken = _anyswapData.token;
}
) external payable nonReentrant {
if (_anyswapData.token == address(0)) revert TokenAddressIsZero();
_anyswapData.amount = _executeAndCheckSwaps(_lifiData, _swapData);

_startBridge(_anyswapData);
(address underlyingToken, bool isNative) = _getUnderlyingToken(_anyswapData.token, _anyswapData.router);
_startBridge(_anyswapData, underlyingToken, isNative);

emit LiFiTransferStarted(
_lifiData.transactionId,
_lifiData.integrator,
_lifiData.referrer,
_lifiData.sendingAssetId,
_swapData[0].sendingAssetId,
_lifiData.receivingAssetId,
_lifiData.receiver,
_lifiData.amount,
_lifiData.destinationChainId,
_anyswapData.recipient,
_swapData[0].fromAmount,
_anyswapData.toChainId,
block.timestamp
);
}

/* ========== Internal Functions ========== */
/* ========== Private Functions ========== */

/**
* @notice Unwraps the underlying token from the Anyswap token if necessary
* @param token The (maybe) wrapped token
* @param router The Anyswap router
*/
function _getUnderlyingToken(address token, address router)
private
returns (address underlyingToken, bool isNative)
{
// Token must implement IAnyswapToken interface
if (token == address(0)) revert TokenAddressIsZero();
underlyingToken = IAnyswapToken(token).underlying();
// The native token does not use the standard null address ID
isNative = IAnyswapRouter(router).wNATIVE() == underlyingToken;
// Some Multichain complying tokens may wrap nothing
if (!isNative && underlyingToken == address(0)) {
underlyingToken = token;
}
}

/**
* @dev Conatains the business logic for the bridge via Anyswap
* @param _anyswapData data specific to Anyswap
*/
function _startBridge(AnyswapData memory _anyswapData) internal {
require(_anyswapData.token != address(0), "AnySwap token address cannot be 0");
// Check chain id
require(block.chainid != _anyswapData.toChainId, "Cannot bridge to same network.");
address underlyingToken = IAnyswapToken(_anyswapData.token).underlying();

if (underlyingToken == IAnyswapRouter(_anyswapData.router).wNATIVE()) {
function _startBridge(
AnyswapData memory _anyswapData,
address underlyingToken,
bool isNative
) private {
if (block.chainid == _anyswapData.toChainId) revert CannotBridgeToSameNetwork();

if (isNative) {
IAnyswapRouter(_anyswapData.router).anySwapOutNative{ value: _anyswapData.amount }(
_anyswapData.token,
_anyswapData.recipient,
_anyswapData.toChainId
);
return;
}

if (_anyswapData.token != address(0)) {
// Has underlying token?
if (underlyingToken != address(0)) {
// Give Anyswap approval to bridge tokens
LibAsset.maxApproveERC20(IERC20(underlyingToken), _anyswapData.router, _anyswapData.amount);

} else {
// Give Anyswap approval to bridge tokens
LibAsset.maxApproveERC20(IERC20(underlyingToken), _anyswapData.router, _anyswapData.amount);
// Was the token wrapping another token?
if (_anyswapData.token != underlyingToken) {
IAnyswapRouter(_anyswapData.router).anySwapOutUnderlying(
_anyswapData.token,
_anyswapData.recipient,
_anyswapData.amount,
_anyswapData.toChainId
);
} else {
// Give Anyswap approval to bridge tokens
LibAsset.maxApproveERC20(IERC20(_anyswapData.token), _anyswapData.router, _anyswapData.amount);

IAnyswapRouter(_anyswapData.router).anySwapOut(
_anyswapData.token,
_anyswapData.recipient,
Expand Down
Loading

0 comments on commit 3329405

Please sign in to comment.