Simulate maker transfer in order validation
This commit is contained in:
parent
0beb2f9d3c
commit
9164d58dc7
@ -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';
|
||||
|
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,10 +1,12 @@
|
||||
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,
|
||||
OrderValidationUtils,
|
||||
} from '@0x/order-utils';
|
||||
import { AssetProxyId, Order, SignedOrder } from '@0x/types';
|
||||
@ -1165,6 +1167,70 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
this.getZRXAssetData(),
|
||||
expectedFillTakerTokenAmountIfExists,
|
||||
);
|
||||
const filledTakerAmount = await this.getFilledTakerAssetAmountAsync(
|
||||
orderHashUtils.getOrderHashHex(signedOrder),
|
||||
);
|
||||
const makerAssetBalance = await balanceAllowanceStore.getBalanceAsync(
|
||||
signedOrder.makerAssetData,
|
||||
signedOrder.makerAddress,
|
||||
);
|
||||
const makerAssetAllowance = await balanceAllowanceStore.getProxyAllowanceAsync(
|
||||
signedOrder.makerAssetData,
|
||||
signedOrder.makerAddress,
|
||||
);
|
||||
const makerZRXBalance = await balanceAllowanceStore.getBalanceAsync(
|
||||
this.getZRXAssetData(),
|
||||
signedOrder.makerAddress,
|
||||
);
|
||||
const makerZRXAllowance = await balanceAllowanceStore.getProxyAllowanceAsync(
|
||||
this.getZRXAssetData(),
|
||||
signedOrder.makerAddress,
|
||||
);
|
||||
const remainingFillableTakerAssetAmount = orderCalculationUtils.calculateRemainingFillableTakerAssetAmount(
|
||||
signedOrder,
|
||||
filledTakerAmount,
|
||||
{ balance: makerAssetBalance, allowance: makerAssetAllowance },
|
||||
{ balance: makerZRXBalance, allowance: makerZRXAllowance },
|
||||
);
|
||||
|
||||
await this.validateMakerTransferThrowIfInvalidAsync(signedOrder, remainingFillableTakerAssetAmount);
|
||||
}
|
||||
/**
|
||||
* 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 unlikely to be transferrable.
|
||||
* @param signedOrder SignedOrder of interest
|
||||
* @param fillTakerAssetAmount Amount we'd like to fill the order for
|
||||
* @param takerAddress The taker of the order, defaults to signedOrder.takerAddress
|
||||
*/
|
||||
public async validateMakerTransferThrowIfInvalidAsync(
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerAssetAmount: 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 makerTransferAmount = orderCalculationUtils.getMakerFillAmount(signedOrder, fillTakerAssetAmount);
|
||||
|
||||
const result = await assetProxy.transferFrom.callAsync(
|
||||
makerAssetData,
|
||||
signedOrder.makerAddress,
|
||||
toAddress,
|
||||
makerTransferAmount,
|
||||
{
|
||||
from: this.address,
|
||||
},
|
||||
);
|
||||
if (result !== undefined) {
|
||||
throw new Error('Unknown error occured during maker transfer simulation');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validate a call to FillOrder and throw if it wouldn't succeed
|
||||
|
@ -294,6 +294,9 @@ describe('ExchangeWrapper', () => {
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrderWithInvalidSignature),
|
||||
).to.eventually.to.be.rejectedWith(RevertReason.InvalidOrderSignature);
|
||||
});
|
||||
it.only('should validate the order', async () => {
|
||||
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||
});
|
||||
});
|
||||
describe('#isValidSignature', () => {
|
||||
it('should check if the signature is valid', async () => {
|
||||
|
@ -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';
|
||||
@ -74,4 +75,5 @@ export {
|
||||
FindOrdersThatCoverMakerAssetFillAmountOpts,
|
||||
FeeOrdersAndRemainingFeeAmount,
|
||||
OrdersAndRemainingFillAmount,
|
||||
BalanceAndAllowance,
|
||||
} from './types';
|
||||
|
110
packages/order-utils/src/order_calculation_utils.ts
Normal file
110
packages/order-utils/src/order_calculation_utils.ts
Normal file
@ -0,0 +1,110 @@
|
||||
import { Order } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { constants } from './constants';
|
||||
import { BalanceAndAllowance } from './types';
|
||||
|
||||
export const orderCalculationUtils = {
|
||||
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 a desired amount of takerAsset to fill, calculate how much makerAsset will be filled
|
||||
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;
|
||||
},
|
||||
/**
|
||||
* Calculates the remaining fillable amount for an order given:
|
||||
* order filled amount
|
||||
* asset balance/allowance (maker/taker)
|
||||
* ZRX fee balance/allowance (maker/taker)
|
||||
* Taker values are checked if specified in the order. For example, if the maker does not
|
||||
* have sufficient ZRX allowance to pay the fee, then this function will return the maximum
|
||||
* amount that can be filled given the maker's ZRX allowance
|
||||
* @param order The order
|
||||
* @param takerAssetFilledAmount The amount currently filled on the order
|
||||
* @param makerAssetBalanceAllowance The makerAsset balance and allowance of the maker
|
||||
* @param makerZRXBalanceAllowance The ZRX balance and allowance of the maker
|
||||
* @param takerAssetBalanceAllowance The takerAsset balance and allowance of the taker
|
||||
* @param takerZRXBalanceAllowance The ZRX balance and allowance of the taker
|
||||
*/
|
||||
calculateRemainingFillableTakerAssetAmount(
|
||||
order: Order,
|
||||
takerAssetFilledAmount: BigNumber,
|
||||
makerAssetBalanceAllowance: BalanceAndAllowance,
|
||||
makerZRXBalanceAllowance: BalanceAndAllowance,
|
||||
takerAssetBalanceAllowance?: BalanceAndAllowance,
|
||||
takerZRXBalanceAllowance?: BalanceAndAllowance,
|
||||
): BigNumber {
|
||||
const minSet = [];
|
||||
|
||||
// Calculate min of balance & allowance of taker's takerAsset
|
||||
if (order.takerAddress !== constants.NULL_ADDRESS) {
|
||||
if (takerAssetBalanceAllowance && takerZRXBalanceAllowance) {
|
||||
const maxTakerAssetFillAmountGivenTakerConstraints = BigNumber.min(
|
||||
takerAssetBalanceAllowance.balance,
|
||||
takerAssetBalanceAllowance.allowance,
|
||||
);
|
||||
minSet.push(
|
||||
maxTakerAssetFillAmountGivenTakerConstraints,
|
||||
takerAssetBalanceAllowance.balance,
|
||||
takerAssetBalanceAllowance.allowance,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate min of balance & allowance of maker's makerAsset -> translate into takerAsset amount
|
||||
const maxMakerAssetFillAmount = BigNumber.min(
|
||||
makerAssetBalanceAllowance.balance,
|
||||
makerAssetBalanceAllowance.allowance,
|
||||
);
|
||||
const maxTakerAssetFillAmountGivenMakerConstraints = orderCalculationUtils.getTakerFillAmount(
|
||||
order,
|
||||
maxMakerAssetFillAmount,
|
||||
);
|
||||
minSet.push(maxTakerAssetFillAmountGivenMakerConstraints);
|
||||
|
||||
// Calculate min of balance & allowance of taker's ZRX -> translate into takerAsset amount
|
||||
if (!order.takerFee.eq(0) && order.takerAddress !== constants.NULL_ADDRESS) {
|
||||
if (takerAssetBalanceAllowance && takerZRXBalanceAllowance) {
|
||||
const takerZRXAvailable = BigNumber.min(
|
||||
takerZRXBalanceAllowance.balance,
|
||||
takerZRXBalanceAllowance.allowance,
|
||||
);
|
||||
const maxTakerAssetFillAmountGivenTakerZRXConstraints = takerZRXAvailable
|
||||
.multipliedBy(order.takerAssetAmount)
|
||||
.div(order.takerFee)
|
||||
.integerValue(BigNumber.ROUND_CEIL); // Should this round to ciel or floor?
|
||||
minSet.push(maxTakerAssetFillAmountGivenTakerZRXConstraints);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate min of balance & allowance of maker's ZRX -> translate into takerAsset amount
|
||||
if (!order.makerFee.eq(0)) {
|
||||
const makerZRXAvailable = BigNumber.min(
|
||||
makerZRXBalanceAllowance.balance,
|
||||
makerZRXBalanceAllowance.allowance,
|
||||
);
|
||||
const maxTakerAssetFillAmountGivenMakerZRXConstraints = makerZRXAvailable
|
||||
.multipliedBy(order.takerAssetAmount)
|
||||
.div(order.makerFee)
|
||||
.integerValue(BigNumber.ROUND_CEIL); // Should this round to ciel or floor?
|
||||
minSet.push(maxTakerAssetFillAmountGivenMakerZRXConstraints);
|
||||
}
|
||||
|
||||
const remainingTakerAssetFillAmount = order.takerAssetAmount.minus(takerAssetFilledAmount);
|
||||
minSet.push(remainingTakerAssetFillAmount);
|
||||
|
||||
const maxTakerAssetFillAmount = BigNumber.min(...minSet);
|
||||
return maxTakerAssetFillAmount;
|
||||
},
|
||||
};
|
@ -64,3 +64,8 @@ export interface OrdersAndRemainingFillAmount<T> {
|
||||
ordersRemainingFillableMakerAssetAmounts: BigNumber[];
|
||||
remainingFillAmount: BigNumber;
|
||||
}
|
||||
|
||||
export interface BalanceAndAllowance {
|
||||
balance: BigNumber;
|
||||
allowance: BigNumber;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user