contract PayTakerTransformer is
    Transformer
{
    // solhint-disable no-empty-blocks
    using LibRichErrorsV06 for bytes;
    using LibSafeMathV06 for uint256;
    using LibERC20Transformer for IERC20TokenV06;

    /// @dev Transform data to ABI-encode and pass into `transform()`.
    struct TransformData {
        // The tokens to transfer to the taker.
        IERC20TokenV06[] tokens;
        // Amount of each token in `tokens` to transfer to the taker.
        // `uint(-1)` will transfer the entire balance.
        uint256[] amounts;
    }

    /// @dev Maximum uint256 value.
    uint256 private constant MAX_UINT256 = uint256(-1);

    /// @dev Create this contract.
    constructor()
        public
        Transformer()
    {}

    /// @dev Forwards tokens to the taker.
    /// @param taker The taker address (caller of `TransformERC20.transformERC20()`).
    /// @param data_ ABI-encoded `TransformData`, indicating which tokens to transfer.
    /// @return success The success bytes (`LibERC20Transformer.TRANSFORMER_SUCCESS`).
    function transform(
        bytes32, // callDataHash,
        address payable taker,
        bytes calldata data_
    )
        external
        override
        returns (bytes4 success)
    {
        TransformData memory data = abi.decode(data_, (TransformData));

        // Transfer tokens directly to the taker.
        for (uint256 i = 0; i < data.tokens.length; ++i) {
            // The `amounts` array can be shorter than the `tokens` array.
            // Missing elements are treated as `uint256(-1)`.
            uint256 amount = data.amounts.length > i ? data.amounts[i] : uint256(-1);
            if (amount == MAX_UINT256) {
                amount = data.tokens[i].getTokenBalanceOf(address(this));
            }
            if (amount != 0) {
                data.tokens[i].transformerTransfer(taker, amount);
            }
        }
        return LibERC20Transformer.TRANSFORMER_SUCCESS;
    }
}
/// @dev A transformer that transfers tokens to the taker.
function transform(
    bytes32, // callDataHash,
    address payable taker,
    bytes calldata data_
)
    external
    override
    returns (bytes4 success)
{
    TransformData memory data = abi.decode(data_, (TransformData));

    // Transfer tokens directly to the taker.
    for (uint256 i = 0; i < data.tokens.length; ++i) {
        // The `amounts` array can be shorter than the `tokens` array.
        // Missing elements are treated as `uint256(-1)`.
        uint256 amount = data.amounts.length > i ? data.amounts[i] : uint256(-1);
        if (amount == MAX_UINT256) {
            amount = data.tokens[i].getTokenBalanceOf(address(this));
        }
        if (amount != 0) {
            data.tokens[i].transformerTransfer(taker, amount);
        }
    }
    return LibERC20Transformer.TRANSFORMER_SUCCESS;
}

/// @dev Forwards tokens to the taker.
/// @param taker The taker address (caller of `TransformERC20.transformERC20()`).
/// @param data_ ABI-encoded `TransformData`, indicating which tokens to transfer.
/// @return success The success bytes (`LibERC20Transformer.TRANSFORMER_SUCCESS`).