@0x/contracts-asset-proxy
: Add Eth2DaiBridge
and tests.
This commit is contained in:
@@ -21,6 +21,10 @@
|
||||
{
|
||||
"note": "Add `ERC20BridgeProxy`",
|
||||
"pr": 2220
|
||||
},
|
||||
{
|
||||
"note": "Add `Eth2DaiBridge`",
|
||||
"pr": "TODO"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
102
contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol
Normal file
102
contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "./ERC20Bridge.sol";
|
||||
import "../interfaces/IEth2Dai.sol";
|
||||
|
||||
|
||||
contract Eth2DaiBridge is
|
||||
ERC20Bridge
|
||||
{
|
||||
/* Mainnet addresses */
|
||||
address constant public ETH2DAI_ADDRESS = 0x39755357759cE0d7f32dC8dC45414CCa409AE24e;
|
||||
address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
||||
address constant public DAI_ADDRESS = 0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359;
|
||||
|
||||
constructor() public {
|
||||
// Grant the Eth2Dai contract unlimited weth and dai allowances.
|
||||
_getWethContract().approve(address(_getEth2DaiContract()), uint256(-1));
|
||||
_getDaiContract().approve(address(_getEth2DaiContract()), uint256(-1));
|
||||
}
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
function transfer(
|
||||
bytes calldata /* bridgeData */,
|
||||
address toTokenAddress,
|
||||
address /* from */,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// The "from" token is the opposite of the "to" token.
|
||||
IERC20Token fromToken = _getWethContract();
|
||||
IERC20Token toToken = _getDaiContract();
|
||||
// Swap them if necessary.
|
||||
if (toTokenAddress == address(fromToken)) {
|
||||
(fromToken, toToken) = (toToken, fromToken);
|
||||
} else {
|
||||
require(
|
||||
toTokenAddress == address(toToken),
|
||||
"INVALID_ETH2DAI_TOKEN"
|
||||
);
|
||||
}
|
||||
// Try to sell all of this contract's `fromToken` balance.
|
||||
uint256 boughtAmount = _getEth2DaiContract().sellAllAmount(
|
||||
address(fromToken),
|
||||
fromToken.balanceOf(address(this)),
|
||||
address(toToken),
|
||||
amount
|
||||
);
|
||||
// Transfer the converted `toToken`s to `to`.
|
||||
toToken.transfer(to, boughtAmount);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev Overridable way to get the weth contract.
|
||||
function _getWethContract()
|
||||
internal
|
||||
view
|
||||
returns (IERC20Token)
|
||||
{
|
||||
return IERC20Token(WETH_ADDRESS);
|
||||
}
|
||||
|
||||
/// @dev Overridable way to get the dai contract.
|
||||
function _getDaiContract()
|
||||
internal
|
||||
view
|
||||
returns (IERC20Token)
|
||||
{
|
||||
return IERC20Token(DAI_ADDRESS);
|
||||
}
|
||||
|
||||
/// @dev Overridable way to get the eth2dai contract.
|
||||
function _getEth2DaiContract()
|
||||
internal
|
||||
view
|
||||
returns (IEth2Dai)
|
||||
{
|
||||
return IEth2Dai(ETH2DAI_ADDRESS);
|
||||
}
|
||||
}
|
32
contracts/asset-proxy/contracts/src/interfaces/IEth2Dai.sol
Normal file
32
contracts/asset-proxy/contracts/src/interfaces/IEth2Dai.sol
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
// solhint-disable func-param-name-mixedcase
|
||||
interface IEth2Dai {
|
||||
function sellAllAmount(
|
||||
address pay_gem,
|
||||
uint256 pay_amt,
|
||||
address buy_gem,
|
||||
uint256 min_fill_amount
|
||||
)
|
||||
external
|
||||
returns (uint256 fill_amt);
|
||||
}
|
197
contracts/asset-proxy/contracts/test/TestEth2DaiBridge.sol
Normal file
197
contracts/asset-proxy/contracts/test/TestEth2DaiBridge.sol
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "../src/bridges/Eth2DaiBridge.sol";
|
||||
import "../src/interfaces/IEth2Dai.sol";
|
||||
|
||||
|
||||
// solhint-disable no-simple-event-func-name
|
||||
/// @dev Interface that allows `TestToken` to call `raiseTransferEvent` on
|
||||
/// the `TestEth2DaiBridge` contract.
|
||||
interface IRaiseTransferEvent {
|
||||
function raiseTransferEvent(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external;
|
||||
}
|
||||
|
||||
|
||||
/// @dev A minimalist ERC20 token.
|
||||
contract TestToken {
|
||||
|
||||
mapping (address => uint256) public balances;
|
||||
mapping (address => mapping (address => uint256)) public allowances;
|
||||
|
||||
/// @dev Just calls `raiseTransferEvent()` on the caller.
|
||||
function transfer(address to, uint256 amount)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
IRaiseTransferEvent(msg.sender).raiseTransferEvent(msg.sender, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @dev Set the balance for `owner`.
|
||||
function setBalance(address owner, uint256 balance)
|
||||
external
|
||||
{
|
||||
balances[owner] = balance;
|
||||
}
|
||||
|
||||
/// @dev Records allowance values.
|
||||
function approve(address spender, uint256 allowance)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
allowances[msg.sender][spender] = allowance;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @dev Retrieve the balance for `owner`.
|
||||
function balanceOf(address owner)
|
||||
external
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return balances[owner];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @dev Eth2DaiBridge overridden to mock tokens and
|
||||
/// implement IEth2Dai.
|
||||
contract TestEth2DaiBridge is
|
||||
IEth2Dai,
|
||||
Eth2DaiBridge
|
||||
{
|
||||
event SellAllAmount(
|
||||
address sellToken,
|
||||
uint256 sellTokenAmount,
|
||||
address buyToken,
|
||||
uint256 minimumFillAmount
|
||||
);
|
||||
|
||||
event TokenTransfer(
|
||||
address token,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
TestToken public wethToken = new TestToken();
|
||||
TestToken public daiToken = new TestToken();
|
||||
string private _nextRevertReason;
|
||||
uint256 private _nextFillAmount;
|
||||
|
||||
/// @dev Set token balances for this contract.
|
||||
function setTokenBalances(uint256 wethBalance, uint256 daiBalance)
|
||||
external
|
||||
{
|
||||
wethToken.setBalance(address(this), wethBalance);
|
||||
daiToken.setBalance(address(this), daiBalance);
|
||||
}
|
||||
|
||||
/// @dev Set the behavior for `IEth2Dai.sellAllAmount()`.
|
||||
function setFillBehavior(string calldata revertReason, uint256 fillAmount)
|
||||
external
|
||||
{
|
||||
_nextRevertReason = revertReason;
|
||||
_nextFillAmount = fillAmount;
|
||||
}
|
||||
|
||||
/// @dev Implementation of `IEth2Dai.sellAllAmount()`
|
||||
function sellAllAmount(
|
||||
address sellTokenAddress,
|
||||
uint256 sellTokenAmount,
|
||||
address buyTokenAddress,
|
||||
uint256 minimumFillAmount
|
||||
)
|
||||
external
|
||||
returns (uint256 fillAmount)
|
||||
{
|
||||
emit SellAllAmount(
|
||||
sellTokenAddress,
|
||||
sellTokenAmount,
|
||||
buyTokenAddress,
|
||||
minimumFillAmount
|
||||
);
|
||||
if (bytes(_nextRevertReason).length != 0) {
|
||||
revert(_nextRevertReason);
|
||||
}
|
||||
return _nextFillAmount;
|
||||
}
|
||||
|
||||
function raiseTransferEvent(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
{
|
||||
emit TokenTransfer(
|
||||
msg.sender,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Retrieves the allowances of the test tokens.
|
||||
function getEth2DaiTokenAllowances()
|
||||
external
|
||||
view
|
||||
returns (uint256 wethAllowance, uint256 daiAllowance)
|
||||
{
|
||||
wethAllowance = wethToken.allowances(address(this), address(this));
|
||||
daiAllowance = daiToken.allowances(address(this), address(this));
|
||||
return (wethAllowance, daiAllowance);
|
||||
}
|
||||
|
||||
// @dev Use `wethToken`.
|
||||
function _getWethContract()
|
||||
internal
|
||||
view
|
||||
returns (IERC20Token)
|
||||
{
|
||||
return IERC20Token(address(wethToken));
|
||||
}
|
||||
|
||||
// @dev Use `daiToken`.
|
||||
function _getDaiContract()
|
||||
internal
|
||||
view
|
||||
returns (IERC20Token)
|
||||
{
|
||||
return IERC20Token(address(daiToken));
|
||||
}
|
||||
|
||||
// @dev This contract will double as the Eth2Dai contract.
|
||||
function _getEth2DaiContract()
|
||||
internal
|
||||
view
|
||||
returns (IEth2Dai)
|
||||
{
|
||||
return IEth2Dai(address(this));
|
||||
}
|
||||
}
|
@@ -9,17 +9,20 @@ import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
|
||||
import * as ERC20BridgeProxy from '../generated-artifacts/ERC20BridgeProxy.json';
|
||||
import * as ERC20Proxy from '../generated-artifacts/ERC20Proxy.json';
|
||||
import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
|
||||
import * as Eth2DaiBridge from '../generated-artifacts/Eth2DaiBridge.json';
|
||||
import * as IAssetData from '../generated-artifacts/IAssetData.json';
|
||||
import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json';
|
||||
import * as IAssetProxyDispatcher from '../generated-artifacts/IAssetProxyDispatcher.json';
|
||||
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
|
||||
import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json';
|
||||
import * as IEth2Dai from '../generated-artifacts/IEth2Dai.json';
|
||||
import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json';
|
||||
import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
|
||||
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
|
||||
import * as Ownable from '../generated-artifacts/Ownable.json';
|
||||
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
|
||||
import * as TestERC20Bridge from '../generated-artifacts/TestERC20Bridge.json';
|
||||
import * as TestEth2DaiBridge from '../generated-artifacts/TestEth2DaiBridge.json';
|
||||
import * as TestStaticCallTarget from '../generated-artifacts/TestStaticCallTarget.json';
|
||||
export const artifacts = {
|
||||
MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact,
|
||||
@@ -36,6 +39,8 @@ export const artifacts = {
|
||||
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
|
||||
IAuthorizable: IAuthorizable as ContractArtifact,
|
||||
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
||||
IEth2Dai: IEth2Dai as ContractArtifact,
|
||||
TestERC20Bridge: TestERC20Bridge as ContractArtifact,
|
||||
TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
|
||||
TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
|
||||
};
|
||||
|
@@ -7,15 +7,18 @@ export * from '../generated-wrappers/erc1155_proxy';
|
||||
export * from '../generated-wrappers/erc20_bridge_proxy';
|
||||
export * from '../generated-wrappers/erc20_proxy';
|
||||
export * from '../generated-wrappers/erc721_proxy';
|
||||
export * from '../generated-wrappers/eth2_dai_bridge';
|
||||
export * from '../generated-wrappers/i_asset_data';
|
||||
export * from '../generated-wrappers/i_asset_proxy';
|
||||
export * from '../generated-wrappers/i_asset_proxy_dispatcher';
|
||||
export * from '../generated-wrappers/i_authorizable';
|
||||
export * from '../generated-wrappers/i_erc20_bridge';
|
||||
export * from '../generated-wrappers/i_eth2_dai';
|
||||
export * from '../generated-wrappers/mixin_asset_proxy_dispatcher';
|
||||
export * from '../generated-wrappers/mixin_authorizable';
|
||||
export * from '../generated-wrappers/multi_asset_proxy';
|
||||
export * from '../generated-wrappers/ownable';
|
||||
export * from '../generated-wrappers/static_call_proxy';
|
||||
export * from '../generated-wrappers/test_erc20_bridge';
|
||||
export * from '../generated-wrappers/test_eth2_dai_bridge';
|
||||
export * from '../generated-wrappers/test_static_call_target';
|
||||
|
147
contracts/asset-proxy/test/eth2dai_bridge.ts
Normal file
147
contracts/asset-proxy/test/eth2dai_bridge.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import {
|
||||
blockchainTests,
|
||||
constants,
|
||||
expect,
|
||||
filterLogsToArguments,
|
||||
getRandomInteger,
|
||||
Numberish,
|
||||
randomAddress,
|
||||
TransactionHelper,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { DecodedLogs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
artifacts,
|
||||
TestEth2DaiBridgeContract,
|
||||
TestEth2DaiBridgeEvents,
|
||||
TestEth2DaiBridgeSellAllAmountEventArgs,
|
||||
TestEth2DaiBridgeTokenTransferEventArgs,
|
||||
} from '../src';
|
||||
|
||||
blockchainTests.resets('Eth2DaiBridge unit tests', env => {
|
||||
const txHelper = new TransactionHelper(env.web3Wrapper, artifacts);
|
||||
let testContract: TestEth2DaiBridgeContract;
|
||||
let daiTokenAddress: string;
|
||||
let wethTokenAddress: string;
|
||||
|
||||
before(async () => {
|
||||
testContract = await TestEth2DaiBridgeContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestEth2DaiBridge,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
[daiTokenAddress, wethTokenAddress] = await Promise.all([
|
||||
testContract.daiToken.callAsync(),
|
||||
testContract.wethToken.callAsync(),
|
||||
]);
|
||||
});
|
||||
|
||||
describe('deployment', () => {
|
||||
it('sets Eth2Dai allowances to maximum', async () => {
|
||||
const [wethAllowance, daiAllowance] = await testContract.getEth2DaiTokenAllowances.callAsync();
|
||||
expect(wethAllowance).to.bignumber.eq(constants.MAX_UINT256);
|
||||
expect(daiAllowance).to.bignumber.eq(constants.MAX_UINT256);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transfer()', () => {
|
||||
interface TransferOpts {
|
||||
toTokenAddress: string;
|
||||
toAddress: string;
|
||||
amount: Numberish;
|
||||
fromTokenBalance: Numberish;
|
||||
revertReason: string;
|
||||
fillAmount: Numberish;
|
||||
}
|
||||
|
||||
function createTransferOpts(opts?: Partial<TransferOpts>): TransferOpts {
|
||||
return {
|
||||
toTokenAddress: _.sampleSize([wethTokenAddress, daiTokenAddress], 1)[0],
|
||||
toAddress: randomAddress(),
|
||||
amount: getRandomInteger(1, 100e18),
|
||||
revertReason: '',
|
||||
fillAmount: getRandomInteger(1, 100e18),
|
||||
fromTokenBalance: getRandomInteger(1, 100e18),
|
||||
...opts,
|
||||
};
|
||||
}
|
||||
|
||||
async function transferAsync(opts?: Partial<TransferOpts>): Promise<[string, DecodedLogs]> {
|
||||
const _opts = createTransferOpts(opts);
|
||||
// Set the fill behavior.
|
||||
await testContract.setFillBehavior.awaitTransactionSuccessAsync(
|
||||
_opts.revertReason,
|
||||
new BigNumber(_opts.fillAmount),
|
||||
);
|
||||
// Set the token balance for the token we're converting from.
|
||||
await testContract.setTokenBalances.awaitTransactionSuccessAsync(
|
||||
_opts.toTokenAddress === daiTokenAddress
|
||||
? new BigNumber(_opts.fromTokenBalance)
|
||||
: constants.ZERO_AMOUNT,
|
||||
_opts.toTokenAddress === wethTokenAddress
|
||||
? new BigNumber(_opts.fromTokenBalance)
|
||||
: constants.ZERO_AMOUNT,
|
||||
);
|
||||
// Call transfer().
|
||||
const [result, { logs }] = await txHelper.getResultAndReceiptAsync(
|
||||
testContract.transfer,
|
||||
'0x',
|
||||
_opts.toTokenAddress,
|
||||
randomAddress(),
|
||||
_opts.toAddress,
|
||||
new BigNumber(_opts.amount),
|
||||
);
|
||||
return [result, (logs as any) as DecodedLogs];
|
||||
}
|
||||
|
||||
function getOppositeToken(tokenAddress: string): string {
|
||||
if (tokenAddress === daiTokenAddress) {
|
||||
return wethTokenAddress;
|
||||
}
|
||||
return daiTokenAddress;
|
||||
}
|
||||
|
||||
it('returns magic bytes on success', async () => {
|
||||
const BRIDGE_SUCCESS_RETURN_DATA = '0xb5d40d78';
|
||||
const [result] = await transferAsync();
|
||||
expect(result).to.eq(BRIDGE_SUCCESS_RETURN_DATA);
|
||||
});
|
||||
|
||||
it('calls `Eth2Dai.sellAllAmount()`', async () => {
|
||||
const opts = createTransferOpts();
|
||||
const [, logs] = await transferAsync(opts);
|
||||
const transfers = filterLogsToArguments<TestEth2DaiBridgeSellAllAmountEventArgs>(
|
||||
logs,
|
||||
TestEth2DaiBridgeEvents.SellAllAmount,
|
||||
);
|
||||
expect(transfers.length).to.eq(1);
|
||||
expect(transfers[0].sellToken).to.eq(getOppositeToken(opts.toTokenAddress));
|
||||
expect(transfers[0].buyToken).to.eq(opts.toTokenAddress);
|
||||
expect(transfers[0].sellTokenAmount).to.bignumber.eq(opts.fromTokenBalance);
|
||||
expect(transfers[0].minimumFillAmount).to.bignumber.eq(opts.amount);
|
||||
});
|
||||
|
||||
it('transfers filled amount to `to`', async () => {
|
||||
const opts = createTransferOpts();
|
||||
const [, logs] = await transferAsync(opts);
|
||||
const transfers = filterLogsToArguments<TestEth2DaiBridgeTokenTransferEventArgs>(
|
||||
logs,
|
||||
TestEth2DaiBridgeEvents.TokenTransfer,
|
||||
);
|
||||
expect(transfers.length).to.eq(1);
|
||||
expect(transfers[0].token).to.eq(opts.toTokenAddress);
|
||||
expect(transfers[0].from).to.eq(testContract.address);
|
||||
expect(transfers[0].to).to.eq(opts.toAddress);
|
||||
expect(transfers[0].amount).to.bignumber.eq(opts.fillAmount);
|
||||
});
|
||||
|
||||
it('fails if `Eth2Dai.sellAllAmount()` reverts', async () => {
|
||||
const opts = createTransferOpts({ revertReason: 'FOOBAR' });
|
||||
const tx = transferAsync(opts);
|
||||
return expect(tx).to.revertWith(opts.revertReason);
|
||||
});
|
||||
});
|
||||
});
|
@@ -7,17 +7,20 @@
|
||||
"generated-artifacts/ERC20BridgeProxy.json",
|
||||
"generated-artifacts/ERC20Proxy.json",
|
||||
"generated-artifacts/ERC721Proxy.json",
|
||||
"generated-artifacts/Eth2DaiBridge.json",
|
||||
"generated-artifacts/IAssetData.json",
|
||||
"generated-artifacts/IAssetProxy.json",
|
||||
"generated-artifacts/IAssetProxyDispatcher.json",
|
||||
"generated-artifacts/IAuthorizable.json",
|
||||
"generated-artifacts/IERC20Bridge.json",
|
||||
"generated-artifacts/IEth2Dai.json",
|
||||
"generated-artifacts/MixinAssetProxyDispatcher.json",
|
||||
"generated-artifacts/MixinAuthorizable.json",
|
||||
"generated-artifacts/MultiAssetProxy.json",
|
||||
"generated-artifacts/Ownable.json",
|
||||
"generated-artifacts/StaticCallProxy.json",
|
||||
"generated-artifacts/TestERC20Bridge.json",
|
||||
"generated-artifacts/TestEth2DaiBridge.json",
|
||||
"generated-artifacts/TestStaticCallTarget.json"
|
||||
],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
|
Reference in New Issue
Block a user