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
2 changes: 1 addition & 1 deletion contracts/core/extensions/CoreIssuance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ contract CoreIssuance is
state.vaultAddress
);

// Log transfer of component from issuer waller
// Log transfer of component from issuer wallet
emit IssuanceComponentDeposited(
_setAddress,
component,
Expand Down
9 changes: 4 additions & 5 deletions contracts/core/extensions/CoreIssuanceOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ contract CoreIssuanceOrder is
// Settle Order
settleOrder(order, _fillQuantity, _orderData);

//Issue Set
// Issue Set
issueInternal(
order.makerAddress,
order.setAddress,
Expand Down Expand Up @@ -364,7 +364,7 @@ contract CoreIssuanceOrder is
);

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

//Send fees to relayer
ITransferProxy(state.transferProxyAddress).transfer(
Expand Down Expand Up @@ -412,8 +412,7 @@ contract CoreIssuanceOrder is
uint[] memory requiredBalances = new uint[](_order.requiredComponents.length);

// Calculate amount of maker token required
// Look into rounding errors
uint requiredMakerTokenAmount = _order.makerTokenAmount.mul(_fillQuantity).div(_order.quantity);
uint requiredMakerTokenAmount = OrderLibrary.getPartialAmount(_order.makerTokenAmount, _fillQuantity, _order.quantity);

// Calculate amount of component tokens required to issue
for (uint16 i = 0; i < _order.requiredComponents.length; i++) {
Expand All @@ -424,7 +423,7 @@ contract CoreIssuanceOrder is
);

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

// Required vault balances after exchange order executed
requiredBalances[i] = tokenBalance.add(requiredAddition);
Expand Down
25 changes: 25 additions & 0 deletions contracts/core/lib/OrderLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

pragma solidity 0.4.24;

import { SafeMath } from "zeppelin-solidity/contracts/math/SafeMath.sol";


/**
* @title OrderLibrary
Expand All @@ -26,6 +28,10 @@ pragma solidity 0.4.24;
*/

library OrderLibrary {
using SafeMath for uint256;

/* ============ Constants ============ */
string constant ROUNDING_ERROR_TOO_LARGE = "Rounding error too large.";

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

Expand Down Expand Up @@ -137,4 +143,23 @@ library OrderLibrary {

return recAddress == _signerAddress;
}

function getPartialAmount(
uint principal,
uint numerator,
uint denominator
)
internal
returns (uint256)
{
uint remainder = mulmod(principal, numerator, denominator);
if (remainder == 0) {
return principal.mul(numerator).div(denominator);
}

uint errPercentageTimes1000000 = remainder.mul(1000000).div(numerator.mul(principal));

require(errPercentageTimes1000000 < 1000, ROUNDING_ERROR_TOO_LARGE);
return principal.mul(numerator).div(denominator);
}
}
20 changes: 20 additions & 0 deletions test/contracts/core/extensions/coreIssuanceOrder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,26 @@ contract('CoreIssuanceOrder', accounts => {
await expectRevertError(subject());
});
});

describe("when rounding error is too large", async () => {
before(async () => {
orderQuantity = ether(6);
makerTokenAmount = new BigNumber(10);
});

beforeEach(async () => {
subjectQuantityToIssue = ether(4);
});

after(async () => {
orderQuantity = undefined;
makerTokenAmount = undefined;
});

it("should revert", async () => {
await expectRevertError(subject());
});
});
});

describe('#cancelOrder', async () => {
Expand Down
Loading