Merge pull request #1714 from 0xProject/feature/order-utils/one-sided-transfer-validation
Simulate Maker transfer in order validation
This commit is contained in:
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Added UntransferrableDummyERC20Token",
|
||||
"pr": 1714
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.0",
|
||||
"changes": [
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"src/interfaces/IEtherToken.sol",
|
||||
"test/DummyERC20Token.sol",
|
||||
"test/DummyMultipleReturnERC20Token.sol",
|
||||
"test/DummyNoReturnERC20Token.sol"
|
||||
"test/DummyNoReturnERC20Token.sol",
|
||||
"test/UntransferrableDummyERC20Token.sol"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 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.5;
|
||||
|
||||
import "./DummyERC20Token.sol";
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract UntransferrableDummyERC20Token is
|
||||
DummyERC20Token
|
||||
{
|
||||
constructor (
|
||||
string memory _name,
|
||||
string memory _symbol,
|
||||
uint256 _decimals,
|
||||
uint256 _totalSupply
|
||||
)
|
||||
public
|
||||
DummyERC20Token(
|
||||
_name,
|
||||
_symbol,
|
||||
_decimals,
|
||||
_totalSupply
|
||||
)
|
||||
{}
|
||||
|
||||
/// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
require(
|
||||
false,
|
||||
"TRANSFER_DISABLED"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "4.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Added IAssetProxy wrapper",
|
||||
"pr": 1714
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "4.1.0",
|
||||
"changes": [
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output src/generated-wrappers --backend ethers"
|
||||
},
|
||||
"config": {
|
||||
"abis": "../contract-artifacts/artifacts/@(AssetProxyOwner|DutchAuction|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC20Token|ERC721Proxy|ERC721Token|Exchange|Forwarder|IValidator|IWallet|MultiAssetProxy|OrderValidator|WETH9|ZRXToken|Coordinator|CoordinatorRegistry).json"
|
||||
"abis": "../contract-artifacts/artifacts/@(AssetProxyOwner|DutchAuction|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC20Token|ERC721Proxy|ERC721Token|Exchange|Forwarder|IAssetProxy|IValidator|IWallet|MultiAssetProxy|OrderValidator|WETH9|ZRXToken|Coordinator|CoordinatorRegistry).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -0,0 +1,534 @@
|
||||
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma whitespace class-name
|
||||
// tslint:disable:no-unused-variable
|
||||
// tslint:disable:no-unbound-method
|
||||
import { BaseContract } from '@0x/base-contract';
|
||||
import { BlockParam, BlockParamLiteral, CallData, ContractAbi, ContractArtifact, DecodedLogArgs, MethodAbi, TxData, TxDataPayable, SupportedProvider } from 'ethereum-types';
|
||||
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
|
||||
import { SimpleContractArtifact } from '@0x/types';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as ethers from 'ethers';
|
||||
import * as _ from 'lodash';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class IAssetProxyContract extends BaseContract {
|
||||
public addAuthorizedAddress = {
|
||||
async sendTransactionAsync(
|
||||
target: string,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<string> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('addAuthorizedAddress(address)', [target
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.addAuthorizedAddress.estimateGasAsync.bind(
|
||||
self,
|
||||
target
|
||||
),
|
||||
);
|
||||
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
async estimateGasAsync(
|
||||
target: string,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<number> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('addAuthorizedAddress(address)', [target
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
target: string,
|
||||
): string {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('addAuthorizedAddress(address)', [target
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
async callAsync(
|
||||
target: string,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('addAuthorizedAddress(address)', [target
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
};
|
||||
public removeAuthorizedAddress = {
|
||||
async sendTransactionAsync(
|
||||
target: string,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<string> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('removeAuthorizedAddress(address)', [target
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.removeAuthorizedAddress.estimateGasAsync.bind(
|
||||
self,
|
||||
target
|
||||
),
|
||||
);
|
||||
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
async estimateGasAsync(
|
||||
target: string,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<number> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('removeAuthorizedAddress(address)', [target
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
target: string,
|
||||
): string {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('removeAuthorizedAddress(address)', [target
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
async callAsync(
|
||||
target: string,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('removeAuthorizedAddress(address)', [target
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
};
|
||||
public removeAuthorizedAddressAtIndex = {
|
||||
async sendTransactionAsync(
|
||||
target: string,
|
||||
index: BigNumber,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<string> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('removeAuthorizedAddressAtIndex(address,uint256)', [target,
|
||||
index
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.removeAuthorizedAddressAtIndex.estimateGasAsync.bind(
|
||||
self,
|
||||
target,
|
||||
index
|
||||
),
|
||||
);
|
||||
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
async estimateGasAsync(
|
||||
target: string,
|
||||
index: BigNumber,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<number> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('removeAuthorizedAddressAtIndex(address,uint256)', [target,
|
||||
index
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
target: string,
|
||||
index: BigNumber,
|
||||
): string {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('removeAuthorizedAddressAtIndex(address,uint256)', [target,
|
||||
index
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
async callAsync(
|
||||
target: string,
|
||||
index: BigNumber,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('removeAuthorizedAddressAtIndex(address,uint256)', [target,
|
||||
index
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
};
|
||||
public transferFrom = {
|
||||
async sendTransactionAsync(
|
||||
assetData: string,
|
||||
from: string,
|
||||
to: string,
|
||||
amount: BigNumber,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<string> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('transferFrom(bytes,address,address,uint256)', [assetData,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.transferFrom.estimateGasAsync.bind(
|
||||
self,
|
||||
assetData,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
),
|
||||
);
|
||||
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
async estimateGasAsync(
|
||||
assetData: string,
|
||||
from: string,
|
||||
to: string,
|
||||
amount: BigNumber,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<number> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('transferFrom(bytes,address,address,uint256)', [assetData,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
assetData: string,
|
||||
from: string,
|
||||
to: string,
|
||||
amount: BigNumber,
|
||||
): string {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('transferFrom(bytes,address,address,uint256)', [assetData,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
async callAsync(
|
||||
assetData: string,
|
||||
from: string,
|
||||
to: string,
|
||||
amount: BigNumber,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('transferFrom(bytes,address,address,uint256)', [assetData,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('transferFrom(bytes,address,address,uint256)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
};
|
||||
public getProxyId = {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<string
|
||||
> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('getProxyId()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('getProxyId()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<string
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
};
|
||||
public getAuthorizedAddresses = {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<string[]
|
||||
> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('getAuthorizedAddresses()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<string[]
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
};
|
||||
public transferOwnership = {
|
||||
async sendTransactionAsync(
|
||||
newOwner: string,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<string> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.transferOwnership.estimateGasAsync.bind(
|
||||
self,
|
||||
newOwner
|
||||
),
|
||||
);
|
||||
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
async estimateGasAsync(
|
||||
newOwner: string,
|
||||
txData: Partial<TxData> = {},
|
||||
): Promise<number> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner
|
||||
]);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
newOwner: string,
|
||||
): string {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('transferOwnership(address)', [newOwner
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
async callAsync(
|
||||
newOwner: string,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
const self = this as any as IAssetProxyContract;
|
||||
const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
};
|
||||
public static async deployFrom0xArtifactAsync(
|
||||
artifact: ContractArtifact | SimpleContractArtifact,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
): Promise<IAssetProxyContract> {
|
||||
if (_.isUndefined(artifact.compilerOutput)) {
|
||||
throw new Error('Compiler output not found in the artifact file');
|
||||
}
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
return IAssetProxyContract.deployAsync(bytecode, abi, provider, txDefaults, );
|
||||
}
|
||||
public static async deployAsync(
|
||||
bytecode: string,
|
||||
abi: ContractAbi,
|
||||
supportedProvider: SupportedProvider,
|
||||
txDefaults: Partial<TxData>,
|
||||
): Promise<IAssetProxyContract> {
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
|
||||
[] = BaseContract._formatABIDataItemList(
|
||||
constructorAbi.inputs,
|
||||
[],
|
||||
BaseContract._bigNumberToString,
|
||||
);
|
||||
const iface = new ethers.utils.Interface(abi);
|
||||
const deployInfo = iface.deployFunction;
|
||||
const txData = deployInfo.encode(bytecode, []);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{data: txData},
|
||||
txDefaults,
|
||||
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
|
||||
);
|
||||
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
logUtils.log(`transactionHash: ${txHash}`);
|
||||
const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
logUtils.log(`IAssetProxy successfully deployed at ${txReceipt.contractAddress}`);
|
||||
const contractInstance = new IAssetProxyContract(abi, txReceipt.contractAddress as string, provider, txDefaults);
|
||||
contractInstance.constructorArgs = [];
|
||||
return contractInstance;
|
||||
}
|
||||
constructor(abi: ContractAbi, address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
|
||||
super('IAssetProxy', abi, address, supportedProvider, txDefaults);
|
||||
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', 'abi', '_web3Wrapper']);
|
||||
}
|
||||
} // tslint:disable:max-file-line-count
|
||||
// tslint:enable:no-unbound-method
|
||||
@@ -8,6 +8,7 @@ export * from './generated-wrappers/erc721_proxy';
|
||||
export * from './generated-wrappers/erc721_token';
|
||||
export * from './generated-wrappers/exchange';
|
||||
export * from './generated-wrappers/forwarder';
|
||||
export * from './generated-wrappers/i_asset_proxy';
|
||||
export * from './generated-wrappers/i_validator';
|
||||
export * from './generated-wrappers/i_wallet';
|
||||
export * from './generated-wrappers/multi_asset_proxy';
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "6.1.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Moved order_utils into `@0x/order-utils` package as `orderCalculationUtils`",
|
||||
"pr": 1714
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1553183790,
|
||||
"version": "6.0.5",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { HttpClient } from '@0x/connect';
|
||||
import { orderCalculationUtils } from '@0x/order-utils';
|
||||
import { APIOrder, AssetPairsResponse, OrderbookResponse } from '@0x/types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@@ -10,7 +11,6 @@ import {
|
||||
SignedOrderWithRemainingFillableMakerAssetAmount,
|
||||
} from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { orderUtils } from '../utils/order_utils';
|
||||
|
||||
export class StandardRelayerAPIOrderProvider implements OrderProvider {
|
||||
public readonly apiUrl: string;
|
||||
@@ -31,7 +31,7 @@ export class StandardRelayerAPIOrderProvider implements OrderProvider {
|
||||
'remainingTakerAssetAmount',
|
||||
order.takerAssetAmount,
|
||||
);
|
||||
const remainingFillableMakerAssetAmount = orderUtils.getRemainingMakerAmount(
|
||||
const remainingFillableMakerAssetAmount = orderCalculationUtils.getMakerFillAmount(
|
||||
order,
|
||||
remainingFillableTakerAssetAmount,
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { marketUtils, SignedOrder } from '@0x/order-utils';
|
||||
import { marketUtils, orderCalculationUtils, SignedOrder } from '@0x/order-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@@ -6,8 +6,6 @@ import { constants } from '../constants';
|
||||
import { InsufficientAssetLiquidityError } from '../errors';
|
||||
import { AssetBuyerError, BuyQuote, BuyQuoteInfo, OrdersAndFillableAmounts } from '../types';
|
||||
|
||||
import { orderUtils } from './order_utils';
|
||||
|
||||
// Calculates a buy quote for orders that have WETH as the takerAsset
|
||||
export const buyQuoteCalculator = {
|
||||
calculate(
|
||||
@@ -166,7 +164,7 @@ function findEthAmountNeededToBuyZrx(
|
||||
const { totalEthAmount, remainingZrxBuyAmount } = acc;
|
||||
const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
|
||||
const makerFillAmount = BigNumber.min(remainingZrxBuyAmount, remainingFillableMakerAssetAmount);
|
||||
const [takerFillAmount, adjustedMakerFillAmount] = orderUtils.getTakerFillAmountForFeeOrder(
|
||||
const [takerFillAmount, adjustedMakerFillAmount] = orderCalculationUtils.getTakerFillAmountForFeeOrder(
|
||||
order,
|
||||
makerFillAmount,
|
||||
);
|
||||
@@ -200,8 +198,8 @@ function findEthAndZrxAmountNeededToBuyAsset(
|
||||
const { totalEthAmount, totalZrxAmount, remainingAssetBuyAmount } = acc;
|
||||
const remainingFillableMakerAssetAmount = remainingFillableMakerAssetAmounts[index];
|
||||
const makerFillAmount = BigNumber.min(acc.remainingAssetBuyAmount, remainingFillableMakerAssetAmount);
|
||||
const takerFillAmount = orderUtils.getTakerFillAmount(order, makerFillAmount);
|
||||
const takerFeeAmount = orderUtils.getTakerFeeAmount(order, takerFillAmount);
|
||||
const takerFillAmount = orderCalculationUtils.getTakerFillAmount(order, makerFillAmount);
|
||||
const takerFeeAmount = orderCalculationUtils.getTakerFeeAmount(order, takerFillAmount);
|
||||
return {
|
||||
totalEthAmount: totalEthAmount.plus(takerFillAmount),
|
||||
totalZrxAmount: totalZrxAmount.plus(takerFeeAmount),
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { orderCalculationUtils } from '@0x/order-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { LiquidityForAssetData, OrdersAndFillableAmounts } from '../types';
|
||||
|
||||
import { orderUtils } from './order_utils';
|
||||
|
||||
export const calculateLiquidity = (ordersAndFillableAmounts: OrdersAndFillableAmounts): LiquidityForAssetData => {
|
||||
const { orders, remainingFillableMakerAssetAmounts } = ordersAndFillableAmounts;
|
||||
const liquidityInBigNumbers = orders.reduce(
|
||||
@@ -14,7 +13,10 @@ export const calculateLiquidity = (ordersAndFillableAmounts: OrdersAndFillableAm
|
||||
}
|
||||
|
||||
const tokensAvailableForCurrentOrder = availableMakerAssetAmount;
|
||||
const ethValueAvailableForCurrentOrder = orderUtils.getTakerFillAmount(order, availableMakerAssetAmount);
|
||||
const ethValueAvailableForCurrentOrder = orderCalculationUtils.getTakerFillAmount(
|
||||
order,
|
||||
availableMakerAssetAmount,
|
||||
);
|
||||
return {
|
||||
tokensAvailableInBaseUnits: acc.tokensAvailableInBaseUnits.plus(tokensAvailableForCurrentOrder),
|
||||
ethValueAvailableInWei: acc.ethValueAvailableInWei.plus(ethValueAvailableForCurrentOrder),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { OrderAndTraderInfo, OrderStatus, OrderValidatorWrapper } from '@0x/contract-wrappers';
|
||||
import { sortingUtils } from '@0x/order-utils';
|
||||
import { orderCalculationUtils, sortingUtils } from '@0x/order-utils';
|
||||
import { RemainingFillableCalculator } from '@0x/order-utils/lib/src/remaining_fillable_calculator';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
@@ -14,8 +14,6 @@ import {
|
||||
SignedOrderWithRemainingFillableMakerAssetAmount,
|
||||
} from '../types';
|
||||
|
||||
import { orderUtils } from './order_utils';
|
||||
|
||||
export const orderProviderResponseProcessor = {
|
||||
throwIfInvalidResponse(response: OrderProviderResponse, request: OrderProviderRequest): void {
|
||||
const { makerAssetData, takerAssetData } = request;
|
||||
@@ -83,7 +81,10 @@ function filterOutExpiredAndNonOpenOrders(
|
||||
expiryBufferSeconds: number,
|
||||
): SignedOrderWithRemainingFillableMakerAssetAmount[] {
|
||||
const result = _.filter(orders, order => {
|
||||
return orderUtils.isOpenOrder(order) && !orderUtils.willOrderExpire(order, expiryBufferSeconds);
|
||||
return (
|
||||
orderCalculationUtils.isOpenOrder(order) &&
|
||||
!orderCalculationUtils.willOrderExpire(order, expiryBufferSeconds)
|
||||
);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
@@ -112,7 +113,10 @@ function getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
|
||||
const transferrableAssetAmount = BigNumber.min(traderInfo.makerAllowance, traderInfo.makerBalance);
|
||||
const transferrableFeeAssetAmount = BigNumber.min(traderInfo.makerZrxAllowance, traderInfo.makerZrxBalance);
|
||||
const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
|
||||
const remainingMakerAssetAmount = orderUtils.getRemainingMakerAmount(order, remainingTakerAssetAmount);
|
||||
const remainingMakerAssetAmount = orderCalculationUtils.getMakerFillAmount(
|
||||
order,
|
||||
remainingTakerAssetAmount,
|
||||
);
|
||||
const remainingFillableCalculator = new RemainingFillableCalculator(
|
||||
order.makerFee,
|
||||
order.makerAssetAmount,
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { constants } from '../constants';
|
||||
|
||||
export const orderUtils = {
|
||||
isOrderExpired(order: SignedOrder): boolean {
|
||||
return orderUtils.willOrderExpire(order, 0);
|
||||
},
|
||||
willOrderExpire(order: SignedOrder, secondsFromNow: number): boolean {
|
||||
const millisecondsInSecond = 1000;
|
||||
const currentUnixTimestampSec = new BigNumber(Date.now() / millisecondsInSecond).integerValue();
|
||||
return order.expirationTimeSeconds.isLessThan(currentUnixTimestampSec.plus(secondsFromNow));
|
||||
},
|
||||
isOpenOrder(order: SignedOrder): boolean {
|
||||
return order.takerAddress === constants.NULL_ADDRESS;
|
||||
},
|
||||
// given a remaining amount of takerAsset, calculate how much makerAsset is available
|
||||
getRemainingMakerAmount(order: SignedOrder, remainingTakerAmount: BigNumber): BigNumber {
|
||||
const remainingMakerAmount = remainingTakerAmount
|
||||
.times(order.makerAssetAmount)
|
||||
.div(order.takerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_FLOOR);
|
||||
return remainingMakerAmount;
|
||||
},
|
||||
// given a desired amount of makerAsset, calculate how much takerAsset is required to fill that amount
|
||||
getTakerFillAmount(order: SignedOrder, makerFillAmount: BigNumber): BigNumber {
|
||||
// Round up because exchange rate favors Maker
|
||||
const takerFillAmount = makerFillAmount
|
||||
.multipliedBy(order.takerAssetAmount)
|
||||
.div(order.makerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_CEIL);
|
||||
return takerFillAmount;
|
||||
},
|
||||
// given a desired amount of takerAsset to fill, calculate how much fee is required by the taker to fill that amount
|
||||
getTakerFeeAmount(order: SignedOrder, takerFillAmount: BigNumber): BigNumber {
|
||||
// Round down because Taker fee rate favors Taker
|
||||
const takerFeeAmount = takerFillAmount
|
||||
.multipliedBy(order.takerFee)
|
||||
.div(order.takerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_FLOOR);
|
||||
return takerFeeAmount;
|
||||
},
|
||||
// given a desired amount of takerAsset to fill, calculate how much makerAsset will be filled
|
||||
getMakerFillAmount(order: SignedOrder, takerFillAmount: BigNumber): BigNumber {
|
||||
// Round down because exchange rate favors Maker
|
||||
const makerFillAmount = takerFillAmount
|
||||
.multipliedBy(order.makerAssetAmount)
|
||||
.div(order.takerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_FLOOR);
|
||||
return makerFillAmount;
|
||||
},
|
||||
// given a desired amount of makerAsset, calculate how much fee is required by the maker to fill that amount
|
||||
getMakerFeeAmount(order: SignedOrder, makerFillAmount: BigNumber): BigNumber {
|
||||
// Round down because Maker fee rate favors Maker
|
||||
const makerFeeAmount = makerFillAmount
|
||||
.multipliedBy(order.makerFee)
|
||||
.div(order.makerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_FLOOR);
|
||||
return makerFeeAmount;
|
||||
},
|
||||
// given a desired amount of ZRX from a fee order, calculate how much takerAsset is required to fill that amount
|
||||
// also calculate how much ZRX needs to be bought in order fill the desired amount + takerFee
|
||||
getTakerFillAmountForFeeOrder(order: SignedOrder, makerFillAmount: BigNumber): [BigNumber, BigNumber] {
|
||||
// For each unit of TakerAsset we buy (MakerAsset - TakerFee)
|
||||
const adjustedTakerFillAmount = makerFillAmount
|
||||
.multipliedBy(order.takerAssetAmount)
|
||||
.div(order.makerAssetAmount.minus(order.takerFee))
|
||||
.integerValue(BigNumber.ROUND_CEIL);
|
||||
// The amount that we buy will be greater than makerFillAmount, since we buy some amount for fees.
|
||||
const adjustedMakerFillAmount = orderUtils.getMakerFillAmount(order, adjustedTakerFillAmount);
|
||||
return [adjustedTakerFillAmount, adjustedMakerFillAmount];
|
||||
},
|
||||
};
|
||||
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "1.5.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Added artifact for `IAssetProxy`",
|
||||
"pr": 1714
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.4.0",
|
||||
"changes": [
|
||||
|
||||
185
packages/contract-artifacts/artifacts/IAssetProxy.json
generated
Normal file
185
packages/contract-artifacts/artifacts/IAssetProxy.json
generated
Normal file
@@ -0,0 +1,185 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "IAssetProxy",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "addAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "removeAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "index",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "removeAuthorizedAddressAtIndex",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "assetData",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getProxyId",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes4"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getAuthorizedAddresses",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"linkReferences": {},
|
||||
"object": "0x",
|
||||
"opcodes": "",
|
||||
"sourceMap": ""
|
||||
},
|
||||
"deployedBytecode": {
|
||||
"linkReferences": {},
|
||||
"object": "0x",
|
||||
"opcodes": "",
|
||||
"sourceMap": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources": {
|
||||
"src/interfaces/IAssetProxy.sol": {
|
||||
"id": 2
|
||||
},
|
||||
"src/interfaces/IAuthorizable.sol": {
|
||||
"id": 3
|
||||
},
|
||||
"@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol": {
|
||||
"id": 6
|
||||
}
|
||||
},
|
||||
"sourceCodes": {
|
||||
"src/interfaces/IAssetProxy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\n\nimport \"./IAuthorizable.sol\";\n\n\ncontract IAssetProxy is\n IAuthorizable\n{\n /// @dev Transfers assets. Either succeeds or throws.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param from Address to transfer asset from.\n /// @param to Address to transfer asset to.\n /// @param amount Amount of asset to transfer.\n function transferFrom(\n bytes assetData,\n address from,\n address to,\n uint256 amount\n )\n external;\n \n /// @dev Gets the proxy id associated with the proxy address.\n /// @return Proxy id.\n function getProxyId()\n external\n pure\n returns (bytes4);\n}\n",
|
||||
"src/interfaces/IAuthorizable.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\n\nimport \"@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol\";\n\n\ncontract IAuthorizable is\n IOwnable\n{\n /// @dev Authorizes an address.\n /// @param target Address to authorize.\n function addAuthorizedAddress(address target)\n external;\n\n /// @dev Removes authorizion of an address.\n /// @param target Address to remove authorization from.\n function removeAuthorizedAddress(address target)\n external;\n\n /// @dev Removes authorizion of an address.\n /// @param target Address to remove authorization from.\n /// @param index Index of target in authorities array.\n function removeAuthorizedAddressAtIndex(\n address target,\n uint256 index\n )\n external;\n \n /// @dev Gets all authorized addresses.\n /// @return Array of authorized addresses.\n function getAuthorizedAddresses()\n external\n view\n returns (address[] memory);\n}\n",
|
||||
"@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol": "pragma solidity ^0.4.24;\n\n\ncontract IOwnable {\n\n function transferOwnership(address newOwner)\n public;\n}\n"
|
||||
},
|
||||
"sourceTreeHashHex": "0x4fe33d3b00ae85e5c1d5478eeb1bf17fdc637fa0501dc1ff6fd1f871f87c83ca",
|
||||
"compiler": {
|
||||
"name": "solc",
|
||||
"version": "0.4.25+commit.59dbf8f1.Linux.g++",
|
||||
"settings": {
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000,
|
||||
"details": {
|
||||
"yul": true,
|
||||
"deduplicate": true,
|
||||
"cse": true,
|
||||
"constantOptimizer": true
|
||||
}
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
},
|
||||
"evmVersion": "byzantium",
|
||||
"remappings": [
|
||||
"@0x/contracts-utils=/Users/jacob/projects/ethdev/0x/0x.js/contracts/asset-proxy/node_modules/@0x/contracts-utils"
|
||||
]
|
||||
}
|
||||
},
|
||||
"networks": {}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import * as ERC721Proxy from '../artifacts/ERC721Proxy.json';
|
||||
import * as ERC721Token from '../artifacts/ERC721Token.json';
|
||||
import * as Exchange from '../artifacts/Exchange.json';
|
||||
import * as Forwarder from '../artifacts/Forwarder.json';
|
||||
import * as IAssetProxy from '../artifacts/IAssetProxy.json';
|
||||
import * as IValidator from '../artifacts/IValidator.json';
|
||||
import * as IWallet from '../artifacts/IWallet.json';
|
||||
import * as MultiAssetProxy from '../artifacts/MultiAssetProxy.json';
|
||||
@@ -28,6 +29,7 @@ export {
|
||||
ERC721Token,
|
||||
Exchange,
|
||||
Forwarder,
|
||||
IAssetProxy,
|
||||
IValidator,
|
||||
IWallet,
|
||||
MultiAssetProxy,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"./artifacts/ERC721Token.json",
|
||||
"./artifacts/Exchange.json",
|
||||
"./artifacts/Forwarder.json",
|
||||
"./artifacts/IAssetProxy.json",
|
||||
"./artifacts/IValidator.json",
|
||||
"./artifacts/IWallet.json",
|
||||
"./artifacts/MultiAssetProxy.json",
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
[
|
||||
{
|
||||
"version": "9.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Added a simulation to transfer from maker to taker during `exchange.validateOrderFillableOrThrowAsync`",
|
||||
"pr": 1714
|
||||
},
|
||||
{
|
||||
"note": "Added additional properties to `ValidateOrderFillableOpts`. An order can now be validated to fill a non-zero amount by specifying `validateRemainingOrderAmountIsFillable` as `false`. The default `true` will continue to validate the entire remaining balance is fillable.",
|
||||
"pr": 1714
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1553183790,
|
||||
"version": "8.0.5",
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from '@0x/abi-gen-wrappers';
|
||||
import { Exchange } from '@0x/contract-artifacts';
|
||||
import { ExchangeContract, ExchangeEventArgs, ExchangeEvents, IAssetProxyContract } from '@0x/abi-gen-wrappers';
|
||||
import { Exchange, IAssetProxy } from '@0x/contract-artifacts';
|
||||
import { schemas } from '@0x/json-schemas';
|
||||
import {
|
||||
assetDataUtils,
|
||||
BalanceAndProxyAllowanceLazyStore,
|
||||
ExchangeTransferSimulator,
|
||||
orderCalculationUtils,
|
||||
orderHashUtils,
|
||||
OrderStateUtils,
|
||||
OrderValidationUtils,
|
||||
} from '@0x/order-utils';
|
||||
import { AssetProxyId, Order, SignedOrder } from '@0x/types';
|
||||
@@ -1139,7 +1142,8 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* Validate if the supplied order is fillable, and throw if it isn't
|
||||
* @param signedOrder SignedOrder of interest
|
||||
* @param opts ValidateOrderFillableOpts options (e.g expectedFillTakerTokenAmount.
|
||||
* If it isn't supplied, we check if the order is fillable for a non-zero amount)
|
||||
* If it isn't supplied, we check if the order is fillable for the remaining amount.
|
||||
* To check if the order is fillable for a non-zero amount, set `validateRemainingOrderAmountIsFillable` to false.)
|
||||
*/
|
||||
public async validateOrderFillableOrThrowAsync(
|
||||
signedOrder: SignedOrder,
|
||||
@@ -1155,16 +1159,77 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
);
|
||||
const balanceAllowanceStore = new BalanceAndProxyAllowanceLazyStore(balanceAllowanceFetcher);
|
||||
const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore);
|
||||
|
||||
const expectedFillTakerTokenAmountIfExists = opts.expectedFillTakerTokenAmount;
|
||||
const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
|
||||
|
||||
let fillableTakerAssetAmount;
|
||||
const shouldValidateRemainingOrderAmountIsFillable = _.isUndefined(opts.validateRemainingOrderAmountIsFillable)
|
||||
? true
|
||||
: opts.validateRemainingOrderAmountIsFillable;
|
||||
if (opts.expectedFillTakerTokenAmount) {
|
||||
// If the caller has specified a taker fill amount, we use this for all validation
|
||||
fillableTakerAssetAmount = opts.expectedFillTakerTokenAmount;
|
||||
} else if (shouldValidateRemainingOrderAmountIsFillable) {
|
||||
// Default behaviour is to validate the amount left on the order.
|
||||
const filledTakerTokenAmount = await this.getFilledTakerAssetAmountAsync(
|
||||
orderHashUtils.getOrderHashHex(signedOrder),
|
||||
);
|
||||
fillableTakerAssetAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount);
|
||||
} else {
|
||||
const orderStateUtils = new OrderStateUtils(balanceAllowanceStore, filledCancelledFetcher);
|
||||
// Calculate the taker amount fillable given the maker balance and allowance
|
||||
const orderRelevantState = await orderStateUtils.getOpenOrderRelevantStateAsync(signedOrder);
|
||||
fillableTakerAssetAmount = orderRelevantState.remainingFillableTakerAssetAmount;
|
||||
}
|
||||
|
||||
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider());
|
||||
await orderValidationUtils.validateOrderFillableOrThrowAsync(
|
||||
exchangeTradeSimulator,
|
||||
signedOrder,
|
||||
this.getZRXAssetData(),
|
||||
expectedFillTakerTokenAmountIfExists,
|
||||
fillableTakerAssetAmount,
|
||||
);
|
||||
const makerTransferAmount = orderCalculationUtils.getMakerFillAmount(signedOrder, fillableTakerAssetAmount);
|
||||
await this.validateMakerTransferThrowIfInvalidAsync(
|
||||
signedOrder,
|
||||
makerTransferAmount,
|
||||
opts.simulationTakerAddress,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Validate the transfer from the maker to the taker. This is simulated on-chain
|
||||
* via an eth_call. If this call fails, the asset is currently nontransferable.
|
||||
* @param signedOrder SignedOrder of interest
|
||||
* @param makerAssetAmount Amount to transfer from the maker
|
||||
* @param takerAddress The address to transfer to, defaults to signedOrder.takerAddress
|
||||
*/
|
||||
public async validateMakerTransferThrowIfInvalidAsync(
|
||||
signedOrder: SignedOrder,
|
||||
makerAssetAmount: BigNumber,
|
||||
takerAddress?: string,
|
||||
): Promise<void> {
|
||||
const toAddress = _.isUndefined(takerAddress) ? signedOrder.takerAddress : takerAddress;
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const makerAssetData = signedOrder.makerAssetData;
|
||||
const makerAssetDataProxyId = assetDataUtils.decodeAssetProxyId(signedOrder.makerAssetData);
|
||||
const assetProxyAddress = await exchangeInstance.assetProxies.callAsync(makerAssetDataProxyId);
|
||||
const assetProxy = new IAssetProxyContract(
|
||||
IAssetProxy.compilerOutput.abi,
|
||||
assetProxyAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
);
|
||||
|
||||
const result = await assetProxy.transferFrom.callAsync(
|
||||
makerAssetData,
|
||||
signedOrder.makerAddress,
|
||||
toAddress,
|
||||
makerAssetAmount,
|
||||
{
|
||||
from: this.address,
|
||||
},
|
||||
);
|
||||
if (result !== undefined) {
|
||||
throw new Error(`Error during maker transfer simulation: ${result}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validate a call to FillOrder and throw if it wouldn't succeed
|
||||
|
||||
@@ -120,13 +120,22 @@ export interface ContractWrappersConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* expectedFillTakerTokenAmount: If specified, the validation method will ensure that the
|
||||
* supplied order maker has a sufficient allowance/balance to fill this amount of the order's
|
||||
* takerTokenAmount. If not specified, the validation method ensures that the maker has a sufficient
|
||||
* allowance/balance to fill the entire remaining order amount.
|
||||
* `expectedFillTakerTokenAmount`: If specified, the validation method will ensure that the supplied order maker has a sufficient
|
||||
* allowance/balance to fill this amount of the order's takerTokenAmount.
|
||||
*
|
||||
* `validateRemainingOrderAmountIsFillable`: The validation method ensures that the maker has sufficient allowance/balance to fill
|
||||
* the entire remaining order amount. If this option is set to false, the balances
|
||||
* and allowances are calculated to determine the order is fillable for a
|
||||
* non-zero amount (some value less than or equal to the order remaining amount).
|
||||
* We call such orders "partially fillable orders". Default is `true`.
|
||||
*
|
||||
* `simulationTakerAddress`: During the maker transfer simulation, tokens are sent from the maker to the `simulationTakerAddress`. This defaults
|
||||
* to the `takerAddress` specified in the order. Some tokens prevent transfer to the NULL address so this address can be specified.
|
||||
*/
|
||||
export interface ValidateOrderFillableOpts {
|
||||
expectedFillTakerTokenAmount?: BigNumber;
|
||||
validateRemainingOrderAmountIsFillable?: boolean;
|
||||
simulationTakerAddress?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,4 @@
|
||||
import { DummyERC20TokenContract } from '@0x/abi-gen-wrappers';
|
||||
import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { assetDataUtils, orderHashUtils, signatureUtils } from '@0x/order-utils';
|
||||
@@ -10,6 +11,7 @@ import 'mocha';
|
||||
import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src';
|
||||
import { DecodedLogEvent } from '../src/types';
|
||||
|
||||
import { UntransferrableDummyERC20Token } from './artifacts/UntransferrableDummyERC20Token';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { migrateOnceAsync } from './utils/migrate';
|
||||
@@ -290,10 +292,94 @@ describe('ExchangeWrapper', () => {
|
||||
'0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403',
|
||||
};
|
||||
|
||||
expect(
|
||||
return expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrderWithInvalidSignature),
|
||||
).to.eventually.to.be.rejectedWith(RevertReason.InvalidOrderSignature);
|
||||
});
|
||||
it('should validate the order with the current balances and allowances for the maker', async () => {
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder, {
|
||||
validateRemainingOrderAmountIsFillable: false,
|
||||
});
|
||||
});
|
||||
it('should validate the order with remaining fillable amount for the order', async () => {
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||
});
|
||||
it('should validate the order with specified amount', async () => {
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder, {
|
||||
expectedFillTakerTokenAmount: signedOrder.takerAssetAmount,
|
||||
});
|
||||
});
|
||||
it('should throw if the amount is greater than the allowance/balance', async () => {
|
||||
return expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder, {
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
expectedFillTakerTokenAmount: new BigNumber(2).pow(256).minus(1),
|
||||
}),
|
||||
).to.eventually.to.be.rejected();
|
||||
});
|
||||
it('should throw when the maker does not have enough balance for the remaining order amount', async () => {
|
||||
const makerBalance = await contractWrappers.erc20Token.getBalanceAsync(makerTokenAddress, makerAddress);
|
||||
// Change maker balance to have less than the order amount
|
||||
const remainingBalance = makerBalance.minus(signedOrder.makerAssetAmount.minus(1));
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
makerTokenAddress,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
remainingBalance,
|
||||
),
|
||||
);
|
||||
return expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder),
|
||||
).to.eventually.to.be.rejected();
|
||||
});
|
||||
it('should validate the order when remaining order amount has some fillable amount', async () => {
|
||||
const makerBalance = await contractWrappers.erc20Token.getBalanceAsync(makerTokenAddress, makerAddress);
|
||||
// Change maker balance to have less than the order amount
|
||||
const remainingBalance = makerBalance.minus(signedOrder.makerAssetAmount.minus(1));
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc20Token.transferAsync(
|
||||
makerTokenAddress,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
remainingBalance,
|
||||
),
|
||||
);
|
||||
// An amount is still transferrable
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder, {
|
||||
validateRemainingOrderAmountIsFillable: false,
|
||||
});
|
||||
});
|
||||
it('should throw when the ERC20 token has transfer restrictions', async () => {
|
||||
const untransferrableToken = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
UntransferrableDummyERC20Token,
|
||||
provider,
|
||||
{ from: userAddresses[0] },
|
||||
'UntransferrableToken',
|
||||
'UTT',
|
||||
new BigNumber(constants.ZRX_DECIMALS),
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
new BigNumber(2).pow(20).minus(1),
|
||||
);
|
||||
const untransferrableMakerAssetData = assetDataUtils.encodeERC20AssetData(untransferrableToken.address);
|
||||
const invalidSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
untransferrableMakerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await contractWrappers.erc20Token.setProxyAllowanceAsync(
|
||||
untransferrableToken.address,
|
||||
makerAddress,
|
||||
signedOrder.makerAssetAmount,
|
||||
),
|
||||
);
|
||||
return expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(invalidSignedOrder),
|
||||
).to.eventually.to.be.rejectedWith('TRANSFER_FAILED');
|
||||
});
|
||||
});
|
||||
describe('#isValidSignature', () => {
|
||||
it('should check if the signature is valid', async () => {
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "7.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Added `orderCalculationUtils`",
|
||||
"pr": 1714
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1553183790,
|
||||
"version": "7.1.1",
|
||||
|
||||
@@ -7,6 +7,7 @@ export { transactionHashUtils } from './transaction_hash';
|
||||
export { rateUtils } from './rate_utils';
|
||||
export { sortingUtils } from './sorting_utils';
|
||||
export { orderParsingUtils } from './parsing_utils';
|
||||
export { orderCalculationUtils } from './order_calculation_utils';
|
||||
|
||||
export { OrderStateUtils } from './order_state_utils';
|
||||
export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
|
||||
|
||||
99
packages/order-utils/src/order_calculation_utils.ts
Normal file
99
packages/order-utils/src/order_calculation_utils.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Order } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
export const orderCalculationUtils = {
|
||||
/**
|
||||
* Determines if the order is expired given the current time
|
||||
* @param order The order for expiry calculation
|
||||
*/
|
||||
isOrderExpired(order: Order): boolean {
|
||||
return orderCalculationUtils.willOrderExpire(order, 0);
|
||||
},
|
||||
/**
|
||||
* Calculates if the order will expire in the future.
|
||||
* @param order The order for expiry calculation
|
||||
* @param secondsFromNow The amount of seconds from current time
|
||||
*/
|
||||
willOrderExpire(order: Order, secondsFromNow: number): boolean {
|
||||
const millisecondsInSecond = 1000;
|
||||
const currentUnixTimestampSec = new BigNumber(Date.now() / millisecondsInSecond).integerValue();
|
||||
return order.expirationTimeSeconds.isLessThan(currentUnixTimestampSec.plus(secondsFromNow));
|
||||
},
|
||||
/**
|
||||
* Determines if the order is open and fillable by any taker.
|
||||
* @param order The order
|
||||
*/
|
||||
isOpenOrder(order: Order): boolean {
|
||||
return order.takerAddress === constants.NULL_ADDRESS;
|
||||
},
|
||||
/**
|
||||
* Given an amount of taker asset, calculate the the amount of maker asset
|
||||
* @param order The order
|
||||
* @param makerFillAmount the amount of taker asset
|
||||
*/
|
||||
getMakerFillAmount(order: Order, takerFillAmount: BigNumber): BigNumber {
|
||||
// Round down because exchange rate favors Maker
|
||||
const makerFillAmount = takerFillAmount
|
||||
.multipliedBy(order.makerAssetAmount)
|
||||
.div(order.takerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_FLOOR);
|
||||
return makerFillAmount;
|
||||
},
|
||||
/**
|
||||
* Given an amount of maker asset, calculate the equivalent amount in taker asset
|
||||
* @param order The order
|
||||
* @param makerFillAmount the amount of maker asset
|
||||
*/
|
||||
getTakerFillAmount(order: Order, makerFillAmount: BigNumber): BigNumber {
|
||||
// Round up because exchange rate favors Maker
|
||||
const takerFillAmount = makerFillAmount
|
||||
.multipliedBy(order.takerAssetAmount)
|
||||
.div(order.makerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_CEIL);
|
||||
return takerFillAmount;
|
||||
},
|
||||
/**
|
||||
* Given an amount of taker asset, calculate the fee amount required for the taker
|
||||
* @param order The order
|
||||
* @param takerFillAmount the amount of taker asset
|
||||
*/
|
||||
getTakerFeeAmount(order: Order, takerFillAmount: BigNumber): BigNumber {
|
||||
// Round down because Taker fee rate favors Taker
|
||||
const takerFeeAmount = takerFillAmount
|
||||
.multipliedBy(order.takerFee)
|
||||
.div(order.takerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_FLOOR);
|
||||
return takerFeeAmount;
|
||||
},
|
||||
/**
|
||||
* Given an amount of maker asset, calculate the fee amount required for the maker
|
||||
* @param order The order
|
||||
* @param makerFillAmount the amount of maker asset
|
||||
*/
|
||||
getMakerFeeAmount(order: Order, makerFillAmount: BigNumber): BigNumber {
|
||||
// Round down because Maker fee rate favors Maker
|
||||
const makerFeeAmount = makerFillAmount
|
||||
.multipliedBy(order.makerFee)
|
||||
.div(order.makerAssetAmount)
|
||||
.integerValue(BigNumber.ROUND_FLOOR);
|
||||
return makerFeeAmount;
|
||||
},
|
||||
/**
|
||||
* Given a desired amount of ZRX from a fee order, calculate the amount of taker asset required to fill.
|
||||
* Also calculate how much ZRX needs to be purchased in order to fill the desired amount plus the taker fee amount
|
||||
* @param order The order
|
||||
* @param makerFillAmount the amount of maker asset
|
||||
*/
|
||||
getTakerFillAmountForFeeOrder(order: Order, makerFillAmount: BigNumber): [BigNumber, BigNumber] {
|
||||
// For each unit of TakerAsset we buy (MakerAsset - TakerFee)
|
||||
const adjustedTakerFillAmount = makerFillAmount
|
||||
.multipliedBy(order.takerAssetAmount)
|
||||
.div(order.makerAssetAmount.minus(order.takerFee))
|
||||
.integerValue(BigNumber.ROUND_CEIL);
|
||||
// The amount that we buy will be greater than makerFillAmount, since we buy some amount for fees.
|
||||
const adjustedMakerFillAmount = orderCalculationUtils.getMakerFillAmount(order, adjustedTakerFillAmount);
|
||||
return [adjustedTakerFillAmount, adjustedMakerFillAmount];
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,185 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "IAssetProxy",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "addAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "removeAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "index",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "removeAuthorizedAddressAtIndex",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "assetData",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getProxyId",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes4"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getAuthorizedAddresses",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"linkReferences": {},
|
||||
"object": "0x",
|
||||
"opcodes": "",
|
||||
"sourceMap": ""
|
||||
},
|
||||
"deployedBytecode": {
|
||||
"linkReferences": {},
|
||||
"object": "0x",
|
||||
"opcodes": "",
|
||||
"sourceMap": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources": {
|
||||
"src/interfaces/IAssetProxy.sol": {
|
||||
"id": 2
|
||||
},
|
||||
"src/interfaces/IAuthorizable.sol": {
|
||||
"id": 3
|
||||
},
|
||||
"@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol": {
|
||||
"id": 6
|
||||
}
|
||||
},
|
||||
"sourceCodes": {
|
||||
"src/interfaces/IAssetProxy.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\n\nimport \"./IAuthorizable.sol\";\n\n\ncontract IAssetProxy is\n IAuthorizable\n{\n /// @dev Transfers assets. Either succeeds or throws.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param from Address to transfer asset from.\n /// @param to Address to transfer asset to.\n /// @param amount Amount of asset to transfer.\n function transferFrom(\n bytes assetData,\n address from,\n address to,\n uint256 amount\n )\n external;\n \n /// @dev Gets the proxy id associated with the proxy address.\n /// @return Proxy id.\n function getProxyId()\n external\n pure\n returns (bytes4);\n}\n",
|
||||
"src/interfaces/IAuthorizable.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\n\nimport \"@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol\";\n\n\ncontract IAuthorizable is\n IOwnable\n{\n /// @dev Authorizes an address.\n /// @param target Address to authorize.\n function addAuthorizedAddress(address target)\n external;\n\n /// @dev Removes authorizion of an address.\n /// @param target Address to remove authorization from.\n function removeAuthorizedAddress(address target)\n external;\n\n /// @dev Removes authorizion of an address.\n /// @param target Address to remove authorization from.\n /// @param index Index of target in authorities array.\n function removeAuthorizedAddressAtIndex(\n address target,\n uint256 index\n )\n external;\n \n /// @dev Gets all authorized addresses.\n /// @return Array of authorized addresses.\n function getAuthorizedAddresses()\n external\n view\n returns (address[] memory);\n}\n",
|
||||
"@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol": "pragma solidity ^0.4.24;\n\n\ncontract IOwnable {\n\n function transferOwnership(address newOwner)\n public;\n}\n"
|
||||
},
|
||||
"sourceTreeHashHex": "0x4fe33d3b00ae85e5c1d5478eeb1bf17fdc637fa0501dc1ff6fd1f871f87c83ca",
|
||||
"compiler": {
|
||||
"name": "solc",
|
||||
"version": "0.4.25+commit.59dbf8f1.Linux.g++",
|
||||
"settings": {
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000,
|
||||
"details": {
|
||||
"yul": true,
|
||||
"deduplicate": true,
|
||||
"cse": true,
|
||||
"constantOptimizer": true
|
||||
}
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
},
|
||||
"evmVersion": "byzantium",
|
||||
"remappings": [
|
||||
"@0x/contracts-utils=/Users/jacob/projects/ethdev/0x/0x.js/contracts/asset-proxy/node_modules/@0x/contracts-utils"
|
||||
]
|
||||
}
|
||||
},
|
||||
"networks": {}
|
||||
}
|
||||
Reference in New Issue
Block a user