Migrate FlashWallet tests to foundry (#637)
* Remove contracts/zero-ex/contracts/test/TestBridge.sol * Move foundry tests to their default location * Wire up base foundry test and start moving FlashWallet tests and mocks to foundry * Move remaining FlashWallet contract tests to foundry * Switch to foundry default cache config
This commit is contained in:
parent
dcb17768cc
commit
b33fc27220
4
.gitignore
vendored
4
.gitignore
vendored
@ -176,8 +176,8 @@ contracts/treasury/test/generated-wrappers/
|
|||||||
# foundry artifacts
|
# foundry artifacts
|
||||||
contracts/zero-ex/foundry-artifacts/
|
contracts/zero-ex/foundry-artifacts/
|
||||||
|
|
||||||
# foundry cache
|
# foundry cache
|
||||||
contracts/zero-ex/foundry-cache/
|
contracts/zero-ex/cache/
|
||||||
|
|
||||||
# typechain wrappers
|
# typechain wrappers
|
||||||
contracts/zero-ex/typechain-wrappers/
|
contracts/zero-ex/typechain-wrappers/
|
||||||
|
@ -157,8 +157,6 @@
|
|||||||
"./contracts/src/vendor/v3/IERC20Bridge.sol",
|
"./contracts/src/vendor/v3/IERC20Bridge.sol",
|
||||||
"./contracts/src/vendor/v3/IStaking.sol",
|
"./contracts/src/vendor/v3/IStaking.sol",
|
||||||
"./contracts/test/ITestSimpleFunctionRegistryFeature.sol",
|
"./contracts/test/ITestSimpleFunctionRegistryFeature.sol",
|
||||||
"./contracts/test/TestBridge.sol",
|
|
||||||
"./contracts/test/TestCallTarget.sol",
|
|
||||||
"./contracts/test/TestDelegateCaller.sol",
|
"./contracts/test/TestDelegateCaller.sol",
|
||||||
"./contracts/test/TestFeeCollectorController.sol",
|
"./contracts/test/TestFeeCollectorController.sol",
|
||||||
"./contracts/test/TestFeeRecipient.sol",
|
"./contracts/test/TestFeeRecipient.sol",
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright 2020 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.6.5;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
|
||||||
import "../src/vendor/v3/IERC20Bridge.sol";
|
|
||||||
|
|
||||||
contract TestBridge is IERC20Bridge {
|
|
||||||
IERC20TokenV06 public immutable xAsset;
|
|
||||||
IERC20TokenV06 public immutable yAsset;
|
|
||||||
|
|
||||||
constructor(IERC20TokenV06 xAsset_, IERC20TokenV06 yAsset_) public {
|
|
||||||
xAsset = xAsset_;
|
|
||||||
yAsset = yAsset_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`.
|
|
||||||
/// @param tokenAddress The address of the ERC20 token to transfer.
|
|
||||||
/// @param from Address to transfer asset from.
|
|
||||||
/// @param to Address to transfer asset to.
|
|
||||||
/// @param amount Amount of asset to transfer.
|
|
||||||
/// @return success The magic bytes `0xdc1600f3` if successful.
|
|
||||||
function bridgeTransferFrom(
|
|
||||||
address tokenAddress,
|
|
||||||
address from,
|
|
||||||
address to,
|
|
||||||
uint256 amount,
|
|
||||||
bytes calldata /* bridgeData */
|
|
||||||
) external override returns (bytes4 success) {
|
|
||||||
IERC20TokenV06 takerToken = tokenAddress == address(xAsset) ? yAsset : xAsset;
|
|
||||||
uint256 takerTokenBalance = takerToken.balanceOf(address(this));
|
|
||||||
emit ERC20BridgeTransfer(address(takerToken), tokenAddress, takerTokenBalance, amount, from, to);
|
|
||||||
return 0xdecaf000;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,7 @@
|
|||||||
[profile.default]
|
[profile.default]
|
||||||
src = 'contracts/src'
|
src = 'contracts/src'
|
||||||
out = 'foundry-artifacts'
|
out = 'foundry-artifacts'
|
||||||
test = 'contracts/test/foundry'
|
test = 'tests'
|
||||||
libs = ["contracts/deps/", "../utils/contracts/src/"]
|
libs = ["contracts/deps/", "../utils/contracts/src/"]
|
||||||
remappings = ['@0x/contracts-utils/=../utils/', '@0x/contracts-erc20/=../erc20/', 'src/=./contracts/src']
|
remappings = ['@0x/contracts-utils/=../utils/', '@0x/contracts-erc20/=../erc20/', 'src/=./contracts/src']
|
||||||
cache_path = 'foundry-cache'
|
|
||||||
optimizer_runs = 1000000
|
optimizer_runs = 1000000
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature,AvalancheBridgeAdapter,BSCBridgeAdapter,CeloBridgeAdapter,EthereumBridgeAdapter,FantomBridgeAdapter,OptimismBridgeAdapter,PolygonBridgeAdapter",
|
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature,AvalancheBridgeAdapter,BSCBridgeAdapter,CeloBridgeAdapter,EthereumBridgeAdapter,FantomBridgeAdapter,OptimismBridgeAdapter,PolygonBridgeAdapter",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./test/generated-artifacts/@(AbstractBridgeAdapter|AffiliateFeeTransformer|AvalancheBridgeAdapter|BSCBridgeAdapter|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeProtocols|CeloBridgeAdapter|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|EthereumBridgeAdapter|FantomBridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2Batch|MixinBancor|MixinBancorV3|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinGMX|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinPlatypus|MixinShell|MixinSolidly|MixinSynthetix|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OptimismBridgeAdapter|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PolygonBridgeAdapter|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
"abis": "./test/generated-artifacts/@(AbstractBridgeAdapter|AffiliateFeeTransformer|AvalancheBridgeAdapter|BSCBridgeAdapter|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeProtocols|CeloBridgeAdapter|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|EthereumBridgeAdapter|FantomBridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2Batch|MixinBancor|MixinBancorV3|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinGMX|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinPlatypus|MixinShell|MixinSolidly|MixinSynthetix|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OptimismBridgeAdapter|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PolygonBridgeAdapter|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -152,8 +152,6 @@ import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/
|
|||||||
import * as PolygonBridgeAdapter from '../test/generated-artifacts/PolygonBridgeAdapter.json';
|
import * as PolygonBridgeAdapter from '../test/generated-artifacts/PolygonBridgeAdapter.json';
|
||||||
import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.json';
|
import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.json';
|
||||||
import * as SimpleFunctionRegistryFeature from '../test/generated-artifacts/SimpleFunctionRegistryFeature.json';
|
import * as SimpleFunctionRegistryFeature from '../test/generated-artifacts/SimpleFunctionRegistryFeature.json';
|
||||||
import * as TestBridge from '../test/generated-artifacts/TestBridge.json';
|
|
||||||
import * as TestCallTarget from '../test/generated-artifacts/TestCallTarget.json';
|
|
||||||
import * as TestCurve from '../test/generated-artifacts/TestCurve.json';
|
import * as TestCurve from '../test/generated-artifacts/TestCurve.json';
|
||||||
import * as TestDelegateCaller from '../test/generated-artifacts/TestDelegateCaller.json';
|
import * as TestDelegateCaller from '../test/generated-artifacts/TestDelegateCaller.json';
|
||||||
import * as TestFeeCollectorController from '../test/generated-artifacts/TestFeeCollectorController.json';
|
import * as TestFeeCollectorController from '../test/generated-artifacts/TestFeeCollectorController.json';
|
||||||
@ -364,8 +362,6 @@ export const artifacts = {
|
|||||||
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
||||||
IStaking: IStaking as ContractArtifact,
|
IStaking: IStaking as ContractArtifact,
|
||||||
ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact,
|
ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact,
|
||||||
TestBridge: TestBridge as ContractArtifact,
|
|
||||||
TestCallTarget: TestCallTarget as ContractArtifact,
|
|
||||||
TestDelegateCaller: TestDelegateCaller as ContractArtifact,
|
TestDelegateCaller: TestDelegateCaller as ContractArtifact,
|
||||||
TestFeeCollectorController: TestFeeCollectorController as ContractArtifact,
|
TestFeeCollectorController: TestFeeCollectorController as ContractArtifact,
|
||||||
TestFeeRecipient: TestFeeRecipient as ContractArtifact,
|
TestFeeRecipient: TestFeeRecipient as ContractArtifact,
|
||||||
|
@ -1,211 +0,0 @@
|
|||||||
import {
|
|
||||||
blockchainTests,
|
|
||||||
constants,
|
|
||||||
expect,
|
|
||||||
getRandomInteger,
|
|
||||||
randomAddress,
|
|
||||||
verifyEventsFromLogs,
|
|
||||||
} from '@0x/contracts-test-utils';
|
|
||||||
import { hexUtils, OwnableRevertErrors, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
|
||||||
|
|
||||||
import { artifacts } from './artifacts';
|
|
||||||
import { FlashWalletContract, TestCallTargetContract, TestCallTargetEvents } from './wrappers';
|
|
||||||
|
|
||||||
blockchainTests.resets('FlashWallet', env => {
|
|
||||||
let owner: string;
|
|
||||||
let wallet: FlashWalletContract;
|
|
||||||
let callTarget: TestCallTargetContract;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
[owner] = await env.getAccountAddressesAsync();
|
|
||||||
wallet = await FlashWalletContract.deployFrom0xArtifactAsync(
|
|
||||||
artifacts.FlashWallet,
|
|
||||||
env.provider,
|
|
||||||
{
|
|
||||||
...env.txDefaults,
|
|
||||||
from: owner,
|
|
||||||
},
|
|
||||||
artifacts,
|
|
||||||
);
|
|
||||||
callTarget = await TestCallTargetContract.deployFrom0xArtifactAsync(
|
|
||||||
artifacts.TestCallTarget,
|
|
||||||
env.provider,
|
|
||||||
env.txDefaults,
|
|
||||||
artifacts,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const TARGET_RETURN_VALUE = hexUtils.rightPad('0x12345678');
|
|
||||||
const REVERTING_DATA = '0x1337';
|
|
||||||
|
|
||||||
it('owned by deployer', () => {
|
|
||||||
return expect(wallet.owner().callAsync()).to.eventually.eq(owner);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('executeCall()', () => {
|
|
||||||
it('non-owner cannot call executeCall()', async () => {
|
|
||||||
const notOwner = randomAddress();
|
|
||||||
const tx = wallet
|
|
||||||
.executeCall(randomAddress(), hexUtils.random(), getRandomInteger(0, '100e18'))
|
|
||||||
.callAsync({ from: notOwner });
|
|
||||||
return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('owner can call executeCall()', async () => {
|
|
||||||
const targetData = hexUtils.random(128);
|
|
||||||
const receipt = await wallet
|
|
||||||
.executeCall(callTarget.address, targetData, constants.ZERO_AMOUNT)
|
|
||||||
.awaitTransactionSuccessAsync({ from: owner });
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
context: callTarget.address,
|
|
||||||
sender: wallet.address,
|
|
||||||
data: targetData,
|
|
||||||
value: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestCallTargetEvents.CallTargetCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('owner can call executeCall() with attached ETH', async () => {
|
|
||||||
const targetData = hexUtils.random(128);
|
|
||||||
const callValue = getRandomInteger(1, '1e18');
|
|
||||||
const receipt = await wallet
|
|
||||||
.executeCall(callTarget.address, targetData, callValue)
|
|
||||||
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
context: callTarget.address,
|
|
||||||
sender: wallet.address,
|
|
||||||
data: targetData,
|
|
||||||
value: callValue,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestCallTargetEvents.CallTargetCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('owner can call executeCall() can transfer less ETH than attached', async () => {
|
|
||||||
const targetData = hexUtils.random(128);
|
|
||||||
const callValue = getRandomInteger(1, '1e18');
|
|
||||||
const receipt = await wallet
|
|
||||||
.executeCall(callTarget.address, targetData, callValue.minus(1))
|
|
||||||
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
context: callTarget.address,
|
|
||||||
sender: wallet.address,
|
|
||||||
data: targetData,
|
|
||||||
value: callValue.minus(1),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestCallTargetEvents.CallTargetCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('wallet returns call result', async () => {
|
|
||||||
const result = await wallet
|
|
||||||
.executeCall(callTarget.address, hexUtils.random(128), constants.ZERO_AMOUNT)
|
|
||||||
.callAsync({ from: owner });
|
|
||||||
expect(result).to.eq(TARGET_RETURN_VALUE);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('wallet wraps call revert', async () => {
|
|
||||||
const tx = wallet
|
|
||||||
.executeCall(callTarget.address, REVERTING_DATA, constants.ZERO_AMOUNT)
|
|
||||||
.callAsync({ from: owner });
|
|
||||||
return expect(tx).to.revertWith(
|
|
||||||
new ZeroExRevertErrors.Wallet.WalletExecuteCallFailedError(
|
|
||||||
wallet.address,
|
|
||||||
callTarget.address,
|
|
||||||
REVERTING_DATA,
|
|
||||||
constants.ZERO_AMOUNT,
|
|
||||||
new StringRevertError('TestCallTarget/REVERT'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('wallet can receive ETH', async () => {
|
|
||||||
await env.web3Wrapper.sendTransactionAsync({
|
|
||||||
to: wallet.address,
|
|
||||||
from: owner,
|
|
||||||
value: 1,
|
|
||||||
});
|
|
||||||
const bal = await env.web3Wrapper.getBalanceInWeiAsync(wallet.address);
|
|
||||||
expect(bal).to.bignumber.eq(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('executeDelegateCall()', () => {
|
|
||||||
it('non-owner cannot call executeDelegateCall()', async () => {
|
|
||||||
const notOwner = randomAddress();
|
|
||||||
const tx = wallet.executeDelegateCall(randomAddress(), hexUtils.random()).callAsync({ from: notOwner });
|
|
||||||
return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('owner can call executeDelegateCall()', async () => {
|
|
||||||
const targetData = hexUtils.random(128);
|
|
||||||
const receipt = await wallet
|
|
||||||
.executeDelegateCall(callTarget.address, targetData)
|
|
||||||
.awaitTransactionSuccessAsync({ from: owner });
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
context: wallet.address,
|
|
||||||
sender: owner,
|
|
||||||
data: targetData,
|
|
||||||
value: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestCallTargetEvents.CallTargetCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('executeDelegateCall() is payable', async () => {
|
|
||||||
const targetData = hexUtils.random(128);
|
|
||||||
const callValue = getRandomInteger(1, '1e18');
|
|
||||||
const receipt = await wallet
|
|
||||||
.executeDelegateCall(callTarget.address, targetData)
|
|
||||||
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
context: wallet.address,
|
|
||||||
sender: owner,
|
|
||||||
data: targetData,
|
|
||||||
value: callValue,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestCallTargetEvents.CallTargetCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('wallet returns call result', async () => {
|
|
||||||
const result = await wallet
|
|
||||||
.executeDelegateCall(callTarget.address, hexUtils.random(128))
|
|
||||||
.callAsync({ from: owner });
|
|
||||||
expect(result).to.eq(TARGET_RETURN_VALUE);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('wallet wraps call revert', async () => {
|
|
||||||
const tx = wallet.executeDelegateCall(callTarget.address, REVERTING_DATA).callAsync({ from: owner });
|
|
||||||
return expect(tx).to.revertWith(
|
|
||||||
new ZeroExRevertErrors.Wallet.WalletExecuteDelegateCallFailedError(
|
|
||||||
wallet.address,
|
|
||||||
callTarget.address,
|
|
||||||
REVERTING_DATA,
|
|
||||||
new StringRevertError('TestCallTarget/REVERT'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -150,8 +150,6 @@ export * from '../test/generated-wrappers/permissionless_transformer_deployer';
|
|||||||
export * from '../test/generated-wrappers/polygon_bridge_adapter';
|
export * from '../test/generated-wrappers/polygon_bridge_adapter';
|
||||||
export * from '../test/generated-wrappers/positive_slippage_fee_transformer';
|
export * from '../test/generated-wrappers/positive_slippage_fee_transformer';
|
||||||
export * from '../test/generated-wrappers/simple_function_registry_feature';
|
export * from '../test/generated-wrappers/simple_function_registry_feature';
|
||||||
export * from '../test/generated-wrappers/test_bridge';
|
|
||||||
export * from '../test/generated-wrappers/test_call_target';
|
|
||||||
export * from '../test/generated-wrappers/test_curve';
|
export * from '../test/generated-wrappers/test_curve';
|
||||||
export * from '../test/generated-wrappers/test_delegate_caller';
|
export * from '../test/generated-wrappers/test_delegate_caller';
|
||||||
export * from '../test/generated-wrappers/test_fee_collector_controller';
|
export * from '../test/generated-wrappers/test_fee_collector_controller';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright 2022 ZeroEx Intl.
|
Copyright 2023 ZeroEx Intl.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -17,14 +17,18 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
import "forge-std/Test.sol";
|
import "forge-std/Test.sol";
|
||||||
|
|
||||||
contract ContractTest is Test {
|
contract BaseTest is Test {
|
||||||
function setUp() public {}
|
address payable internal account1 = payable(vm.addr(1));
|
||||||
|
address payable internal account2 = payable(vm.addr(2));
|
||||||
|
address payable internal account3 = payable(vm.addr(3));
|
||||||
|
|
||||||
function testExample() public {
|
constructor() public {
|
||||||
assertTrue(true);
|
vm.deal(account1, 1e20);
|
||||||
|
vm.deal(account2, 1e20);
|
||||||
|
vm.deal(account3, 1e20);
|
||||||
}
|
}
|
||||||
}
|
}
|
146
contracts/zero-ex/tests/FlashWalletTest.t.sol
Normal file
146
contracts/zero-ex/tests/FlashWalletTest.t.sol
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2022 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.6.5;
|
||||||
|
|
||||||
|
import "./BaseTest.sol";
|
||||||
|
import "../contracts/src/external/FlashWallet.sol";
|
||||||
|
import "./mocks/TestCallTarget.sol";
|
||||||
|
|
||||||
|
contract FlashWalletTest is BaseTest {
|
||||||
|
address public owner = account1;
|
||||||
|
FlashWallet public wallet;
|
||||||
|
TestCallTarget public callTarget;
|
||||||
|
|
||||||
|
bytes public constant MAGIC_BYTES = hex"1234567800000000000000000000000000000000000000000000000000000000";
|
||||||
|
bytes public constant REVERTING_DATA = hex"1337";
|
||||||
|
|
||||||
|
event CallTargetCalled(address sender, bytes data, uint256 value);
|
||||||
|
|
||||||
|
function setUp() public {
|
||||||
|
vm.startPrank(owner);
|
||||||
|
|
||||||
|
wallet = new FlashWallet();
|
||||||
|
callTarget = new TestCallTarget();
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_OwnedByDeployer() public {
|
||||||
|
assertEq(wallet.owner(), account1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeCall_nonOwnerCannotExecute() public {
|
||||||
|
vm.expectRevert(LibOwnableRichErrorsV06.OnlyOwnerError(account2, owner));
|
||||||
|
vm.startPrank(account2);
|
||||||
|
wallet.executeCall(address(callTarget), "0x1", 123);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeCall_ownerCanCallWithZeroValue() public {
|
||||||
|
vm.expectEmit(true, true, true, true);
|
||||||
|
emit CallTargetCalled(address(wallet), "0x1", 0);
|
||||||
|
vm.startPrank(owner);
|
||||||
|
wallet.executeCall(address(callTarget), "0x1", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeCall_ownerCanCallWithNonZeroValue() public {
|
||||||
|
vm.expectEmit(true, true, true, true);
|
||||||
|
emit CallTargetCalled(address(wallet), "0x1", 1);
|
||||||
|
vm.startPrank(owner);
|
||||||
|
wallet.executeCall{value: 1}(address(callTarget), "0x1", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeCall_ownerCanTransferLessETHThanAttached() public {
|
||||||
|
vm.expectEmit(true, true, true, true);
|
||||||
|
emit CallTargetCalled(address(wallet), "0x1", 1);
|
||||||
|
vm.startPrank(owner);
|
||||||
|
// Send value 2 but execute call with 1
|
||||||
|
wallet.executeCall{value: 2}(address(callTarget), "0x1", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeCall_walletReturnsCallResult() public {
|
||||||
|
vm.startPrank(owner);
|
||||||
|
bytes memory result = wallet.executeCall(address(callTarget), "0x1", 0);
|
||||||
|
assertEq0(result, MAGIC_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeCall_walletWrapsCallRevert() public {
|
||||||
|
(, bytes memory resultData) = address(callTarget).call(REVERTING_DATA);
|
||||||
|
bytes memory error = LibWalletRichErrors.WalletExecuteCallFailedError(
|
||||||
|
address(wallet),
|
||||||
|
address(callTarget),
|
||||||
|
REVERTING_DATA,
|
||||||
|
0,
|
||||||
|
resultData
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.expectRevert(error);
|
||||||
|
|
||||||
|
vm.startPrank(owner);
|
||||||
|
wallet.executeCall(address(callTarget), REVERTING_DATA, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeCall_walletCanReceiveETH() public {
|
||||||
|
vm.startPrank(owner);
|
||||||
|
(bool sent, ) = address(wallet).call{value: 1}("");
|
||||||
|
assertTrue(sent, "Failed to send ETH to wallet");
|
||||||
|
assertEq(address(wallet).balance, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeDelegateCall_nonOwnerCannotExecute() public {
|
||||||
|
vm.expectRevert(LibOwnableRichErrorsV06.OnlyOwnerError(account2, owner));
|
||||||
|
vm.startPrank(account2);
|
||||||
|
wallet.executeDelegateCall(address(callTarget), "0x1");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeDelegateCall_ownerCanExecute() public {
|
||||||
|
vm.expectEmit(true, true, true, true);
|
||||||
|
emit CallTargetCalled(owner, "0x1", 0);
|
||||||
|
vm.startPrank(owner);
|
||||||
|
wallet.executeDelegateCall(address(callTarget), "0x1");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeDelegateCall_ownerCanExecuteWithValue() public {
|
||||||
|
vm.expectEmit(true, true, true, true);
|
||||||
|
emit CallTargetCalled(owner, "0x1", 1);
|
||||||
|
vm.startPrank(owner);
|
||||||
|
wallet.executeDelegateCall{value: 1}(address(callTarget), "0x1");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeDelegateCall_walletReturnsCallResult() public {
|
||||||
|
vm.startPrank(owner);
|
||||||
|
bytes memory result = wallet.executeDelegateCall(address(callTarget), "0x1");
|
||||||
|
assertEq0(result, MAGIC_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_executeDelegateCall_walletWrapsCallRevert() public {
|
||||||
|
(, bytes memory resultData) = address(callTarget).call(REVERTING_DATA);
|
||||||
|
bytes memory error = LibWalletRichErrors.WalletExecuteDelegateCallFailedError(
|
||||||
|
address(wallet),
|
||||||
|
address(callTarget),
|
||||||
|
REVERTING_DATA,
|
||||||
|
resultData
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.expectRevert(error);
|
||||||
|
|
||||||
|
vm.startPrank(owner);
|
||||||
|
wallet.executeDelegateCall(address(callTarget), REVERTING_DATA);
|
||||||
|
}
|
||||||
|
}
|
@ -21,16 +21,16 @@ pragma solidity ^0.6.5;
|
|||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
contract TestCallTarget {
|
contract TestCallTarget {
|
||||||
event CallTargetCalled(address context, address sender, bytes data, uint256 value);
|
event CallTargetCalled(address sender, bytes data, uint256 value);
|
||||||
|
|
||||||
bytes4 private constant MAGIC_BYTES = 0x12345678;
|
bytes4 public constant MAGIC_BYTES = 0x12345678;
|
||||||
bytes private constant REVERTING_DATA = hex"1337";
|
bytes public constant REVERTING_DATA = hex"1337";
|
||||||
|
|
||||||
fallback() external payable {
|
fallback() external payable {
|
||||||
if (keccak256(msg.data) == keccak256(REVERTING_DATA)) {
|
if (keccak256(msg.data) == keccak256(REVERTING_DATA)) {
|
||||||
revert("TestCallTarget/REVERT");
|
revert("TestCallTarget/REVERT");
|
||||||
}
|
}
|
||||||
emit CallTargetCalled(address(this), msg.sender, msg.data, msg.value);
|
emit CallTargetCalled(msg.sender, msg.data, msg.value);
|
||||||
bytes4 rval = MAGIC_BYTES;
|
bytes4 rval = MAGIC_BYTES;
|
||||||
assembly {
|
assembly {
|
||||||
mstore(0, rval)
|
mstore(0, rval)
|
@ -189,8 +189,6 @@
|
|||||||
"test/generated-artifacts/PolygonBridgeAdapter.json",
|
"test/generated-artifacts/PolygonBridgeAdapter.json",
|
||||||
"test/generated-artifacts/PositiveSlippageFeeTransformer.json",
|
"test/generated-artifacts/PositiveSlippageFeeTransformer.json",
|
||||||
"test/generated-artifacts/SimpleFunctionRegistryFeature.json",
|
"test/generated-artifacts/SimpleFunctionRegistryFeature.json",
|
||||||
"test/generated-artifacts/TestBridge.json",
|
|
||||||
"test/generated-artifacts/TestCallTarget.json",
|
|
||||||
"test/generated-artifacts/TestCurve.json",
|
"test/generated-artifacts/TestCurve.json",
|
||||||
"test/generated-artifacts/TestDelegateCaller.json",
|
"test/generated-artifacts/TestDelegateCaller.json",
|
||||||
"test/generated-artifacts/TestFeeCollectorController.json",
|
"test/generated-artifacts/TestFeeCollectorController.json",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user