@0x/contracts-utils: Use simple assembly instead of abi.decode() in LibERC20Token._callWithOptionalBooleanResult().

`@0x/contracts-exchange-forwarder`: Use `LibERC20Token` in `MixinAssets`.
`@0x/order-utils`: Remove `TransferFailedError` from `ForwarderRevertErrors`.
This commit is contained in:
Lawrence Forman
2019-10-31 10:10:23 -04:00
parent 16dc73bd1e
commit c8ef10baaf
5 changed files with 12 additions and 55 deletions

View File

@@ -1,4 +1,12 @@
[ [
{
"changes": [
{
"note": "Use `LibERC20Token` in `MixinAssets`",
"pr": 2309
}
]
},
{ {
"version": "3.1.0-beta.0", "version": "3.1.0-beta.0",
"changes": [ "changes": [

View File

@@ -19,6 +19,7 @@
pragma solidity ^0.5.9; pragma solidity ^0.5.9;
import "@0x/contracts-utils/contracts/src/LibBytes.sol"; import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/LibERC20Token.sol";
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol"; import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-utils/contracts/src/Ownable.sol"; import "@0x/contracts-utils/contracts/src/Ownable.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
@@ -105,38 +106,8 @@ contract MixinAssets is
internal internal
{ {
address token = assetData.readAddress(16); address token = assetData.readAddress(16);
// Transfer tokens. // Transfer tokens.
// We do a raw call so we can check the success separate LibERC20Token.transfer(token, msg.sender, amount);
// from the return data.
(bool success, bytes memory returnData) = token.call(abi.encodeWithSelector(
ERC20_TRANSFER_SELECTOR,
msg.sender,
amount
));
if (!success) {
LibRichErrors.rrevert(LibForwarderRichErrors.TransferFailedError(returnData));
}
// Check return data.
// If there is no return data, we assume the token incorrectly
// does not return a bool. In this case we expect it to revert
// on failure, which was handled above.
// If the token does return data, we require that it is a single
// value that evaluates to true.
assembly {
if returndatasize {
success := 0
if eq(returndatasize, 32) {
// First 64 bytes of memory are reserved scratch space
returndatacopy(0, 0, 32)
success := mload(0)
}
}
}
if (!success) {
LibRichErrors.rrevert(LibForwarderRichErrors.TransferFailedError(returnData));
}
} }
/// @dev Decodes ERC721 assetData and transfers given amount to sender. /// @dev Decodes ERC721 assetData and transfers given amount to sender.

View File

@@ -51,10 +51,6 @@ library LibForwarderRichErrors {
bytes4 internal constant OVERSPENT_WETH_ERROR_SELECTOR = bytes4 internal constant OVERSPENT_WETH_ERROR_SELECTOR =
0xcdcbed5d; 0xcdcbed5d;
// bytes4(keccak256("TransferFailedError(bytes)"))
bytes4 internal constant TRANSFER_FAILED_ERROR_SELECTOR =
0x5e7eb60f;
// bytes4(keccak256("DefaultFunctionWethContractOnlyError(address)")) // bytes4(keccak256("DefaultFunctionWethContractOnlyError(address)"))
bytes4 internal constant DEFAULT_FUNCTION_WETH_CONTRACT_ONLY_ERROR_SELECTOR = bytes4 internal constant DEFAULT_FUNCTION_WETH_CONTRACT_ONLY_ERROR_SELECTOR =
0x08b18698; 0x08b18698;
@@ -160,19 +156,6 @@ library LibForwarderRichErrors {
); );
} }
function TransferFailedError(
bytes memory errorData
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
TRANSFER_FAILED_ERROR_SELECTOR,
errorData
);
}
function DefaultFunctionWethContractOnlyError( function DefaultFunctionWethContractOnlyError(
address senderAddress address senderAddress
) )

View File

@@ -101,7 +101,8 @@ library LibERC20Token {
return; return;
} }
if (resultData.length == 32) { if (resultData.length == 32) {
uint256 result = abi.decode(resultData, (uint256)); uint256 result;
assembly { result := mload(add(resultData, 0x20)) }
if (result == 1) { if (result == 1) {
return; return;
} }

View File

@@ -60,12 +60,6 @@ export class OverspentWethError extends RevertError {
} }
} }
export class TransferFailedError extends RevertError {
constructor(errorData?: string) {
super('TransferFailedError', 'TransferFailedError(bytes errorData)', { errorData });
}
}
export class DefaultFunctionWethContractOnlyError extends RevertError { export class DefaultFunctionWethContractOnlyError extends RevertError {
constructor(senderAddress?: string) { constructor(senderAddress?: string) {
super('DefaultFunctionWethContractOnlyError', 'DefaultFunctionWethContractOnlyError(address senderAddress)', { super('DefaultFunctionWethContractOnlyError', 'DefaultFunctionWethContractOnlyError(address senderAddress)', {