Convert to use rich reverts
This commit is contained in:
parent
34e0345b29
commit
7277fb3d93
@ -25,7 +25,8 @@ import "./interfaces/IAssetProxy.sol";
|
|||||||
|
|
||||||
contract MixinAssetProxyDispatcher is
|
contract MixinAssetProxyDispatcher is
|
||||||
Ownable,
|
Ownable,
|
||||||
MAssetProxyDispatcher
|
MAssetProxyDispatcher,
|
||||||
|
MRichErrors
|
||||||
{
|
{
|
||||||
// Mapping from Asset Proxy Id's to their respective Asset Proxy
|
// Mapping from Asset Proxy Id's to their respective Asset Proxy
|
||||||
mapping (bytes4 => address) public assetProxies;
|
mapping (bytes4 => address) public assetProxies;
|
||||||
@ -64,17 +65,17 @@ contract MixinAssetProxyDispatcher is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
|
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
|
||||||
|
/// @param orderHash Hash of the order associated with this transfer.
|
||||||
/// @param assetData Byte array encoded for the asset.
|
/// @param assetData Byte array encoded for the asset.
|
||||||
/// @param from Address to transfer token from.
|
/// @param from Address to transfer token from.
|
||||||
/// @param to Address to transfer token to.
|
/// @param to Address to transfer token to.
|
||||||
/// @param amount Amount of token to transfer.
|
/// @param amount Amount of token to transfer.
|
||||||
/// @param orderHash Order hash, used for rich reverts.
|
|
||||||
function dispatchTransferFrom(
|
function dispatchTransferFrom(
|
||||||
|
bytes32 orderHash,
|
||||||
bytes memory assetData,
|
bytes memory assetData,
|
||||||
address from,
|
address from,
|
||||||
address to,
|
address to,
|
||||||
uint256 amount,
|
uint256 amount
|
||||||
bytes32 orderHash
|
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
@ -82,14 +83,13 @@ contract MixinAssetProxyDispatcher is
|
|||||||
if (amount > 0 && from != to) {
|
if (amount > 0 && from != to) {
|
||||||
// Ensure assetData length is valid
|
// Ensure assetData length is valid
|
||||||
if (assetData.length <= 3) {
|
if (assetData.length <= 3) {
|
||||||
rrevert(AssetProxyDispatchError(AssetProxyDispatchErrorCodes.INVALID_ASSET_DATA_LENGTH));
|
rrevert(AssetProxyDispatchError(
|
||||||
|
orderHash,
|
||||||
|
assetData,
|
||||||
|
AssetProxyDispatchErrorCodes.INVALID_ASSET_DATA_LENGTH
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
require(
|
|
||||||
assetData.length > 3,
|
|
||||||
"LENGTH_GREATER_THAN_3_REQUIRED"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Lookup assetProxy. We do not use `LibBytes.readBytes4` for gas efficiency reasons.
|
// Lookup assetProxy. We do not use `LibBytes.readBytes4` for gas efficiency reasons.
|
||||||
bytes4 assetProxyId;
|
bytes4 assetProxyId;
|
||||||
assembly {
|
assembly {
|
||||||
@ -102,13 +102,17 @@ contract MixinAssetProxyDispatcher is
|
|||||||
|
|
||||||
// Ensure that assetProxy exists
|
// Ensure that assetProxy exists
|
||||||
if (assetProxy == address(0)) {
|
if (assetProxy == address(0)) {
|
||||||
rrevert(AssetProxyDispatchError(AssetProxyDispatchErrorCodes.UNKNOWN_ASSET_PROXY));
|
rrevert(AssetProxyDispatchError(
|
||||||
|
orderHash,
|
||||||
|
assetData,
|
||||||
|
AssetProxyDispatchErrorCodes.UNKNOWN_ASSET_PROXY
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether the AssetProxy transfer succeeded.
|
// Whether the AssetProxy transfer succeeded.
|
||||||
bool didSucceed;
|
bool didSucceed;
|
||||||
// On failure, the revert message returned by the asset proxy.
|
// On failure, the revert message returned by the asset proxy.
|
||||||
bytes revertMessage = new bytes(0);
|
bytes revertMessage;
|
||||||
|
|
||||||
// We construct calldata for the `assetProxy.transferFrom` ABI.
|
// We construct calldata for the `assetProxy.transferFrom` ABI.
|
||||||
// The layout of this calldata is in the table below.
|
// The layout of this calldata is in the table below.
|
||||||
@ -129,8 +133,8 @@ contract MixinAssetProxyDispatcher is
|
|||||||
/////// Setup State ///////
|
/////// Setup State ///////
|
||||||
// `cdStart` is the start of the calldata for `assetProxy.transferFrom` (equal to free memory ptr).
|
// `cdStart` is the start of the calldata for `assetProxy.transferFrom` (equal to free memory ptr).
|
||||||
let cdStart := mload(64)
|
let cdStart := mload(64)
|
||||||
// We reserve 256 bytes from `cdStart` because we'll reuse it later for return data.
|
// We reserve 288 bytes from `cdStart` because we'll reuse it later for return data.
|
||||||
mstore(64, add(cdStart, 256))
|
mstore(64, add(cdStart, 288))
|
||||||
// `dataAreaLength` is the total number of words needed to store `assetData`
|
// `dataAreaLength` is the total number of words needed to store `assetData`
|
||||||
// As-per the ABI spec, this value is padded up to the nearest multiple of 32,
|
// As-per the ABI spec, this value is padded up to the nearest multiple of 32,
|
||||||
// and includes 32-bytes for length.
|
// and includes 32-bytes for length.
|
||||||
@ -172,7 +176,7 @@ contract MixinAssetProxyDispatcher is
|
|||||||
cdStart, // pointer to start of input
|
cdStart, // pointer to start of input
|
||||||
sub(cdEnd, cdStart), // length of input
|
sub(cdEnd, cdStart), // length of input
|
||||||
cdStart, // write output over input
|
cdStart, // write output over input
|
||||||
256 // reserve 256 bytes for output
|
288 // reserve 288 bytes for output
|
||||||
)
|
)
|
||||||
|
|
||||||
if iszero(didSucceed) { // Call reverted.
|
if iszero(didSucceed) { // Call reverted.
|
||||||
@ -196,12 +200,12 @@ contract MixinAssetProxyDispatcher is
|
|||||||
let selector := and(mload(sub(cdStart, 28), 0xffffffff)
|
let selector := and(mload(sub(cdStart, 28), 0xffffffff)
|
||||||
cdStart := add(cdStart, 4)
|
cdStart := add(cdStart, 4)
|
||||||
if eq(selector, 0x08c379a) {
|
if eq(selector, 0x08c379a) {
|
||||||
let dataLength := mload(cdStart);
|
// Set revertMessage to the start of Data.
|
||||||
revertMessage := add(cdStart, mload(cdStart))
|
revertMessage := add(cdStart, mload(cdStart))
|
||||||
// Truncate the data length if it's larger than our buffer
|
// Truncate the data length if it's larger than our buffer
|
||||||
// size (256 - 32 = 224)
|
// size (288 - 32 = 256)
|
||||||
if gt(dataLength, 224) {
|
if gt(mload(revertMessage), 256) {
|
||||||
mstore(revertMessage, 224)
|
mstore(revertMessage, 256)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ contract MixinRichErrors is
|
|||||||
}
|
}
|
||||||
|
|
||||||
function AssetProxyExistsError(
|
function AssetProxyExistsError(
|
||||||
address proxy
|
address proxyAddress
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
@ -143,11 +143,12 @@ contract MixinRichErrors is
|
|||||||
{
|
{
|
||||||
return abi.encodeWithSelector(
|
return abi.encodeWithSelector(
|
||||||
ASSET_PROXY_EXISTS_ERROR_SELECTOR,
|
ASSET_PROXY_EXISTS_ERROR_SELECTOR,
|
||||||
proxy
|
proxyAddress
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AssetProxyDispatchError(
|
function AssetProxyDispatchError(
|
||||||
|
bytes32 orderHash,
|
||||||
bytes memory assetData,
|
bytes memory assetData,
|
||||||
AssetProxyDispatchErrorCodes error
|
AssetProxyDispatchErrorCodes error
|
||||||
)
|
)
|
||||||
@ -157,6 +158,7 @@ contract MixinRichErrors is
|
|||||||
{
|
{
|
||||||
return abi.encodeWithSelector(
|
return abi.encodeWithSelector(
|
||||||
ASSET_PROXY_DISPATCH_ERROR_SELECTOR,
|
ASSET_PROXY_DISPATCH_ERROR_SELECTOR,
|
||||||
|
orderHash,
|
||||||
assetData,
|
assetData,
|
||||||
uint8(error)
|
uint8(error)
|
||||||
);
|
);
|
||||||
|
@ -18,9 +18,12 @@
|
|||||||
|
|
||||||
pragma solidity ^0.5.5;
|
pragma solidity ^0.5.5;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracs/src/mixins/MLibRichErrors.sol";
|
||||||
|
|
||||||
contract MRichErrors {
|
|
||||||
|
|
||||||
|
contract MRichErrors is
|
||||||
|
MLibRichErrors
|
||||||
|
{
|
||||||
enum FillErrorCodes {
|
enum FillErrorCodes {
|
||||||
INVALID_TAKER_AMOUNT,
|
INVALID_TAKER_AMOUNT,
|
||||||
TAKER_OVERPAY,
|
TAKER_OVERPAY,
|
||||||
@ -139,9 +142,10 @@ contract MRichErrors {
|
|||||||
returns (bytes memory);
|
returns (bytes memory);
|
||||||
|
|
||||||
bytes4 internal constant ASSET_PROXY_DISPATCH_ERROR_SELECTOR =
|
bytes4 internal constant ASSET_PROXY_DISPATCH_ERROR_SELECTOR =
|
||||||
bytes4(keccak256("AssetProxyDispatchError(bytes,uint8)"));
|
bytes4(keccak256("AssetProxyDispatchError(bytes32,bytes,uint8)"));
|
||||||
|
|
||||||
function AssetProxyDispatchError(
|
function AssetProxyDispatchError(
|
||||||
|
bytes32 orderHash,
|
||||||
bytes memory assetData,
|
bytes memory assetData,
|
||||||
AssetProxyDispatchErrorCodes error
|
AssetProxyDispatchErrorCodes error
|
||||||
)
|
)
|
||||||
|
@ -18,12 +18,13 @@
|
|||||||
|
|
||||||
pragma solidity ^0.5.5;
|
pragma solidity ^0.5.5;
|
||||||
|
|
||||||
contract LibRichErrors {
|
import "./mixins/MLibRichErrors.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract LibRichErrors is
|
||||||
|
MLibRichErrors
|
||||||
|
{
|
||||||
// solhint-disable func-name-mixedcase
|
// solhint-disable func-name-mixedcase
|
||||||
|
|
||||||
bytes4 private constant STANDARD_ERROR_SELECTOR =
|
|
||||||
bytes4(keccak256("Error(string)"));
|
|
||||||
|
|
||||||
function StandardError(
|
function StandardError(
|
||||||
string memory message
|
string memory message
|
||||||
)
|
)
|
||||||
|
41
contracts/utils/contracts/src/mixins/MLibRichErrors.sol
Normal file
41
contracts/utils/contracts/src/mixins/MLibRichErrors.sol
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 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.5.5;
|
||||||
|
|
||||||
|
contract MRichErrors {
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
|
||||||
|
bytes4 internal constant STANDARD_ERROR_SELECTOR =
|
||||||
|
bytes4(keccak256("Error(string)"));
|
||||||
|
|
||||||
|
function StandardError(
|
||||||
|
string memory message
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user