Contract Name:
FlashWallet
Contract Source Code:
// 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-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/errors/LibOwnableRichErrorsV06.sol";
import "../errors/LibWalletRichErrors.sol";
import "./IFlashWallet.sol";
/// @dev A contract that can execute arbitrary calls from its owner.
contract FlashWallet is
IFlashWallet
{
// 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 executeCall(
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) {
LibWalletRichErrors
.WalletExecuteCallFailedError(
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 executeDelegateCall(
address payable target,
bytes calldata callData
)
external
payable
override
onlyOwner
returns (bytes memory resultData)
{
bool success;
(success, resultData) = target.delegatecall(callData);
if (!success) {
LibWalletRichErrors
.WalletExecuteDelegateCallFailedError(
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
{}
}
// 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;
library LibRichErrorsV06 {
// bytes4(keccak256("Error(string)"))
bytes4 internal constant STANDARD_ERROR_SELECTOR = 0x08c379a0;
// solhint-disable func-name-mixedcase
/// @dev ABI encode a standard, string revert error payload.
/// This is the same payload that would be included by a `revert(string)`
/// solidity statement. It has the function signature `Error(string)`.
/// @param message The error string.
/// @return The ABI encoded error.
function StandardError(string memory message)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
STANDARD_ERROR_SELECTOR,
bytes(message)
);
}
// solhint-enable func-name-mixedcase
/// @dev Reverts an encoded rich revert reason `errorData`.
/// @param errorData ABI encoded error data.
function rrevert(bytes memory errorData)
internal
pure
{
assembly {
revert(add(errorData, 0x20), mload(errorData))
}
}
}
// 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;
library LibOwnableRichErrorsV06 {
// bytes4(keccak256("OnlyOwnerError(address,address)"))
bytes4 internal constant ONLY_OWNER_ERROR_SELECTOR =
0x1de45ad1;
// bytes4(keccak256("TransferOwnerToZeroError()"))
bytes internal constant TRANSFER_OWNER_TO_ZERO_ERROR_BYTES =
hex"e69edc3e";
// solhint-disable func-name-mixedcase
function OnlyOwnerError(
address sender,
address owner
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
ONLY_OWNER_ERROR_SELECTOR,
sender,
owner
);
}
function TransferOwnerToZeroError()
internal
pure
returns (bytes memory)
{
return TRANSFER_OWNER_TO_ZERO_ERROR_BYTES;
}
}
// 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;
library LibWalletRichErrors {
// solhint-disable func-name-mixedcase
function WalletExecuteCallFailedError(
address wallet,
address callTarget,
bytes memory callData,
uint256 callValue,
bytes memory errorData
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("WalletExecuteCallFailedError(address,address,bytes,uint256,bytes)")),
wallet,
callTarget,
callData,
callValue,
errorData
);
}
function WalletExecuteDelegateCallFailedError(
address wallet,
address callTarget,
bytes memory callData,
bytes memory errorData
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("WalletExecuteDelegateCallFailedError(address,address,bytes,bytes)")),
wallet,
callTarget,
callData,
errorData
);
}
}
// 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-utils/contracts/src/v06/interfaces/IOwnableV06.sol";
/// @dev A contract that can execute arbitrary calls from its owner.
interface IFlashWallet {
/// @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 executeCall(
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 executeDelegateCall(
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_);
}
// 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;
interface IOwnableV06 {
/// @dev Emitted by Ownable when ownership is transferred.
/// @param previousOwner The previous owner of the contract.
/// @param newOwner The new owner of the contract.
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/// @dev Transfers ownership of the contract to a new address.
/// @param newOwner The address that will become the owner.
function transferOwnership(address newOwner) external;
/// @dev The owner of this contract.
/// @return ownerAddress The owner address.
function owner() external view returns (address ownerAddress);
}