diff --git a/.gitignore b/.gitignore index e30e893bff..7aed5ab90f 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/contracts/zero-ex/compiler.json b/contracts/zero-ex/compiler.json index 7b38881a7a..81a46e7b21 100644 --- a/contracts/zero-ex/compiler.json +++ b/contracts/zero-ex/compiler.json @@ -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", diff --git a/contracts/zero-ex/contracts/test/TestBridge.sol b/contracts/zero-ex/contracts/test/TestBridge.sol deleted file mode 100644 index 718deca80d..0000000000 --- a/contracts/zero-ex/contracts/test/TestBridge.sol +++ /dev/null @@ -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; - } -} diff --git a/contracts/zero-ex/foundry.toml b/contracts/zero-ex/foundry.toml index 5254ff5670..ddf0bbeeba 100644 --- a/contracts/zero-ex/foundry.toml +++ b/contracts/zero-ex/foundry.toml @@ -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 diff --git a/contracts/zero-ex/package.json b/contracts/zero-ex/package.json index 518cd0befb..4ef0b8a350 100644 --- a/contracts/zero-ex/package.json +++ b/contracts/zero-ex/package.json @@ -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", diff --git a/contracts/zero-ex/test/artifacts.ts b/contracts/zero-ex/test/artifacts.ts index 8449d5231b..5af249be83 100644 --- a/contracts/zero-ex/test/artifacts.ts +++ b/contracts/zero-ex/test/artifacts.ts @@ -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, diff --git a/contracts/zero-ex/test/flash_wallet_test.ts b/contracts/zero-ex/test/flash_wallet_test.ts deleted file mode 100644 index f13f0fa6a2..0000000000 --- a/contracts/zero-ex/test/flash_wallet_test.ts +++ /dev/null @@ -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'), - ), - ); - }); - }); -}); diff --git a/contracts/zero-ex/test/wrappers.ts b/contracts/zero-ex/test/wrappers.ts index 5f0cd5bb96..022062f292 100644 --- a/contracts/zero-ex/test/wrappers.ts +++ b/contracts/zero-ex/test/wrappers.ts @@ -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'; diff --git a/contracts/zero-ex/contracts/test/foundry/ContractTest.sol b/contracts/zero-ex/tests/BaseTest.sol similarity index 61% rename from contracts/zero-ex/contracts/test/foundry/ContractTest.sol rename to contracts/zero-ex/tests/BaseTest.sol index c405020662..1ded630eed 100644 --- a/contracts/zero-ex/contracts/test/foundry/ContractTest.sol +++ b/contracts/zero-ex/tests/BaseTest.sol @@ -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); } } diff --git a/contracts/zero-ex/tests/FlashWalletTest.t.sol b/contracts/zero-ex/tests/FlashWalletTest.t.sol new file mode 100644 index 0000000000..7e38ce7bf5 --- /dev/null +++ b/contracts/zero-ex/tests/FlashWalletTest.t.sol @@ -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); + } +} diff --git a/contracts/zero-ex/contracts/test/TestCallTarget.sol b/contracts/zero-ex/tests/mocks/TestCallTarget.sol similarity index 78% rename from contracts/zero-ex/contracts/test/TestCallTarget.sol rename to contracts/zero-ex/tests/mocks/TestCallTarget.sol index cdbdb5bd1e..9b5e249de1 100644 --- a/contracts/zero-ex/contracts/test/TestCallTarget.sol +++ b/contracts/zero-ex/tests/mocks/TestCallTarget.sol @@ -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) diff --git a/contracts/zero-ex/tsconfig.json b/contracts/zero-ex/tsconfig.json index 47b0d733a8..dc88229614 100644 --- a/contracts/zero-ex/tsconfig.json +++ b/contracts/zero-ex/tsconfig.json @@ -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",