* `@0x/contracts-zero-ex`: Fix NativeOrdersFeature order hash cancellation not emitting proper maker. `@0x/contracts-zero-ex`: Revert to original (deployed) ZeroEx/EP proxy implementation. Optimized one is now at `ZeroExOptimized.sol`. `@0x/contracts-zero-ex`: Add gas limits to first `transferFrom()` call in `LibTokenSpender` and `UniswapFeature`. * `@0x/contracts-zero-ex`: Update changelog * disable `no-empty-blocks` solidity linter rule * `@0x/contracts-zero-ex`: Use bloom filters of greedy tokens in token transfer logic `@0x/contracts-zero-ex`: Turn `LibTokenSpender` into `FixinTokenSpender`. `@0x/contracts-zero-ex`: Misc renames for consistency. * `@0x/contracts-zero-ex`: Export `GREEDY_TOKENS` list * rebase and update changelog * `@0x/contracts-zero-ex`: Change bloom filter hash algo based on discussions * `@0x/contracts-zero-ex`: Fix changelog * update orders docs * `@0x/contracts-zero-ex`: revert if allowance call fails in uniswap feature Co-authored-by: Lawrence Forman <me@merklejerk.com>
97 lines
4.3 KiB
TypeScript
97 lines
4.3 KiB
TypeScript
import { blockchainTests, constants, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
|
import { BigNumber, ZeroExRevertErrors } from '@0x/utils';
|
|
|
|
import { ZeroExContract } from '../src/wrappers';
|
|
|
|
import { artifacts } from './artifacts';
|
|
import { initialMigrateAsync } from './utils/migration';
|
|
import {
|
|
IFeatureContract,
|
|
IOwnableFeatureContract,
|
|
ISimpleFunctionRegistryFeatureContract,
|
|
TestZeroExFeatureContract,
|
|
TestZeroExFeatureEvents,
|
|
} from './wrappers';
|
|
|
|
blockchainTests.resets('ZeroEx contract', env => {
|
|
let owner: string;
|
|
let zeroEx: ZeroExContract;
|
|
let ownable: IOwnableFeatureContract;
|
|
let registry: ISimpleFunctionRegistryFeatureContract;
|
|
let testFeature: TestZeroExFeatureContract;
|
|
|
|
before(async () => {
|
|
[owner] = await env.getAccountAddressesAsync();
|
|
zeroEx = await initialMigrateAsync(owner, env.provider, env.txDefaults);
|
|
ownable = new IOwnableFeatureContract(zeroEx.address, env.provider, env.txDefaults);
|
|
registry = new ISimpleFunctionRegistryFeatureContract(zeroEx.address, env.provider, env.txDefaults);
|
|
testFeature = new TestZeroExFeatureContract(zeroEx.address, env.provider, env.txDefaults);
|
|
// Register test features.
|
|
const testFeatureImpl = await TestZeroExFeatureContract.deployFrom0xArtifactAsync(
|
|
artifacts.TestZeroExFeature,
|
|
env.provider,
|
|
env.txDefaults,
|
|
artifacts,
|
|
);
|
|
for (const fn of ['payableFn', 'notPayableFn', 'internalFn']) {
|
|
await registry
|
|
.extend(testFeature.getSelector(fn), testFeatureImpl.address)
|
|
.awaitTransactionSuccessAsync({ from: owner });
|
|
}
|
|
});
|
|
|
|
it('can receive ether', async () => {
|
|
const txHash = await env.web3Wrapper.sendTransactionAsync({
|
|
from: owner,
|
|
to: zeroEx.address,
|
|
data: constants.NULL_BYTES,
|
|
value: 1,
|
|
});
|
|
await env.web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
|
});
|
|
|
|
it('can attach ether to a call', async () => {
|
|
const wei = Math.floor(Math.random() * 100 + 1);
|
|
const receipt = await testFeature.payableFn().awaitTransactionSuccessAsync({ value: wei });
|
|
verifyEventsFromLogs(receipt.logs, [{ value: new BigNumber(wei) }], TestZeroExFeatureEvents.PayableFnCalled);
|
|
});
|
|
|
|
it('reverts when attaching ether to a non-payable function', async () => {
|
|
const wei = Math.floor(Math.random() * 100 + 1);
|
|
const tx = testFeature.notPayableFn().awaitTransactionSuccessAsync({ value: wei });
|
|
// This will cause an empty revert.
|
|
return expect(tx).to.be.rejectedWith('revert');
|
|
});
|
|
|
|
it('reverts when calling an unimplmented function', async () => {
|
|
const selector = testFeature.getSelector('unimplmentedFn');
|
|
const tx = testFeature.unimplmentedFn().awaitTransactionSuccessAsync();
|
|
return expect(tx).to.revertWith(new ZeroExRevertErrors.Proxy.NotImplementedError(selector));
|
|
});
|
|
|
|
it('reverts when calling an internal function', async () => {
|
|
const tx = testFeature.internalFn().awaitTransactionSuccessAsync({ from: owner });
|
|
return expect(tx).to.revertWith(new ZeroExRevertErrors.Common.OnlyCallableBySelfError(owner));
|
|
});
|
|
|
|
describe('getFunctionImplementation()', () => {
|
|
it('returns the correct implementations of the initial features', async () => {
|
|
const ownableSelectors = [ownable.getSelector('transferOwnership')];
|
|
const registrySelectors = [
|
|
registry.getSelector('rollback'),
|
|
registry.getSelector('extend'),
|
|
// registry.getSelector('extendSelf'),
|
|
];
|
|
const selectors = [...ownableSelectors, ...registrySelectors];
|
|
const impls = await Promise.all(selectors.map(s => zeroEx.getFunctionImplementation(s).callAsync()));
|
|
for (let i = 0; i < impls.length; ++i) {
|
|
const selector = selectors[i];
|
|
const impl = impls[i];
|
|
const feat = new IFeatureContract(impl, env.provider, env.txDefaults);
|
|
const featName = ownableSelectors.includes(selector) ? 'Ownable' : 'SimpleFunctionRegistry';
|
|
expect(await feat.FEATURE_NAME().callAsync()).to.eq(featName);
|
|
}
|
|
});
|
|
});
|
|
});
|