feat: opt-in positive slippage fee for integrators (#101)
* feat: Positive Slippage Fee * fix: rename ethToTakerAssetRate to takerAssetPriceForOneEth * fix: rename takerAssetPriceForOneEth to takerAssetsPerEth * fix: export AffiliateFeeType * rebased off development * Add a gasOverhead for non-deterministic operations * CHANGELOGs * rename outputTokens to outputAmount * Confirm transformer addresses on Mainnet and Ropsten * fix import Co-authored-by: Jacob Evans <jacob@dekz.net>
This commit is contained in:
@@ -92,6 +92,7 @@ import * as NativeOrdersFeature from '../test/generated-artifacts/NativeOrdersFe
|
||||
import * as OwnableFeature from '../test/generated-artifacts/OwnableFeature.json';
|
||||
import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json';
|
||||
import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/PermissionlessTransformerDeployer.json';
|
||||
import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.json';
|
||||
import * as SimpleFunctionRegistryFeature from '../test/generated-artifacts/SimpleFunctionRegistryFeature.json';
|
||||
import * as TestBridge from '../test/generated-artifacts/TestBridge.json';
|
||||
import * as TestCallTarget from '../test/generated-artifacts/TestCallTarget.json';
|
||||
@@ -209,6 +210,7 @@ export const artifacts = {
|
||||
LibERC20Transformer: LibERC20Transformer as ContractArtifact,
|
||||
LogMetadataTransformer: LogMetadataTransformer as ContractArtifact,
|
||||
PayTakerTransformer: PayTakerTransformer as ContractArtifact,
|
||||
PositiveSlippageFeeTransformer: PositiveSlippageFeeTransformer as ContractArtifact,
|
||||
Transformer: Transformer as ContractArtifact,
|
||||
WethTransformer: WethTransformer as ContractArtifact,
|
||||
BridgeAdapter: BridgeAdapter as ContractArtifact,
|
||||
|
@@ -0,0 +1,127 @@
|
||||
import { blockchainTests, constants, expect, getRandomInteger, randomAddress } from '@0x/contracts-test-utils';
|
||||
import { encodePositiveSlippageFeeTransformerData } from '@0x/protocol-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { artifacts } from '../artifacts';
|
||||
import {
|
||||
PositiveSlippageFeeTransformerContract,
|
||||
TestMintableERC20TokenContract,
|
||||
TestTransformerHostContract,
|
||||
} from '../wrappers';
|
||||
|
||||
const { ZERO_AMOUNT } = constants;
|
||||
|
||||
blockchainTests.resets('PositiveSlippageFeeTransformer', env => {
|
||||
const recipient = randomAddress();
|
||||
let caller: string;
|
||||
let token: TestMintableERC20TokenContract;
|
||||
let transformer: PositiveSlippageFeeTransformerContract;
|
||||
let host: TestTransformerHostContract;
|
||||
|
||||
before(async () => {
|
||||
[caller] = await env.getAccountAddressesAsync();
|
||||
token = await TestMintableERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestMintableERC20Token,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
transformer = await PositiveSlippageFeeTransformerContract.deployFrom0xArtifactAsync(
|
||||
artifacts.PositiveSlippageFeeTransformer,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
host = await TestTransformerHostContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestTransformerHost,
|
||||
env.provider,
|
||||
{ ...env.txDefaults, from: caller },
|
||||
artifacts,
|
||||
);
|
||||
});
|
||||
|
||||
interface Balances {
|
||||
ethBalance: BigNumber;
|
||||
tokenBalance: BigNumber;
|
||||
}
|
||||
|
||||
async function getBalancesAsync(owner: string): Promise<Balances> {
|
||||
return {
|
||||
ethBalance: await env.web3Wrapper.getBalanceInWeiAsync(owner),
|
||||
tokenBalance: await token.balanceOf(owner).callAsync(),
|
||||
};
|
||||
}
|
||||
|
||||
async function mintHostTokensAsync(amount: BigNumber): Promise<void> {
|
||||
await token.mint(host.address, amount).awaitTransactionSuccessAsync();
|
||||
}
|
||||
|
||||
it('does not transfer positive slippage fees when bestCaseAmount is equal to amount', async () => {
|
||||
const amount = getRandomInteger(1, '1e18');
|
||||
const data = encodePositiveSlippageFeeTransformerData({
|
||||
token: token.address,
|
||||
bestCaseAmount: amount,
|
||||
recipient,
|
||||
});
|
||||
await mintHostTokensAsync(amount);
|
||||
const beforeBalanceHost = await getBalancesAsync(host.address);
|
||||
const beforeBalanceRecipient = await getBalancesAsync(recipient);
|
||||
await host
|
||||
.rawExecuteTransform(transformer.address, {
|
||||
data,
|
||||
sender: randomAddress(),
|
||||
taker: randomAddress(),
|
||||
})
|
||||
.awaitTransactionSuccessAsync();
|
||||
expect(await getBalancesAsync(host.address)).to.deep.eq(beforeBalanceHost);
|
||||
expect(await getBalancesAsync(recipient)).to.deep.eq(beforeBalanceRecipient);
|
||||
});
|
||||
|
||||
it('does not transfer positive slippage fees when bestCaseAmount is higher than amount', async () => {
|
||||
const amount = getRandomInteger(1, '1e18');
|
||||
const bestCaseAmount = amount.times(1.1).decimalPlaces(0, BigNumber.ROUND_FLOOR);
|
||||
const data = encodePositiveSlippageFeeTransformerData({
|
||||
token: token.address,
|
||||
bestCaseAmount,
|
||||
recipient,
|
||||
});
|
||||
await mintHostTokensAsync(amount);
|
||||
const beforeBalanceHost = await getBalancesAsync(host.address);
|
||||
const beforeBalanceRecipient = await getBalancesAsync(recipient);
|
||||
await host
|
||||
.rawExecuteTransform(transformer.address, {
|
||||
data,
|
||||
sender: randomAddress(),
|
||||
taker: randomAddress(),
|
||||
})
|
||||
.awaitTransactionSuccessAsync();
|
||||
expect(await getBalancesAsync(host.address)).to.deep.eq(beforeBalanceHost);
|
||||
expect(await getBalancesAsync(recipient)).to.deep.eq(beforeBalanceRecipient);
|
||||
});
|
||||
|
||||
it('send positive slippage fee to recipient when bestCaseAmount is lower than amount', async () => {
|
||||
const amount = getRandomInteger(1, '1e18');
|
||||
const bestCaseAmount = amount.times(0.95).decimalPlaces(0, BigNumber.ROUND_FLOOR);
|
||||
const data = encodePositiveSlippageFeeTransformerData({
|
||||
token: token.address,
|
||||
bestCaseAmount,
|
||||
recipient,
|
||||
});
|
||||
await mintHostTokensAsync(amount);
|
||||
await host
|
||||
.rawExecuteTransform(transformer.address, {
|
||||
data,
|
||||
sender: randomAddress(),
|
||||
taker: randomAddress(),
|
||||
})
|
||||
.awaitTransactionSuccessAsync();
|
||||
expect(await getBalancesAsync(host.address)).to.deep.eq({
|
||||
tokenBalance: bestCaseAmount,
|
||||
ethBalance: ZERO_AMOUNT,
|
||||
});
|
||||
expect(await getBalancesAsync(recipient)).to.deep.eq({
|
||||
tokenBalance: amount.minus(bestCaseAmount), // positive slippage
|
||||
ethBalance: ZERO_AMOUNT,
|
||||
});
|
||||
});
|
||||
});
|
@@ -90,6 +90,7 @@ export * from '../test/generated-wrappers/native_orders_feature';
|
||||
export * from '../test/generated-wrappers/ownable_feature';
|
||||
export * from '../test/generated-wrappers/pay_taker_transformer';
|
||||
export * from '../test/generated-wrappers/permissionless_transformer_deployer';
|
||||
export * from '../test/generated-wrappers/positive_slippage_fee_transformer';
|
||||
export * from '../test/generated-wrappers/simple_function_registry_feature';
|
||||
export * from '../test/generated-wrappers/test_bridge';
|
||||
export * from '../test/generated-wrappers/test_call_target';
|
||||
|
Reference in New Issue
Block a user