Skip to content
This repository was archived by the owner on Jan 18, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 134 additions & 26 deletions contracts/core/extensions/CoreIssuanceOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import { CoreModifiers } from "../lib/CoreSharedModifiers.sol";
import { CoreState } from "../lib/CoreState.sol";
import { ExchangeHandler } from "../lib/ExchangeHandler.sol";
import { ICoreIssuance } from "../interfaces/ICoreIssuance.sol";
import { IExchange } from "../interfaces/IExchange.sol";
import { ITransferProxy } from "../interfaces/ITransferProxy.sol";
import { IVault } from "../interfaces/IVault.sol";
import { ISetToken } from "../interfaces/ISetToken.sol";
import { LibBytes } from "../../external/0x/LibBytes.sol";
import { OrderLibrary } from "../lib/OrderLibrary.sol";
Expand Down Expand Up @@ -72,18 +75,20 @@ contract CoreIssuanceOrder is
function fillOrder(
address[5] _addresses,
uint[5] _values,
address[] _requiredComponents,
uint[] _requiredComponentAmounts,
uint _fillQuantity,
uint8 _v,
bytes32[] sigBytes,
bytes _orderData
)
external
isValidSet(_addresses[0])
isPositiveQuantity(_fillQuantity)
{
OrderLibrary.IssuanceOrder memory order = OrderLibrary.IssuanceOrder({
setAddress: _addresses[0],
quantity: _values[0],
requiredComponents: _requiredComponents,
requiredComponentAmounts: _requiredComponentAmounts,
makerAddress: _addresses[1],
makerToken: _addresses[2],
makerTokenAmount: _values[1],
Expand All @@ -94,7 +99,9 @@ contract CoreIssuanceOrder is
salt: _values[4],
orderHash: OrderLibrary.generateOrderHash(
_addresses,
_values
_values,
_requiredComponents,
_requiredComponentAmounts
)
});

Expand All @@ -116,26 +123,15 @@ contract CoreIssuanceOrder is
_fillQuantity
);

// Execute exchange orders
executeExchangeOrders(_orderData);

// Check to make sure open order amount equals _fillQuantity
uint closedOrderAmount = state.orderFills[order.orderHash].add(state.orderCancels[order.orderHash]);
uint openOrderAmount = order.quantity.sub(closedOrderAmount);
require(
openOrderAmount >= _fillQuantity,
INVALID_FILL_AMOUNT
);

// Tally fill in orderFills mapping
state.orderFills[order.orderHash] = state.orderFills[order.orderHash].add(_fillQuantity);
// Settle Order
settleOrder(order, _fillQuantity, _orderData);

//Issue Set
issueInternal(
order.makerAddress,
order.setAddress,
_fillQuantity
);
// issueInternal(
// order.makerAddress,
// order.setAddress,
// _fillQuantity
// );
}

/**
Expand All @@ -148,6 +144,8 @@ contract CoreIssuanceOrder is
function cancelOrder(
address[5] _addresses,
uint[5] _values,
address[] _requiredComponents,
uint[] _requiredComponentAmounts,
uint _cancelQuantity
)
external
Expand All @@ -156,6 +154,8 @@ contract CoreIssuanceOrder is
OrderLibrary.IssuanceOrder memory order = OrderLibrary.IssuanceOrder({
setAddress: _addresses[0],
quantity: _values[0],
requiredComponents: _requiredComponents,
requiredComponentAmounts: _requiredComponentAmounts,
makerAddress: _addresses[1],
makerToken: _addresses[2],
makerTokenAmount: _values[1],
Expand All @@ -166,7 +166,9 @@ contract CoreIssuanceOrder is
salt: _values[4],
orderHash: OrderLibrary.generateOrderHash(
_addresses,
_values
_values,
_requiredComponents,
_requiredComponentAmounts
)
});

Expand Down Expand Up @@ -198,11 +200,14 @@ contract CoreIssuanceOrder is
* @param _orderData Bytes array containing the exchange orders to execute
*/
function executeExchangeOrders(
bytes _orderData
bytes _orderData,
address _makerAddress
)
private
returns (uint256)
{
uint256 scannedBytes;
uint256 makerTokenUsed;
while (scannedBytes < _orderData.length) {
// Read the next exchange order header
bytes memory headerData = LibBytes.slice(
Expand Down Expand Up @@ -231,19 +236,28 @@ contract CoreIssuanceOrder is
scannedBytes.add(exchangeDataLength)
);

// TODO: Transfer header.makerToken to Exchange
// Transfer header.makerTokenAmount to Exchange Wrapper
ITransferProxy(state.transferProxyAddress).transfer(
header.makerTokenAddress,
header.makerTokenAmount,
_makerAddress,
exchange
);

// TODO: Call Exchange
//Call Exchange
//IExchange(header.exchange).exchange(orderBody);

// Update scanned bytes with header and body lengths
scannedBytes = scannedBytes.add(exchangeDataLength);
makerTokenUsed += header.makerTokenAmount;
}
return makerTokenUsed;
}

/**
* Validate order params are still valid
*
* @param _order IssuanceOrder object containing order params
* @param _order IssuanceOrder object containing order params
* @param _executeQuantity Quantity of Set to be filled
*/
function validateOrder(
Expand All @@ -252,6 +266,8 @@ contract CoreIssuanceOrder is
)
private
view
isValidSet(_order.setAddress)
isPositiveQuantity(_executeQuantity)
{
// Make sure makerTokenAmount and Set Token to issue is greater than 0.
require(
Expand All @@ -276,4 +292,96 @@ contract CoreIssuanceOrder is
INVALID_QUANTITY
);
}

function settleAccounts(
OrderLibrary.IssuanceOrder _order,
uint _fillQuantity,
uint _requiredMakerTokenAmount,
uint _makerTokenUsed
)
private
{
// Calculate amount to send to taker
uint toTaker = _requiredMakerTokenAmount.sub(_makerTokenUsed);

// Send left over maker token balance to taker
ITransferProxy(state.transferProxyAddress).transfer(
_order.makerToken,
toTaker,
_order.makerAddress,
msg.sender
);

// Calculate fees required
uint requiredFees = _order.relayerTokenAmount.mul(_fillQuantity).div(_order.quantity);

//Send fees to relayer
ITransferProxy(state.transferProxyAddress).transfer(
_order.relayerToken,
requiredFees,
_order.makerAddress,
_order.relayerAddress
);
ITransferProxy(state.transferProxyAddress).transfer(
_order.relayerToken,
requiredFees,
msg.sender,
_order.relayerAddress
);
}

function settleOrder(
OrderLibrary.IssuanceOrder _order,
uint _fillQuantity,
bytes _orderData
)
private
{
// Check to make sure open order amount equals _fillQuantity
uint closedOrderAmount = state.orderFills[_order.orderHash].add(state.orderCancels[_order.orderHash]);
uint openOrderAmount = _order.quantity.sub(closedOrderAmount);
require(
openOrderAmount >= _fillQuantity,
INVALID_FILL_AMOUNT
);

uint[] memory requiredBalances = new uint[](_order.requiredComponents.length);

// Calculate amount of maker token required
// Look into rounding errors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to tech debt

uint requiredMakerTokenAmount = _order.makerTokenAmount.mul(_fillQuantity).div(_order.quantity);

// Calculate amount of component tokens required to issue
for (uint16 i = 0; i < _order.requiredComponents.length; i++) {
// Get current vault balances
uint tokenBalance = IVault(state.vaultAddress).getOwnerBalance(
_order.makerAddress,
_order.requiredComponents[i]
);

// Amount of component tokens to be added to Vault
uint requiredAddition = _order.requiredComponentAmounts[i].mul(_fillQuantity).div(_order.quantity);

// Required vault balances after exchange order executed
requiredBalances[i] = tokenBalance.add(requiredAddition);
}

// Execute exchange orders
uint makerTokenAmountUsed = executeExchangeOrders(_orderData, _order.makerAddress);
require(makerTokenAmountUsed <= requiredMakerTokenAmount);

// Check that maker's component tokens in Vault have been incremented correctly
for (i = 0; i < _order.requiredComponents.length; i++) {
uint currentBal = IVault(state.vaultAddress).getOwnerBalance(
_order.makerAddress,
_order.requiredComponents[i]
);
//require(currentBal >= requiredBalances[i]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pending taker wallet exchange I assume?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Si

}

settleAccounts(_order, _fillQuantity, requiredMakerTokenAmount, makerTokenAmountUsed);

// Tally fill in orderFills mapping
state.orderFills[_order.orderHash] = state.orderFills[_order.orderHash].add(_fillQuantity);
}
}
72 changes: 48 additions & 24 deletions contracts/core/lib/OrderLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,36 @@ library OrderLibrary {

/* ============ Structs ============ */

/**
* Struct containing all parameters for the issuance order
*
* @param setAddress Set the maker wants to mint
* @param quantity Amount of Sets maker is looking to mint
* @param requiredComponents Components to be acquired by taker's exchange orders
* @param requiredComponentAmounts Amounts of each component to be acquired by exchange order
* @param makerAddress Address of maker of the Issuance Order
* @param makerToken Address of token maker wants to exchange for filling issuance order
* @param makerTokenAmount Amount of makerToken to be used to fill the order
* @param expiration Timestamp marking when the order expires
* @param relayerAddress Address of relayer
* @param relayerTokenAmount Token relayer wants to be compensated in
* @param relayerTokenAmount Amount of tokens relayer wants to be compensated
* @param salt Random number used to create unique orderHash
* @param orderHash Unique order identifier used to log information about the order in the protocol
*/
struct IssuanceOrder {
address setAddress; // _addresses[0]
uint256 quantity; // _values[0]
address makerAddress; // _addresses[1]
address makerToken; // _addresses[2]
uint256 makerTokenAmount; // _values[1]
uint256 expiration; // _values[2]
address relayerAddress; // _addresses[3]
address relayerToken; // _addresses[4]
uint256 relayerTokenAmount; // _values[3]
uint256 salt; // _values[4]
address setAddress; // _addresses[0]
uint256 quantity; // _values[0]
address[] requiredComponents; // _requiredComponents
uint[] requiredComponentAmounts; // _requiredComponentAmounts
address makerAddress; // _addresses[1]
address makerToken; // _addresses[2]
uint256 makerTokenAmount; // _values[1]
uint256 expiration; // _values[2]
address relayerAddress; // _addresses[3]
address relayerToken; // _addresses[4]
uint256 relayerTokenAmount; // _values[3]
uint256 salt; // _values[4]
bytes32 orderHash;
}

Expand All @@ -48,12 +67,16 @@ library OrderLibrary {
/**
* Create hash of order parameters
*
* @param _addresses [setAddress, makerAddress, makerToken, relayerAddress, relayerToken]
* @param _values [quantity, makerTokenAmount, expiration, relayerTokenAmount, salt]
* @param _addresses [setAddress, makerAddress, makerToken, relayerAddress, relayerToken]
* @param _values [quantity, makerTokenAmount, expiration, relayerTokenAmount, salt]
* @param _requiredComponents Components to be acquired by exchange order
* @param _requiredComponentAmounts Amounts of each component to be acquired by exchange order
*/
function generateOrderHash(
address[5] _addresses,
uint[5] _values
uint[5] _values,
address[] _requiredComponents,
uint[] _requiredComponentAmounts
)
internal
pure
Expand All @@ -62,16 +85,18 @@ library OrderLibrary {
// Hash the order parameters
return keccak256(
abi.encodePacked(
_addresses[0], // setAddress
_addresses[1], // makerAddress
_addresses[2], // makerToken
_addresses[3], // relayerAddress
_addresses[4], // relayerToken
_values[0], // quantity
_values[1], // makerTokenAmount
_values[2], // expiration
_values[3], // relayerTokenAmount
_values[4] // salt
_addresses[0], // setAddress
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add descriptions to each of these?

_addresses[1], // makerAddress
_addresses[2], // makerToken
_addresses[3], // relayerAddress
_addresses[4], // relayerToken
_values[0], // quantity
_values[1], // makerTokenAmount
_values[2], // expiration
_values[3], // relayerTokenAmount
_values[4], // salt
_requiredComponents, // _requiredComponents
_requiredComponentAmounts // _requiredComponentAmounts
)
);
}
Expand Down Expand Up @@ -112,5 +137,4 @@ library OrderLibrary {

return recAddress == _signerAddress;
}

}
8 changes: 6 additions & 2 deletions contracts/mocks/core/lib/OrderLibraryMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ import { OrderLibrary } from "../../../core/lib/OrderLibrary.sol";
contract OrderLibraryMock {
function testGenerateOrderHash(
address[5] _addresses,
uint[5] _values
uint[5] _values,
address[] _requiredComponents,
uint[] _requiredComponentAmounts
)
public
pure
returns(bytes32)
{
return OrderLibrary.generateOrderHash(
_addresses,
_values
_values,
_requiredComponents,
_requiredComponentAmounts
);
}

Expand Down
Loading