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
|
||||
contracts/zero-ex/foundry-artifacts/
|
||||
|
||||
# foundry cache
|
||||
contracts/zero-ex/foundry-cache/
|
||||
# foundry cache
|
||||
contracts/zero-ex/cache/
|
||||
|
||||
# typechain wrappers
|
||||
contracts/zero-ex/typechain-wrappers/
|
||||
|
@ -157,8 +157,6 @@
|
||||
"./contracts/src/vendor/v3/IERC20Bridge.sol",
|
||||
"./contracts/src/vendor/v3/IStaking.sol",
|
||||
"./contracts/test/ITestSimpleFunctionRegistryFeature.sol",
|
||||
"./contracts/test/TestBridge.sol",
|
||||
"./contracts/test/TestCallTarget.sol",
|
||||
"./contracts/test/TestDelegateCaller.sol",
|
||||
"./contracts/test/TestFeeCollectorController.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]
|
||||
src = 'contracts/src'
|
||||
out = 'foundry-artifacts'
|
||||
test = 'contracts/test/foundry'
|
||||
test = 'tests'
|
||||
libs = ["contracts/deps/", "../utils/contracts/src/"]
|
||||
remappings = ['@0x/contracts-utils/=../utils/', '@0x/contracts-erc20/=../erc20/', 'src/=./contracts/src']
|
||||
cache_path = 'foundry-cache'
|
||||
optimizer_runs = 1000000
|
||||
|
@ -43,7 +43,7 @@
|
||||
"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",
|
||||
"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": {
|
||||
"type": "git",
|
||||
|
@ -152,8 +152,6 @@ import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/
|
||||
import * as PolygonBridgeAdapter from '../test/generated-artifacts/PolygonBridgeAdapter.json';
|
||||
import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.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 TestDelegateCaller from '../test/generated-artifacts/TestDelegateCaller.json';
|
||||
import * as TestFeeCollectorController from '../test/generated-artifacts/TestFeeCollectorController.json';
|
||||
@ -364,8 +362,6 @@ export const artifacts = {
|
||||
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
||||
IStaking: IStaking as ContractArtifact,
|
||||
ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact,
|
||||
TestBridge: TestBridge as ContractArtifact,
|
||||
TestCallTarget: TestCallTarget as ContractArtifact,
|
||||
TestDelegateCaller: TestDelegateCaller as ContractArtifact,
|
||||
TestFeeCollectorController: TestFeeCollectorController 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/positive_slippage_fee_transformer';
|
||||
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_delegate_caller';
|
||||
export * from '../test/generated-wrappers/test_fee_collector_controller';
|
||||
|
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
|
||||
Copyright 2022 ZeroEx Intl.
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (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";
|
||||
|
||||
contract ContractTest is Test {
|
||||
function setUp() public {}
|
||||
contract BaseTest is Test {
|
||||
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 {
|
||||
assertTrue(true);
|
||||
constructor() public {
|
||||
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;
|
||||
|
||||
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;
|
||||
bytes private constant REVERTING_DATA = hex"1337";
|
||||
bytes4 public constant MAGIC_BYTES = 0x12345678;
|
||||
bytes public constant REVERTING_DATA = hex"1337";
|
||||
|
||||
fallback() external payable {
|
||||
if (keccak256(msg.data) == keccak256(REVERTING_DATA)) {
|
||||
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;
|
||||
assembly {
|
||||
mstore(0, rval)
|
@ -189,8 +189,6 @@
|
||||
"test/generated-artifacts/PolygonBridgeAdapter.json",
|
||||
"test/generated-artifacts/PositiveSlippageFeeTransformer.json",
|
||||
"test/generated-artifacts/SimpleFunctionRegistryFeature.json",
|
||||
"test/generated-artifacts/TestBridge.json",
|
||||
"test/generated-artifacts/TestCallTarget.json",
|
||||
"test/generated-artifacts/TestCurve.json",
|
||||
"test/generated-artifacts/TestDelegateCaller.json",
|
||||
"test/generated-artifacts/TestFeeCollectorController.json",
|
||||
|
Loading…
x
Reference in New Issue
Block a user