Move LibAssetDataTransfer from forwarder to exchange-libs package

This commit is contained in:
Michael Zhu
2020-01-28 16:06:09 -08:00
parent c5e0de51aa
commit 3da7c5d3e2
23 changed files with 126 additions and 67 deletions

View File

@@ -1,4 +1,13 @@
[
{
"version": "4.2.0",
"changes": [
{
"note": "Moved LibAssetDataTransfer here from forwarder",
"pr": 2455
}
]
},
{
"timestamp": 1580811564,
"version": "4.1.1",

View File

@@ -0,0 +1,258 @@
/*
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.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "./LibAssetDataTransferRichErrors.sol";
library LibAssetDataTransfer {
using LibBytes for bytes;
using LibSafeMath for uint256;
using LibAssetDataTransfer for bytes;
/// @dev Transfers given amount of asset to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer to sender.
function transferFrom(
bytes memory assetData,
address from,
address to,
uint256 amount
)
internal
{
if (amount == 0) {
return;
}
bytes4 proxyId = assetData.readBytes4(0);
if (
proxyId == IAssetData(address(0)).ERC20Token.selector ||
proxyId == IAssetData(address(0)).ERC20Bridge.selector
) {
assetData.transferERC20Token(
from,
to,
amount
);
} else if (proxyId == IAssetData(address(0)).ERC721Token.selector) {
assetData.transferERC721Token(
from,
to,
amount
);
} else if (proxyId == IAssetData(address(0)).ERC1155Assets.selector) {
assetData.transferERC1155Assets(
from,
to,
amount
);
} else if (proxyId == IAssetData(address(0)).MultiAsset.selector) {
assetData.transferMultiAsset(
from,
to,
amount
);
} else if (proxyId != IAssetData(address(0)).StaticCall.selector) {
LibRichErrors.rrevert(LibAssetDataTransferRichErrors.UnsupportedAssetProxyError(
proxyId
));
}
}
///@dev Transfer asset from sender to this contract.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param amount Amount of asset to transfer to sender.
function transferIn(
bytes memory assetData,
uint256 amount
)
internal
{
assetData.transferFrom(
msg.sender,
address(this),
amount
);
}
///@dev Transfer asset from this contract to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param amount Amount of asset to transfer to sender.
function transferOut(
bytes memory assetData,
uint256 amount
)
internal
{
assetData.transferFrom(
address(this),
msg.sender,
amount
);
}
/// @dev Decodes ERC20 or ERC20Bridge assetData and transfers given amount to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer to sender.
function transferERC20Token(
bytes memory assetData,
address from,
address to,
uint256 amount
)
internal
{
address token = assetData.readAddress(16);
// Transfer tokens.
if (from == address(this)) {
LibERC20Token.transfer(
token,
to,
amount
);
} else {
LibERC20Token.transferFrom(
token,
from,
to,
amount
);
}
}
/// @dev Decodes ERC721 assetData and transfers given amount to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer to sender.
function transferERC721Token(
bytes memory assetData,
address from,
address to,
uint256 amount
)
internal
{
if (amount != 1) {
LibRichErrors.rrevert(LibAssetDataTransferRichErrors.Erc721AmountMustEqualOneError(
amount
));
}
// Decode asset data.
address token = assetData.readAddress(16);
uint256 tokenId = assetData.readUint256(36);
// Perform transfer.
IERC721Token(token).transferFrom(
from,
to,
tokenId
);
}
/// @dev Decodes ERC1155 assetData and transfers given amounts to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer to sender.
function transferERC1155Assets(
bytes memory assetData,
address from,
address to,
uint256 amount
)
internal
{
// Decode assetData
// solhint-disable
(
address token,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) = abi.decode(
assetData.slice(4, assetData.length),
(address, uint256[], uint256[], bytes)
);
// solhint-enable
// Scale up values by `amount`
uint256 length = values.length;
uint256[] memory scaledValues = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
scaledValues[i] = values[i].safeMul(amount);
}
// Execute `safeBatchTransferFrom` call
// Either succeeds or throws
IERC1155(token).safeBatchTransferFrom(
from,
to,
ids,
scaledValues,
data
);
}
/// @dev Decodes MultiAsset assetData and recursively transfers assets to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer to sender.
function transferMultiAsset(
bytes memory assetData,
address from,
address to,
uint256 amount
)
internal
{
// solhint-disable indent
(uint256[] memory nestedAmounts, bytes[] memory nestedAssetData) = abi.decode(
assetData.slice(4, assetData.length),
(uint256[], bytes[])
);
// solhint-enable indent
uint256 numNestedAssets = nestedAssetData.length;
for (uint256 i = 0; i != numNestedAssets; i++) {
transferFrom(
nestedAssetData[i],
from,
to,
amount.safeMul(nestedAmounts[i])
);
}
}
}

View File

@@ -0,0 +1,58 @@
/*
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.9;
library LibAssetDataTransferRichErrors {
// bytes4(keccak256("UnsupportedAssetProxyError(bytes4)"))
bytes4 internal constant UNSUPPORTED_ASSET_PROXY_ERROR_SELECTOR =
0x7996a271;
// bytes4(keccak256("Erc721AmountMustEqualOneError(uint256)"))
bytes4 internal constant ERC721_AMOUNT_MUST_EQUAL_ONE_ERROR_SELECTOR =
0xbaffa474;
// solhint-disable func-name-mixedcase
function UnsupportedAssetProxyError(
bytes4 proxyId
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
UNSUPPORTED_ASSET_PROXY_ERROR_SELECTOR,
proxyId
);
}
function Erc721AmountMustEqualOneError(
uint256 amount
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
ERC721_AMOUNT_MUST_EQUAL_ONE_ERROR_SELECTOR,
amount
);
}
}

View File

@@ -39,7 +39,7 @@
},
"config": {
"publicInterfaceContracts": "IWallet,LibEIP712ExchangeDomain,LibExchangeRichErrors,LibMath,LibMathRichErrors,LibOrder,LibZeroExTransaction",
"abis": "./test/generated-artifacts/@(IWallet|LibEIP712ExchangeDomain|LibExchangeRichErrors|LibFillResults|LibMath|LibMathRichErrors|LibOrder|LibZeroExTransaction|TestLibEIP712ExchangeDomain|TestLibFillResults|TestLibMath|TestLibOrder|TestLibZeroExTransaction).json",
"abis": "./test/generated-artifacts/@(IWallet|LibAssetDataTransfer|LibAssetDataTransferRichErrors|LibEIP712ExchangeDomain|LibExchangeRichErrors|LibFillResults|LibMath|LibMathRichErrors|LibOrder|LibZeroExTransaction|TestLibEIP712ExchangeDomain|TestLibFillResults|TestLibMath|TestLibOrder|TestLibZeroExTransaction).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {

View File

@@ -8,7 +8,7 @@ export {
LibOrderContract,
LibZeroExTransactionContract,
} from './wrappers';
export { LibMathRevertErrors } from '@0x/utils';
export { LibAssetDataTransferRevertErrors, LibMathRevertErrors } from '@0x/utils';
import * as ReferenceFunctionsToExport from './reference_functions';
export import ReferenceFunctions = ReferenceFunctionsToExport;

View File

@@ -6,6 +6,8 @@
import { ContractArtifact } from 'ethereum-types';
import * as IWallet from '../test/generated-artifacts/IWallet.json';
import * as LibAssetDataTransfer from '../test/generated-artifacts/LibAssetDataTransfer.json';
import * as LibAssetDataTransferRichErrors from '../test/generated-artifacts/LibAssetDataTransferRichErrors.json';
import * as LibEIP712ExchangeDomain from '../test/generated-artifacts/LibEIP712ExchangeDomain.json';
import * as LibExchangeRichErrors from '../test/generated-artifacts/LibExchangeRichErrors.json';
import * as LibFillResults from '../test/generated-artifacts/LibFillResults.json';
@@ -20,6 +22,8 @@ import * as TestLibOrder from '../test/generated-artifacts/TestLibOrder.json';
import * as TestLibZeroExTransaction from '../test/generated-artifacts/TestLibZeroExTransaction.json';
export const artifacts = {
IWallet: IWallet as ContractArtifact,
LibAssetDataTransfer: LibAssetDataTransfer as ContractArtifact,
LibAssetDataTransferRichErrors: LibAssetDataTransferRichErrors as ContractArtifact,
LibEIP712ExchangeDomain: LibEIP712ExchangeDomain as ContractArtifact,
LibExchangeRichErrors: LibExchangeRichErrors as ContractArtifact,
LibFillResults: LibFillResults as ContractArtifact,

View File

@@ -4,6 +4,8 @@
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/i_wallet';
export * from '../test/generated-wrappers/lib_asset_data_transfer';
export * from '../test/generated-wrappers/lib_asset_data_transfer_rich_errors';
export * from '../test/generated-wrappers/lib_e_i_p712_exchange_domain';
export * from '../test/generated-wrappers/lib_exchange_rich_errors';
export * from '../test/generated-wrappers/lib_fill_results';

View File

@@ -11,6 +11,8 @@
"generated-artifacts/LibOrder.json",
"generated-artifacts/LibZeroExTransaction.json",
"test/generated-artifacts/IWallet.json",
"test/generated-artifacts/LibAssetDataTransfer.json",
"test/generated-artifacts/LibAssetDataTransferRichErrors.json",
"test/generated-artifacts/LibEIP712ExchangeDomain.json",
"test/generated-artifacts/LibExchangeRichErrors.json",
"test/generated-artifacts/LibFillResults.json",