DevUtils.sol: Upgrade for v3 (#2161)

* Exhibit bug in getSimulatedOrderTransferResults

* Fix getSimulatedOrderTransferResults

* dev-utils/package.json: add quantify_bytecode cmd

* Fix typo in log message

* Reduce compiler optimization runs

In order to reduce the EVM bytecode object length of the DevUtils
contract to be under the EIP-170 limit of 24 KB.
This commit is contained in:
F. Eugene Aumson 2019-09-18 19:36:06 -04:00 committed by GitHub
parent 549697dc47
commit bca8c5eccc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 64 additions and 7 deletions

View File

@ -7,7 +7,7 @@
"evmVersion": "constantinople", "evmVersion": "constantinople",
"optimizer": { "optimizer": {
"enabled": true, "enabled": true,
"runs": 1000000, "runs": 10000,
"details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true } "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
}, },
"outputSelection": { "outputSelection": {

View File

@ -24,6 +24,7 @@ import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange/contracts/src/libs/LibExchangeRichErrorDecoder.sol"; import "@0x/contracts-exchange/contracts/src/libs/LibExchangeRichErrorDecoder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibExchangeRichErrors.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibExchangeRichErrors.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol"; import "@0x/contracts-utils/contracts/src/LibBytes.sol";
@ -66,6 +67,13 @@ contract OrderTransferSimulationUtils is
public public
returns (OrderTransferResults orderTransferResults) returns (OrderTransferResults orderTransferResults)
{ {
LibFillResults.FillResults memory fillResults = LibFillResults.calculateFillResults(
order,
takerAssetFillAmount,
_EXCHANGE.protocolFeeMultiplier(),
tx.gasprice
);
// Create input arrays // Create input arrays
bytes[] memory assetData = new bytes[](4); bytes[] memory assetData = new bytes[](4);
address[] memory fromAddresses = new address[](4); address[] memory fromAddresses = new address[](4);
@ -76,25 +84,25 @@ contract OrderTransferSimulationUtils is
assetData[0] = order.takerAssetData; assetData[0] = order.takerAssetData;
fromAddresses[0] = takerAddress; fromAddresses[0] = takerAddress;
toAddresses[0] = order.makerAddress; toAddresses[0] = order.makerAddress;
amounts[0] = order.takerAssetAmount; amounts[0] = takerAssetFillAmount;
// Transfer `makerAsset` from maker to taker // Transfer `makerAsset` from maker to taker
assetData[1] = order.makerAssetData; assetData[1] = order.makerAssetData;
fromAddresses[1] = order.makerAddress; fromAddresses[1] = order.makerAddress;
toAddresses[1] = takerAddress; toAddresses[1] = takerAddress;
amounts[1] = order.makerAssetAmount; amounts[1] = fillResults.makerAssetFilledAmount;
// Transfer `takerFeeAsset` from taker to feeRecipient // Transfer `takerFeeAsset` from taker to feeRecipient
assetData[2] = order.takerFeeAssetData; assetData[2] = order.takerFeeAssetData;
fromAddresses[2] = takerAddress; fromAddresses[2] = takerAddress;
toAddresses[2] = order.feeRecipientAddress; toAddresses[2] = order.feeRecipientAddress;
amounts[2] = order.takerFee; amounts[2] = fillResults.takerFeePaid;
// Transfer `makerFeeAsset` from maker to feeRecipient // Transfer `makerFeeAsset` from maker to feeRecipient
assetData[3] = order.makerFeeAssetData; assetData[3] = order.makerFeeAssetData;
fromAddresses[3] = order.makerAddress; fromAddresses[3] = order.makerAddress;
toAddresses[3] = order.feeRecipientAddress; toAddresses[3] = order.feeRecipientAddress;
amounts[3] = order.makerFee; amounts[3] = fillResults.makerFeePaid;
// Encode data for `simulateDispatchTransferFromCalls(assetData, fromAddresses, toAddresses, amounts)` // Encode data for `simulateDispatchTransferFromCalls(assetData, fromAddresses, toAddresses, amounts)`
bytes memory simulateDispatchTransferFromCallsData = abi.encodeWithSelector( bytes memory simulateDispatchTransferFromCallsData = abi.encodeWithSelector(

View File

@ -12,7 +12,7 @@
"scripts": { "scripts": {
"build": "yarn pre_build && tsc -b", "build": "yarn pre_build && tsc -b",
"build:ci": "yarn build", "build:ci": "yarn build",
"pre_build": "run-s compile contracts:gen generate_contract_wrappers", "pre_build": "run-s compile quantify_bytecode contracts:gen generate_contract_wrappers",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild_and_test": "run-s build test", "rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
@ -32,6 +32,7 @@
"test:circleci": "yarn test", "test:circleci": "yarn test",
"contracts:gen": "contracts-gen", "contracts:gen": "contracts-gen",
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol", "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
"quantify_bytecode": "echo EVM bytecode object lengths:;for i in ./generated-artifacts/*.json; do node -e \"console.log('$i\t' + (require('$i').compilerOutput.evm.bytecode.object.length - 2) / 2)\"; done",
"compile:truffle": "truffle compile" "compile:truffle": "truffle compile"
}, },
"config": { "config": {

View File

@ -551,6 +551,42 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
); );
expect(orderTransferResults).to.equal(OrderTransferResults.TransfersSuccessful); expect(orderTransferResults).to.equal(OrderTransferResults.TransfersSuccessful);
}); });
it('should return TransfersSuccessful for a partial fill when taker has ample assets for the fill but not for the whole order', async () => {
await erc20Token2.setBalance.awaitTransactionSuccessAsync(
takerAddress,
signedOrder.takerAssetAmount.dividedBy(2),
{
from: owner,
},
);
await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
from: takerAddress,
});
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount, {
from: owner,
});
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
from: makerAddress,
});
await feeErc20Token.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerFee, {
from: owner,
});
await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerFee, {
from: takerAddress,
});
await feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee, {
from: owner,
});
await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
from: makerAddress,
});
const orderTransferResults = await devUtils.getSimulatedOrderTransferResults.callAsync(
signedOrder,
takerAddress,
signedOrder.takerAssetAmount.dividedBy(2),
);
expect(orderTransferResults).to.equal(OrderTransferResults.TransfersSuccessful);
});
}); });
describe('getSimulatedOrdersTransferResults', async () => { describe('getSimulatedOrdersTransferResults', async () => {
it('should simulate the transfers of each order independently from one another', async () => { it('should simulate the transfers of each order independently from one another', async () => {

View File

@ -36,4 +36,16 @@ contract IProtocolFees {
/// @param updatedProtocolFeeCollector The updated protocolFeeCollector contract address. /// @param updatedProtocolFeeCollector The updated protocolFeeCollector contract address.
function setProtocolFeeCollectorAddress(address updatedProtocolFeeCollector) function setProtocolFeeCollectorAddress(address updatedProtocolFeeCollector)
external; external;
/// @dev Returns the protocolFeeMultiplier
function protocolFeeMultiplier()
external
view
returns (uint256);
/// @dev Returns the protocolFeeCollector address
function protocolFeeCollector()
external
view
returns (address);
} }

View File

@ -41,7 +41,7 @@ if (allArtifactPaths.length < pkgNames.length) {
throw new Error( throw new Error(
`Expected ${pkgNames.length} artifacts, found ${ `Expected ${pkgNames.length} artifacts, found ${
allArtifactPaths.length allArtifactPaths.length
}. Please ensure artifacts are present in ${contractsPath}/**/generated_artifacts`, }. Please ensure artifacts are present in ${contractsPath}/**/generated-artifacts`,
); );
} }