More tests + require instead of revert in compliance contract
This commit is contained in:
parent
989b5b0a98
commit
33e41dd500
@ -52,7 +52,13 @@ contract CompliantForwarder {
|
|||||||
revert("EXCHANGE_TRANSACTION_NOT_FILL_ORDER");
|
revert("EXCHANGE_TRANSACTION_NOT_FILL_ORDER");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract maker address from fill order transaction
|
// Taker must be compliant
|
||||||
|
require(
|
||||||
|
COMPLIANCE_TOKEN.balanceOf(signerAddress) > 0,
|
||||||
|
"TAKER_UNVERIFIED"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Extract maker address from fill order transaction and ensure maker is compliant
|
||||||
// Below is the table of calldata offsets into a fillOrder transaction.
|
// Below is the table of calldata offsets into a fillOrder transaction.
|
||||||
/**
|
/**
|
||||||
### parameters
|
### parameters
|
||||||
@ -82,13 +88,10 @@ contract CompliantForwarder {
|
|||||||
// Add 0xc to the makerAddress since abi-encoded addresses are left padded with 12 bytes.
|
// Add 0xc to the makerAddress since abi-encoded addresses are left padded with 12 bytes.
|
||||||
// Putting this together: makerAddress = 0x60 + 0x4 + 0xc = 0x70
|
// Putting this together: makerAddress = 0x60 + 0x4 + 0xc = 0x70
|
||||||
address makerAddress = signedFillOrderTransaction.readAddress(0x70);
|
address makerAddress = signedFillOrderTransaction.readAddress(0x70);
|
||||||
|
require(
|
||||||
// Verify maker/taker have been verified by the compliance token.
|
COMPLIANCE_TOKEN.balanceOf(makerAddress) > 0,
|
||||||
if (COMPLIANCE_TOKEN.balanceOf(makerAddress) == 0) {
|
"MAKER_UNVERIFIED"
|
||||||
revert("MAKER_UNVERIFIED");
|
);
|
||||||
} else if (COMPLIANCE_TOKEN.balanceOf(signerAddress) == 0) {
|
|
||||||
revert("TAKER_UNVERIFIED");
|
|
||||||
}
|
|
||||||
|
|
||||||
// All entities are verified. Execute fillOrder.
|
// All entities are verified. Execute fillOrder.
|
||||||
EXCHANGE.executeTransaction(
|
EXCHANGE.executeTransaction(
|
||||||
|
@ -4,6 +4,7 @@ import { RevertReason, SignedOrder } from '@0x/types';
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
|
|
||||||
import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token';
|
import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token';
|
||||||
import { ExchangeContract } from '../../generated-wrappers/exchange';
|
import { ExchangeContract } from '../../generated-wrappers/exchange';
|
||||||
@ -12,9 +13,8 @@ import { YesComplianceTokenContract } from '../../generated-wrappers/yes_complia
|
|||||||
|
|
||||||
import { artifacts } from '../../src/artifacts';
|
import { artifacts } from '../../src/artifacts';
|
||||||
import {
|
import {
|
||||||
expectContractCreationFailedAsync,
|
|
||||||
expectTransactionFailedAsync,
|
expectTransactionFailedAsync,
|
||||||
sendTransactionResult,
|
expectTransactionFailedWithoutReasonAsync,
|
||||||
} from '../utils/assertions';
|
} from '../utils/assertions';
|
||||||
import { chaiSetup } from '../utils/chai_setup';
|
import { chaiSetup } from '../utils/chai_setup';
|
||||||
import { constants } from '../utils/constants';
|
import { constants } from '../utils/constants';
|
||||||
@ -36,17 +36,19 @@ describe.only(ContractName.CompliantForwarder, () => {
|
|||||||
let owner: string;
|
let owner: string;
|
||||||
let compliantTakerAddress: string;
|
let compliantTakerAddress: string;
|
||||||
let feeRecipientAddress: string;
|
let feeRecipientAddress: string;
|
||||||
let noncompliantAddress: string;
|
let nonCompliantAddress: string;
|
||||||
let defaultMakerAssetAddress: string;
|
let defaultMakerAssetAddress: string;
|
||||||
let defaultTakerAssetAddress: string;
|
let defaultTakerAssetAddress: string;
|
||||||
let zrxAssetData: string;
|
let zrxAssetData: string;
|
||||||
let zrxToken: DummyERC20TokenContract;
|
let zrxToken: DummyERC20TokenContract;
|
||||||
|
let exchangeInstance: ExchangeContract;
|
||||||
let exchangeWrapper: ExchangeWrapper;
|
let exchangeWrapper: ExchangeWrapper;
|
||||||
|
|
||||||
let orderFactory: OrderFactory;
|
let orderFactory: OrderFactory;
|
||||||
let erc20Wrapper: ERC20Wrapper;
|
let erc20Wrapper: ERC20Wrapper;
|
||||||
let erc20Balances: ERC20BalancesByOwner;
|
let erc20Balances: ERC20BalancesByOwner;
|
||||||
|
|
||||||
|
let takerTransactionFactory: TransactionFactory;
|
||||||
let compliantSignedOrder: SignedOrder;
|
let compliantSignedOrder: SignedOrder;
|
||||||
let compliantSignedFillOrderTx: SignedTransaction;
|
let compliantSignedFillOrderTx: SignedTransaction;
|
||||||
let noncompliantSignedFillOrderTx: SignedTransaction;
|
let noncompliantSignedFillOrderTx: SignedTransaction;
|
||||||
@ -66,7 +68,7 @@ describe.only(ContractName.CompliantForwarder, () => {
|
|||||||
compliantMakerAddress,
|
compliantMakerAddress,
|
||||||
compliantTakerAddress,
|
compliantTakerAddress,
|
||||||
feeRecipientAddress,
|
feeRecipientAddress,
|
||||||
noncompliantAddress,
|
nonCompliantAddress,
|
||||||
] = accounts);
|
] = accounts);
|
||||||
// Create wrappers
|
// Create wrappers
|
||||||
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
|
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
|
||||||
@ -91,7 +93,7 @@ describe.only(ContractName.CompliantForwarder, () => {
|
|||||||
const erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
const erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||||
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
||||||
// Deploy Exchange congtract
|
// Deploy Exchange congtract
|
||||||
const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
|
exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.Exchange,
|
artifacts.Exchange,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
@ -164,7 +166,7 @@ describe.only(ContractName.CompliantForwarder, () => {
|
|||||||
);
|
);
|
||||||
// Create Valid/Invalid orders
|
// Create Valid/Invalid orders
|
||||||
const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantTakerAddress)];
|
const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantTakerAddress)];
|
||||||
const takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchangeInstance.address);
|
takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchangeInstance.address);
|
||||||
compliantSignedOrder = await orderFactory.newSignedOrderAsync({
|
compliantSignedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
senderAddress: compliantForwarderInstance.address,
|
senderAddress: compliantForwarderInstance.address,
|
||||||
});
|
});
|
||||||
@ -190,8 +192,7 @@ describe.only(ContractName.CompliantForwarder, () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
erc20Balances = await erc20Wrapper.getBalancesAsync();
|
erc20Balances = await erc20Wrapper.getBalancesAsync();
|
||||||
});
|
});
|
||||||
|
it('should transfer the correct amounts when maker and taker are compliant', async () => {
|
||||||
it.only('should transfer the correct amounts when maker and taker are verified', async () => {
|
|
||||||
await compliantForwarderInstance.fillOrder.sendTransactionAsync(
|
await compliantForwarderInstance.fillOrder.sendTransactionAsync(
|
||||||
compliantSignedFillOrderTx.salt,
|
compliantSignedFillOrderTx.salt,
|
||||||
compliantSignedFillOrderTx.signerAddress,
|
compliantSignedFillOrderTx.signerAddress,
|
||||||
@ -230,8 +231,76 @@ describe.only(ContractName.CompliantForwarder, () => {
|
|||||||
erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
|
erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// @TODO: Should fail if order's senderAddress is not set to the compliant forwarding contract
|
it('should revert if the signed transaction is not intended for fillOrder', async () => {
|
||||||
// @TODO: Should fail if the signed transaction is not intended for fillOrder
|
// Create signed order without the fillOrder function selector
|
||||||
|
const txDataBuf = ethUtil.toBuffer(compliantSignedFillOrderTx.data);
|
||||||
|
const selectorLengthInBytes = 4;
|
||||||
|
const txDataBufMinusSelector = txDataBuf.slice(selectorLengthInBytes);
|
||||||
|
const badSelector = '0x00000000';
|
||||||
|
const badSelectorBuf = ethUtil.toBuffer(badSelector);
|
||||||
|
const txDataBufWithBadSelector = Buffer.concat([badSelectorBuf, txDataBufMinusSelector]);
|
||||||
|
const txDataBufWithBadSelectorHex = ethUtil.bufferToHex(txDataBufWithBadSelector);
|
||||||
|
// Call compliant forwarder
|
||||||
|
return expectTransactionFailedWithoutReasonAsync(compliantForwarderInstance.fillOrder.sendTransactionAsync(
|
||||||
|
compliantSignedFillOrderTx.salt,
|
||||||
|
compliantSignedFillOrderTx.signerAddress,
|
||||||
|
txDataBufWithBadSelectorHex,
|
||||||
|
compliantSignedFillOrderTx.signature,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
it('should revert if senderAddress is not set to the compliant forwarding contract', async () => {
|
||||||
|
// Create signed order with incorrect senderAddress
|
||||||
|
const notCompliantForwarderAddress = zrxToken.address;
|
||||||
|
const signedOrderWithBadSenderAddress = await orderFactory.newSignedOrderAsync({
|
||||||
|
senderAddress: notCompliantForwarderAddress,
|
||||||
|
});
|
||||||
|
const signedOrderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(
|
||||||
|
signedOrderWithBadSenderAddress,
|
||||||
|
);
|
||||||
|
const signedOrderWithoutExchangeAddressData = exchangeInstance.fillOrder.getABIEncodedTransactionData(
|
||||||
|
signedOrderWithoutExchangeAddress,
|
||||||
|
takerAssetFillAmount,
|
||||||
|
compliantSignedOrder.signature,
|
||||||
|
);
|
||||||
|
const signedFillOrderTx = takerTransactionFactory.newSignedTransaction(
|
||||||
|
signedOrderWithoutExchangeAddressData,
|
||||||
|
);
|
||||||
|
// Call compliant forwarder
|
||||||
|
return expectTransactionFailedWithoutReasonAsync(compliantForwarderInstance.fillOrder.sendTransactionAsync(
|
||||||
|
signedFillOrderTx.salt,
|
||||||
|
signedFillOrderTx.signerAddress,
|
||||||
|
signedFillOrderTx.data,
|
||||||
|
signedFillOrderTx.signature,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
it('should revert if maker address is not compliant (does not hold a Yes Token)', async () => {
|
||||||
|
// Create signed order with non-compliant maker address
|
||||||
|
const signedOrderWithBadSenderAddress = await orderFactory.newSignedOrderAsync({
|
||||||
|
senderAddress: compliantForwarderInstance.address,
|
||||||
|
makerAddress: nonCompliantAddress
|
||||||
|
});
|
||||||
|
const signedOrderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(
|
||||||
|
signedOrderWithBadSenderAddress,
|
||||||
|
);
|
||||||
|
const signedOrderWithoutExchangeAddressData = exchangeInstance.fillOrder.getABIEncodedTransactionData(
|
||||||
|
signedOrderWithoutExchangeAddress,
|
||||||
|
takerAssetFillAmount,
|
||||||
|
compliantSignedOrder.signature,
|
||||||
|
);
|
||||||
|
const signedFillOrderTx = takerTransactionFactory.newSignedTransaction(
|
||||||
|
signedOrderWithoutExchangeAddressData,
|
||||||
|
);
|
||||||
|
// Call compliant forwarder
|
||||||
|
return expectTransactionFailedAsync(
|
||||||
|
compliantForwarderInstance.fillOrder.sendTransactionAsync(
|
||||||
|
signedFillOrderTx.salt,
|
||||||
|
signedFillOrderTx.signerAddress,
|
||||||
|
signedFillOrderTx.data,
|
||||||
|
signedFillOrderTx.signature,
|
||||||
|
),
|
||||||
|
RevertReason.MakerUnverified
|
||||||
|
);
|
||||||
|
});
|
||||||
// @TODO: Should fail if maker is not verified
|
// @TODO: Should fail if maker is not verified
|
||||||
// @TODO: Should fail it taker is not verified
|
// @TODO: Should fail it taker is not verified
|
||||||
});
|
});
|
||||||
|
@ -243,6 +243,8 @@ export enum RevertReason {
|
|||||||
AuctionNotStarted = 'AUCTION_NOT_STARTED',
|
AuctionNotStarted = 'AUCTION_NOT_STARTED',
|
||||||
AuctionInvalidBeginTime = 'INVALID_BEGIN_TIME',
|
AuctionInvalidBeginTime = 'INVALID_BEGIN_TIME',
|
||||||
InvalidAssetData = 'INVALID_ASSET_DATA',
|
InvalidAssetData = 'INVALID_ASSET_DATA',
|
||||||
|
MakerUnverified = 'MAKER_UNVERIFED',
|
||||||
|
TakerUnverified = 'TAKER_UNVERIFIED',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum StatusCodes {
|
export enum StatusCodes {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user