This repository has been archived by the owner on Oct 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 118
/
transform_erc20.ts
162 lines (150 loc) · 6.12 KB
/
transform_erc20.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import { ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers';
import {
encodeFillQuoteTransformerData,
encodeWethTransformerData,
FillQuoteTransformerOrderType,
FillQuoteTransformerSide,
findTransformerNonce,
RfqOrder,
SignatureType,
} from '@0x/protocol-utils';
import { BigNumber, hexUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { NETWORK_CONFIGS, TX_DEFAULTS } from '../configs';
import {
DECIMALS,
ETH_ADDRESS,
NULL_ADDRESS,
UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
} from '../constants';
import { PrintUtils } from '../print_utils';
import { providerEngine } from '../provider_engine';
import { getRandomFutureDateInSeconds, runMigrationsOnceIfRequiredAsync } from '../utils';
/**
* In this scenario, we use the TransformERC20 function to convert ETH
* to ZRX.
*
* TransformERC20 is used for aggregating various liquidity sources
* into a single trade. We only use a single RFQ order in this trade,
* but TransformERC20 can be used to fill quotes from a variety of
* DEX protocols (e.g. Uniswap, Balancer) in a single trade.
*/
export async function scenarioAsync(): Promise<void> {
await runMigrationsOnceIfRequiredAsync();
PrintUtils.printScenario('Transform ERC20');
// Initialize the ContractWrappers, this provides helper functions around calling
// 0x contracts as well as ERC20/ERC721 token contracts on the blockchain
const contractWrappers = new ContractWrappers(providerEngine, { chainId: NETWORK_CONFIGS.chainId });
// Initialize the Web3Wrapper, this provides helper functions around fetching
// account information, balances, general contract logs
const web3Wrapper = new Web3Wrapper(providerEngine);
const [maker, taker] = await web3Wrapper.getAvailableAddressesAsync();
const exchangeProxyAddress = contractWrappers.contractAddresses.exchangeProxy;
const zrxTokenAddress = contractWrappers.contractAddresses.zrxToken;
const etherTokenAddress = contractWrappers.contractAddresses.etherToken;
const printUtils = new PrintUtils(
web3Wrapper,
contractWrappers,
{ maker, taker },
{ WETH: etherTokenAddress, ZRX: zrxTokenAddress },
);
printUtils.printAccounts();
// the amount of ether the taker is selling
const etherAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS);
// Print out the Balances and Allowances
await printUtils.fetchAndPrintContractAllowancesAsync(contractWrappers.contractAddresses.exchangeProxy);
await printUtils.fetchAndPrintContractBalancesAsync();
// Create an RFQ order to fill later
const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(5), DECIMALS);
const zrxToken = new ERC20TokenContract(zrxTokenAddress, providerEngine);
const makerZRXApprovalTxHash = await zrxToken
.approve(exchangeProxyAddress, UNLIMITED_ALLOWANCE_IN_BASE_UNITS)
.sendTransactionAsync({ from: maker, ...TX_DEFAULTS });
await printUtils.awaitTransactionMinedSpinnerAsync('Maker ZRX Approval', makerZRXApprovalTxHash);
const randomExpiration = getRandomFutureDateInSeconds();
const pool = hexUtils.leftPad(1);
const rfqOrder: RfqOrder = new RfqOrder({
chainId: NETWORK_CONFIGS.chainId,
verifyingContract: exchangeProxyAddress,
maker,
taker: NULL_ADDRESS,
makerToken: zrxTokenAddress,
takerToken: etherTokenAddress,
makerAmount: makerAssetAmount,
takerAmount: etherAmount,
txOrigin: taker,
expiry: randomExpiration,
pool,
salt: new BigNumber(Date.now()),
});
const signature = await rfqOrder.getSignatureWithProviderAsync(web3Wrapper.getProvider(), SignatureType.EthSign, maker);
// TRANSFORMATIONS
// In this case the taker is starting with ETH.
// In order to fill an RFQ order, we need to transform the ETH
// into WETH first.
// We do this via the WethTransformer.
const wethTransformerData = {
deploymentNonce: findTransformerNonce(
contractWrappers.contractAddresses.transformers.wethTransformer,
contractWrappers.contractAddresses.exchangeProxyTransformerDeployer,
),
data: encodeWethTransformerData({
token: ETH_ADDRESS,
amount: etherAmount,
}),
};
// The second step is using the WETH to fill an RFQ order
// via the FillQuoteTransformer.
const fillQuoteTransformerData = {
deploymentNonce: findTransformerNonce(
contractWrappers.contractAddresses.transformers.fillQuoteTransformer,
contractWrappers.contractAddresses.exchangeProxyTransformerDeployer,
),
data: encodeFillQuoteTransformerData({
side: FillQuoteTransformerSide.Sell,
sellToken: etherTokenAddress,
buyToken: zrxTokenAddress,
rfqOrders: [{
order: rfqOrder,
signature,
maxTakerTokenFillAmount: etherAmount,
}],
bridgeOrders: [],
limitOrders: [],
fillSequence: [FillQuoteTransformerOrderType.Rfq],
refundReceiver: NULL_ADDRESS,
fillAmount: etherAmount,
}),
};
// Call TransformERC20 on the 0x Exchange Proxy contract
const txHash = await contractWrappers.exchangeProxy
.transformERC20(
ETH_ADDRESS,
zrxTokenAddress,
etherAmount,
makerAssetAmount,
[wethTransformerData, fillQuoteTransformerData],
)
.sendTransactionAsync({
from: taker,
value: etherAmount,
...TX_DEFAULTS,
});
const txReceipt = await printUtils.awaitTransactionMinedSpinnerAsync('TransformERC20', txHash);
printUtils.printTransaction('TransformERC20', txReceipt, []);
// Print the Balances
await printUtils.fetchAndPrintContractBalancesAsync();
// Stop the Provider Engine
providerEngine.stop();
}
void (async () => {
try {
if (!module.parent) {
await scenarioAsync();
}
} catch (e) {
console.log(e);
providerEngine.stop();
process.exit(1);
}
})();