diff --git a/contracts/zero-ex/contracts/src/errors/LibPuppetRichErrors.sol b/contracts/zero-ex/contracts/src/errors/LibPuppetRichErrors.sol deleted file mode 100644 index 5d7e3ff043..0000000000 --- a/contracts/zero-ex/contracts/src/errors/LibPuppetRichErrors.sol +++ /dev/null @@ -1,65 +0,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; - - -library LibPuppetRichErrors { - - // solhint-disable func-name-mixedcase - - function PuppetExecuteFailedError( - address puppet, - address callTarget, - bytes memory callData, - uint256 callValue, - bytes memory errorData - ) - internal - pure - returns (bytes memory) - { - return abi.encodeWithSelector( - bytes4(keccak256("PuppetExecuteFailedError(address,address,bytes,uint256,bytes)")), - puppet, - callTarget, - callData, - callValue, - errorData - ); - } - - function PuppetExecuteWithFailedError( - address puppet, - address callTarget, - bytes memory callData, - bytes memory errorData - ) - internal - pure - returns (bytes memory) - { - return abi.encodeWithSelector( - bytes4(keccak256("PuppetExecuteWithFailedError(address,address,bytes,bytes)")), - puppet, - callTarget, - callData, - errorData - ); - } -} diff --git a/contracts/zero-ex/contracts/src/external/IPuppet.sol b/contracts/zero-ex/contracts/src/external/IPuppet.sol deleted file mode 100644 index f349476db9..0000000000 --- a/contracts/zero-ex/contracts/src/external/IPuppet.sol +++ /dev/null @@ -1,61 +0,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-utils/contracts/src/v06/interfaces/IOwnableV06.sol"; - - -/// @dev A contract that can execute arbitrary calls from its owner. -interface IPuppet { - - /// @dev Execute an arbitrary call. Only an authority can call this. - /// @param target The call target. - /// @param callData The call data. - /// @param value Ether to attach to the call. - /// @return resultData The data returned by the call. - function execute( - address payable target, - bytes calldata callData, - uint256 value - ) - external - payable - returns (bytes memory resultData); - - /// @dev Execute an arbitrary delegatecall, in the context of this puppet. - /// Only an authority can call this. - /// @param target The call target. - /// @param callData The call data. - /// @return resultData The data returned by the call. - function executeWith( - address payable target, - bytes calldata callData - ) - external - payable - returns (bytes memory resultData); - - /// @dev Allows the puppet to receive ETH. - receive() external payable; - - /// @dev Fetch the immutable owner/deployer of this contract. - /// @return owner_ The immutable owner/deployer/ - function owner() external view returns (address owner_); -} diff --git a/contracts/zero-ex/contracts/src/external/Puppet.sol b/contracts/zero-ex/contracts/src/external/Puppet.sol deleted file mode 100644 index aea8457bde..0000000000 --- a/contracts/zero-ex/contracts/src/external/Puppet.sol +++ /dev/null @@ -1,175 +0,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-utils/contracts/src/v06/errors/LibRichErrorsV06.sol"; -import "@0x/contracts-utils/contracts/src/v06/errors/LibOwnableRichErrorsV06.sol"; -import "../errors/LibPuppetRichErrors.sol"; -import "./IPuppet.sol"; - - -/// @dev A contract that can execute arbitrary calls from its owner. -contract Puppet is - IPuppet -{ - // solhint-disable no-unused-vars,indent,no-empty-blocks - using LibRichErrorsV06 for bytes; - - // solhint-disable - /// @dev Store the owner/deployer as an immutable to make this contract stateless. - address public override immutable owner; - // solhint-enable - - constructor() public { - // The deployer is the owner. - owner = msg.sender; - } - - /// @dev Allows only the (immutable) owner to call a function. - modifier onlyOwner() virtual { - if (msg.sender != owner) { - LibOwnableRichErrorsV06.OnlyOwnerError( - msg.sender, - owner - ).rrevert(); - } - _; - } - - /// @dev Execute an arbitrary call. Only an authority can call this. - /// @param target The call target. - /// @param callData The call data. - /// @param value Ether to attach to the call. - /// @return resultData The data returned by the call. - function execute( - address payable target, - bytes calldata callData, - uint256 value - ) - external - payable - override - onlyOwner - returns (bytes memory resultData) - { - bool success; - (success, resultData) = target.call{value: value}(callData); - if (!success) { - LibPuppetRichErrors - .PuppetExecuteFailedError( - address(this), - target, - callData, - value, - resultData - ) - .rrevert(); - } - } - - /// @dev Execute an arbitrary delegatecall, in the context of this puppet. - /// Only an authority can call this. - /// @param target The call target. - /// @param callData The call data. - /// @return resultData The data returned by the call. - function executeWith( - address payable target, - bytes calldata callData - ) - external - payable - override - onlyOwner - returns (bytes memory resultData) - { - bool success; - (success, resultData) = target.delegatecall(callData); - if (!success) { - LibPuppetRichErrors - .PuppetExecuteWithFailedError( - address(this), - target, - callData, - resultData - ) - .rrevert(); - } - } - - // solhint-disable - /// @dev Allows this contract to receive ether. - receive() external override payable {} - // solhint-enable - - /// @dev Signal support for receiving ERC1155 tokens. - /// @param interfaceID The interface ID, as per ERC-165 rules. - /// @return hasSupport `true` if this contract supports an ERC-165 interface. - function supportsInterface(bytes4 interfaceID) - external - pure - returns (bool hasSupport) - { - return interfaceID == this.supportsInterface.selector || - interfaceID == this.onERC1155Received.selector ^ this.onERC1155BatchReceived.selector || - interfaceID == this.tokenFallback.selector; - } - - /// @dev Allow this contract to receive ERC1155 tokens. - /// @return success `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` - function onERC1155Received( - address, // operator, - address, // from, - uint256, // id, - uint256, // value, - bytes calldata //data - ) - external - pure - returns (bytes4 success) - { - return this.onERC1155Received.selector; - } - - /// @dev Allow this contract to receive ERC1155 tokens. - /// @return success `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` - function onERC1155BatchReceived( - address, // operator, - address, // from, - uint256[] calldata, // ids, - uint256[] calldata, // values, - bytes calldata // data - ) - external - pure - returns (bytes4 success) - { - return this.onERC1155BatchReceived.selector; - } - - /// @dev Allows this contract to receive ERC223 tokens. - function tokenFallback( - address, // from, - uint256, // value, - bytes calldata // value - ) - external - pure - {} -} diff --git a/contracts/zero-ex/contracts/test/TestPuppetTarget.sol b/contracts/zero-ex/contracts/test/TestPuppetTarget.sol deleted file mode 100644 index 85b4164fd9..0000000000 --- a/contracts/zero-ex/contracts/test/TestPuppetTarget.sol +++ /dev/null @@ -1,51 +0,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; - - -contract TestPuppetTarget { - - event PuppetTargetCalled( - address context, - address sender, - bytes data, - uint256 value - ); - - bytes4 private constant MAGIC_BYTES = 0x12345678; - bytes private constant REVERTING_DATA = hex"1337"; - - fallback() external payable { - if (keccak256(msg.data) == keccak256(REVERTING_DATA)) { - revert("TestPuppetTarget/REVERT"); - } - emit PuppetTargetCalled( - address(this), - msg.sender, - msg.data, - msg.value - ); - bytes4 rval = MAGIC_BYTES; - assembly { - mstore(0, rval) - return(0, 32) - } - } -} diff --git a/contracts/zero-ex/test/puppet_test.ts b/contracts/zero-ex/test/puppet_test.ts deleted file mode 100644 index 6514c636fa..0000000000 --- a/contracts/zero-ex/test/puppet_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 { PuppetContract, TestPuppetTargetContract, TestPuppetTargetEvents } from './wrappers'; - -blockchainTests.resets('Puppets', env => { - let owner: string; - let puppet: PuppetContract; - let puppetTarget: TestPuppetTargetContract; - - before(async () => { - [owner] = await env.getAccountAddressesAsync(); - puppet = await PuppetContract.deployFrom0xArtifactAsync( - artifacts.Puppet, - env.provider, - { - ...env.txDefaults, - from: owner, - }, - artifacts, - ); - puppetTarget = await TestPuppetTargetContract.deployFrom0xArtifactAsync( - artifacts.TestPuppetTarget, - env.provider, - env.txDefaults, - artifacts, - ); - }); - - const TARGET_RETURN_VALUE = hexUtils.rightPad('0x12345678'); - const REVERTING_DATA = '0x1337'; - - it('owned by deployer', () => { - return expect(puppet.owner().callAsync()).to.eventually.eq(owner); - }); - - describe('execute()', () => { - it('non-owner cannot call execute()', async () => { - const notOwner = randomAddress(); - const tx = puppet - .execute(randomAddress(), hexUtils.random(), getRandomInteger(0, '100e18')) - .callAsync({ from: notOwner }); - return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner)); - }); - - it('owner can call execute()', async () => { - const targetData = hexUtils.random(128); - const receipt = await puppet - .execute(puppetTarget.address, targetData, constants.ZERO_AMOUNT) - .awaitTransactionSuccessAsync({ from: owner }); - verifyEventsFromLogs( - receipt.logs, - [ - { - context: puppetTarget.address, - sender: puppet.address, - data: targetData, - value: constants.ZERO_AMOUNT, - }, - ], - TestPuppetTargetEvents.PuppetTargetCalled, - ); - }); - - it('owner can call execute() with attached ETH', async () => { - const targetData = hexUtils.random(128); - const callValue = getRandomInteger(1, '1e18'); - const receipt = await puppet - .execute(puppetTarget.address, targetData, callValue) - .awaitTransactionSuccessAsync({ from: owner, value: callValue }); - verifyEventsFromLogs( - receipt.logs, - [ - { - context: puppetTarget.address, - sender: puppet.address, - data: targetData, - value: callValue, - }, - ], - TestPuppetTargetEvents.PuppetTargetCalled, - ); - }); - - it('owner can call execute() can transfer less ETH than attached', async () => { - const targetData = hexUtils.random(128); - const callValue = getRandomInteger(1, '1e18'); - const receipt = await puppet - .execute(puppetTarget.address, targetData, callValue.minus(1)) - .awaitTransactionSuccessAsync({ from: owner, value: callValue }); - verifyEventsFromLogs( - receipt.logs, - [ - { - context: puppetTarget.address, - sender: puppet.address, - data: targetData, - value: callValue.minus(1), - }, - ], - TestPuppetTargetEvents.PuppetTargetCalled, - ); - }); - - it('puppet returns call result', async () => { - const result = await puppet - .execute(puppetTarget.address, hexUtils.random(128), constants.ZERO_AMOUNT) - .callAsync({ from: owner }); - expect(result).to.eq(TARGET_RETURN_VALUE); - }); - - it('puppet wraps call revert', async () => { - const tx = puppet - .execute(puppetTarget.address, REVERTING_DATA, constants.ZERO_AMOUNT) - .callAsync({ from: owner }); - return expect(tx).to.revertWith( - new ZeroExRevertErrors.Puppet.PuppetExecuteFailedError( - puppet.address, - puppetTarget.address, - REVERTING_DATA, - constants.ZERO_AMOUNT, - new StringRevertError('TestPuppetTarget/REVERT').encode(), - ), - ); - }); - - it('puppet can receive ETH', async () => { - await env.web3Wrapper.sendTransactionAsync({ - to: puppet.address, - from: owner, - value: 1, - }); - const bal = await env.web3Wrapper.getBalanceInWeiAsync(puppet.address); - expect(bal).to.bignumber.eq(1); - }); - }); - - describe('executeWith()', () => { - it('non-owner cannot call executeWith()', async () => { - const notOwner = randomAddress(); - const tx = puppet.executeWith(randomAddress(), hexUtils.random()).callAsync({ from: notOwner }); - return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner)); - }); - - it('owner can call executeWith()', async () => { - const targetData = hexUtils.random(128); - const receipt = await puppet - .executeWith(puppetTarget.address, targetData) - .awaitTransactionSuccessAsync({ from: owner }); - verifyEventsFromLogs( - receipt.logs, - [ - { - context: puppet.address, - sender: owner, - data: targetData, - value: constants.ZERO_AMOUNT, - }, - ], - TestPuppetTargetEvents.PuppetTargetCalled, - ); - }); - - it('executeWith() is payable', async () => { - const targetData = hexUtils.random(128); - const callValue = getRandomInteger(1, '1e18'); - const receipt = await puppet - .executeWith(puppetTarget.address, targetData) - .awaitTransactionSuccessAsync({ from: owner, value: callValue }); - verifyEventsFromLogs( - receipt.logs, - [ - { - context: puppet.address, - sender: owner, - data: targetData, - value: callValue, - }, - ], - TestPuppetTargetEvents.PuppetTargetCalled, - ); - }); - - it('puppet returns call result', async () => { - const result = await puppet - .executeWith(puppetTarget.address, hexUtils.random(128)) - .callAsync({ from: owner }); - expect(result).to.eq(TARGET_RETURN_VALUE); - }); - - it('puppet wraps call revert', async () => { - const tx = puppet.executeWith(puppetTarget.address, REVERTING_DATA).callAsync({ from: owner }); - return expect(tx).to.revertWith( - new ZeroExRevertErrors.Puppet.PuppetExecuteWithFailedError( - puppet.address, - puppetTarget.address, - REVERTING_DATA, - new StringRevertError('TestPuppetTarget/REVERT').encode(), - ), - ); - }); - }); -});