@0x/contracts-erc20-bridge-aggregator: Create package.
				
					
				
			`@0x/contracts-erc20`: Add `decimals()` to `LibERC20Token`. `@0x/contracts-erc20-bridge-sampler`: Created package.
This commit is contained in:
		
							
								
								
									
										10
									
								
								contracts/erc20-bridge-sampler/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								contracts/erc20-bridge-sampler/.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					# Blacklist all files
 | 
				
			||||||
 | 
					.*
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					# Whitelist lib
 | 
				
			||||||
 | 
					!lib/**/*
 | 
				
			||||||
 | 
					# Whitelist Solidity contracts
 | 
				
			||||||
 | 
					!contracts/src/**/*
 | 
				
			||||||
 | 
					# Blacklist tests in lib
 | 
				
			||||||
 | 
					/lib/test/*
 | 
				
			||||||
 | 
					# Package specific ignore
 | 
				
			||||||
							
								
								
									
										11
									
								
								contracts/erc20-bridge-sampler/CHANGELOG.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								contracts/erc20-bridge-sampler/CHANGELOG.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					[
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "version": "1.0.0-beta.1",
 | 
				
			||||||
 | 
					        "changes": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "note": "Created package.",
 | 
				
			||||||
 | 
					                "pr": "TODO"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										0
									
								
								contracts/erc20-bridge-sampler/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								contracts/erc20-bridge-sampler/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										17
									
								
								contracts/erc20-bridge-sampler/DEPLOYS.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								contracts/erc20-bridge-sampler/DEPLOYS.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					[
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "Exchange",
 | 
				
			||||||
 | 
					        "version": "2.0.0",
 | 
				
			||||||
 | 
					        "changes": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "note": "protocol v2 deploy",
 | 
				
			||||||
 | 
					                "networks": {
 | 
				
			||||||
 | 
					                    "1": "0xBDB58Fdf0a1587a0a258330a184Bb2C6cbA0aabe",
 | 
				
			||||||
 | 
					                    "3": "0x0000000000000000000000000000000000000000",
 | 
				
			||||||
 | 
					                    "4": "0x0000000000000000000000000000000000000000",
 | 
				
			||||||
 | 
					                    "42": "0x0000000000000000000000000000000000000000"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										3
									
								
								contracts/erc20-bridge-sampler/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								contracts/erc20-bridge-sampler/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					## ERC20BridgeSampler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These are contracts used in DEX aggregation.
 | 
				
			||||||
							
								
								
									
										26
									
								
								contracts/erc20-bridge-sampler/compiler.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								contracts/erc20-bridge-sampler/compiler.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "artifactsDir": "./test/generated-artifacts",
 | 
				
			||||||
 | 
					    "contractsDir": "./contracts",
 | 
				
			||||||
 | 
					    "useDockerisedSolc": false,
 | 
				
			||||||
 | 
					    "isOfflineMode": false,
 | 
				
			||||||
 | 
					    "compilerSettings": {
 | 
				
			||||||
 | 
					        "evmVersion": "constantinople",
 | 
				
			||||||
 | 
					        "optimizer": {
 | 
				
			||||||
 | 
					            "enabled": true,
 | 
				
			||||||
 | 
					            "runs": 1000000,
 | 
				
			||||||
 | 
					            "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "outputSelection": {
 | 
				
			||||||
 | 
					            "*": {
 | 
				
			||||||
 | 
					                "*": [
 | 
				
			||||||
 | 
					                    "abi",
 | 
				
			||||||
 | 
					                    "devdoc",
 | 
				
			||||||
 | 
					                    "evm.bytecode.object",
 | 
				
			||||||
 | 
					                    "evm.bytecode.sourceMap",
 | 
				
			||||||
 | 
					                    "evm.deployedBytecode.object",
 | 
				
			||||||
 | 
					                    "evm.deployedBytecode.sourceMap"
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,320 @@
 | 
				
			|||||||
 | 
					pragma solidity ^0.5;
 | 
				
			||||||
 | 
					pragma experimental ABIEncoderV2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
 | 
				
			||||||
 | 
					import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
 | 
				
			||||||
 | 
					import "./IERC20BridgeSampler.sol";
 | 
				
			||||||
 | 
					import "./IExchange.sol";
 | 
				
			||||||
 | 
					import "./IEth2Dai.sol";
 | 
				
			||||||
 | 
					import "./IKyberNetwork.sol";
 | 
				
			||||||
 | 
					import "./IUniswapExchange.sol";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					contract ERC20BridgeSampler is
 | 
				
			||||||
 | 
					    IERC20BridgeSampler
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bytes4 constant internal ERC20_PROXY_ID = bytes4(keccak256("ERC20Token(address)"));
 | 
				
			||||||
 | 
					    address constant public EXCHANGE_ADDRESS = 0x080bf510FCbF18b91105470639e9561022937712; // V2
 | 
				
			||||||
 | 
					    address constant public ETH2DAI_ADDRESS = 0x39755357759cE0d7f32dC8dC45414CCa409AE24e;
 | 
				
			||||||
 | 
					    address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
 | 
				
			||||||
 | 
					    address constant public KYBER_NETWORK_PROXY_ADDRESS = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755;
 | 
				
			||||||
 | 
					    address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
 | 
				
			||||||
 | 
					    address constant public KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function queryOrdersAndSampleSells(
 | 
				
			||||||
 | 
					        IExchange.Order[] memory orders,
 | 
				
			||||||
 | 
					        address[] memory sources,
 | 
				
			||||||
 | 
					        uint256[] memory takerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (
 | 
				
			||||||
 | 
					            IExchange.OrderInfo[] memory orderInfos,
 | 
				
			||||||
 | 
					            uint256[][] memory makerTokenAmountsBySource
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        require(orders.length != 0, "EMPTY_ORDERS");
 | 
				
			||||||
 | 
					        orderInfos = queryOrders(orders);
 | 
				
			||||||
 | 
					        makerTokenAmountsBySource = sampleSells(
 | 
				
			||||||
 | 
					            sources,
 | 
				
			||||||
 | 
					            _assetDataToTokenAddress(orders[0].takerAssetData),
 | 
				
			||||||
 | 
					            _assetDataToTokenAddress(orders[0].makerAssetData),
 | 
				
			||||||
 | 
					            takerTokenAmounts
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function queryOrdersAndSampleBuys(
 | 
				
			||||||
 | 
					        IExchange.Order[] memory orders,
 | 
				
			||||||
 | 
					        address[] memory sources,
 | 
				
			||||||
 | 
					        uint256[] memory makerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (
 | 
				
			||||||
 | 
					            IExchange.OrderInfo[] memory orderInfos,
 | 
				
			||||||
 | 
					            uint256[][] memory makerTokenAmountsBySource
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        orderInfos = queryOrders(orders);
 | 
				
			||||||
 | 
					        makerTokenAmountsBySource = sampleBuys(
 | 
				
			||||||
 | 
					            sources,
 | 
				
			||||||
 | 
					            _assetDataToTokenAddress(orders[0].takerAssetData),
 | 
				
			||||||
 | 
					            _assetDataToTokenAddress(orders[0].makerAssetData),
 | 
				
			||||||
 | 
					            makerTokenAmounts
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function queryOrders(IExchange.Order[] memory orders)
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (IExchange.OrderInfo[] memory orderInfos)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint256 numOrders = orders.length;
 | 
				
			||||||
 | 
					        orderInfos = new IExchange.OrderInfo[](numOrders);
 | 
				
			||||||
 | 
					        for (uint256 i = 0; i < numOrders; i++) {
 | 
				
			||||||
 | 
					            orderInfos[i] = IExchange(EXCHANGE_ADDRESS).getOrderInfo(orders[i]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function sampleSells(
 | 
				
			||||||
 | 
					        address[] memory sources,
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory takerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[][] memory makerTokenAmountsBySource)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint256 numSources = sources.length;
 | 
				
			||||||
 | 
					        makerTokenAmountsBySource = new uint256[][](numSources);
 | 
				
			||||||
 | 
					        for (uint256 i = 0; i < numSources; i++) {
 | 
				
			||||||
 | 
					            makerTokenAmountsBySource[i] = _sampleSellSource(
 | 
				
			||||||
 | 
					                sources[i],
 | 
				
			||||||
 | 
					                takerToken,
 | 
				
			||||||
 | 
					                makerToken,
 | 
				
			||||||
 | 
					                takerTokenAmounts
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function sampleBuys(
 | 
				
			||||||
 | 
					        address[] memory sources,
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory makerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[][] memory takerTokenAmountsBySource)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint256 numSources = sources.length;
 | 
				
			||||||
 | 
					        takerTokenAmountsBySource = new uint256[][](numSources);
 | 
				
			||||||
 | 
					        for (uint256 i = 0; i < numSources; i++) {
 | 
				
			||||||
 | 
					            takerTokenAmountsBySource[i] = _sampleBuySource(
 | 
				
			||||||
 | 
					                sources[i],
 | 
				
			||||||
 | 
					                takerToken,
 | 
				
			||||||
 | 
					                makerToken,
 | 
				
			||||||
 | 
					                makerTokenAmounts
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function sampleSellFromKyberNetwork(
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory takerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[] memory makerTokenAmounts)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        address _takerToken = takerToken == WETH_ADDRESS ? KYBER_ETH_ADDRESS : takerToken;
 | 
				
			||||||
 | 
					        address _makerToken = makerToken == WETH_ADDRESS ? KYBER_ETH_ADDRESS : makerToken;
 | 
				
			||||||
 | 
					        uint256 takerTokenDecimals = LibERC20Token(takerToken).decimals();
 | 
				
			||||||
 | 
					        uint256 makerTokenDecimals = LibERC20Token(makerToken).decimals();
 | 
				
			||||||
 | 
					        uint256 numSamples = takerTokenAmounts.length;
 | 
				
			||||||
 | 
					        makerTokenAmounts = new uint256[](numSamples);
 | 
				
			||||||
 | 
					        for (uint256 i = 0; i < numSamples; i++) {
 | 
				
			||||||
 | 
					            (uint256 rate,) = IKyberNetwork(KYBER_NETWORK_PROXY_ADDRESS).getExpectedRate(
 | 
				
			||||||
 | 
					                _takerToken,
 | 
				
			||||||
 | 
					                _makerToken,
 | 
				
			||||||
 | 
					                takerTokenAmounts[i]
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            makerTokenAmounts[i] =
 | 
				
			||||||
 | 
					                rate *
 | 
				
			||||||
 | 
					                takerTokenAmounts[i] *
 | 
				
			||||||
 | 
					                makerTokenDecimals /
 | 
				
			||||||
 | 
					                (10 ** 18 * takerTokenDecimals);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function sampleSellFromEth2Dai(
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory takerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[] memory makerTokenAmounts)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint256 numSamples = takerTokenAmounts.length;
 | 
				
			||||||
 | 
					        makerTokenAmounts = new uint256[](numSamples);
 | 
				
			||||||
 | 
					        for (uint256 i = 0; i < numSamples; i++) {
 | 
				
			||||||
 | 
					            makerTokenAmounts[i] = IEth2Dai(ETH2DAI_ADDRESS).getBuyAmount(
 | 
				
			||||||
 | 
					                makerToken,
 | 
				
			||||||
 | 
					                takerToken,
 | 
				
			||||||
 | 
					                takerTokenAmounts[i]
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function sampleBuyFromEth2Dai(
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory makerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[] memory takerTokenAmounts)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint256 numSamples = makerTokenAmounts.length;
 | 
				
			||||||
 | 
					        takerTokenAmounts = new uint256[](numSamples);
 | 
				
			||||||
 | 
					        for (uint256 i = 0; i < numSamples; i++) {
 | 
				
			||||||
 | 
					            takerTokenAmounts[i] = IEth2Dai(ETH2DAI_ADDRESS).getPayAmount(
 | 
				
			||||||
 | 
					                takerToken,
 | 
				
			||||||
 | 
					                makerToken,
 | 
				
			||||||
 | 
					                makerTokenAmounts[i]
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function sampleSellFromUniswap(
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory takerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[] memory makerTokenAmounts)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint256 numSamples = takerTokenAmounts.length;
 | 
				
			||||||
 | 
					        makerTokenAmounts = new uint256[](numSamples);
 | 
				
			||||||
 | 
					        IUniswapExchange takerTokenExchange = takerToken == WETH_ADDRESS ?
 | 
				
			||||||
 | 
					            IUniswapExchange(0) :
 | 
				
			||||||
 | 
					            IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS).getExchange(takerToken);
 | 
				
			||||||
 | 
					        IUniswapExchange makerTokenExchange = makerToken == WETH_ADDRESS ?
 | 
				
			||||||
 | 
					            IUniswapExchange(0) :
 | 
				
			||||||
 | 
					            IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS).getExchange(makerToken);
 | 
				
			||||||
 | 
					        for (uint256 i = 0; i < numSamples; i++) {
 | 
				
			||||||
 | 
					            if (makerToken == WETH_ADDRESS) {
 | 
				
			||||||
 | 
					                makerTokenAmounts[i] = takerTokenExchange.getTokenToEthInputPrice(
 | 
				
			||||||
 | 
					                    takerTokenAmounts[i]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } else if (takerToken == WETH_ADDRESS) {
 | 
				
			||||||
 | 
					                makerTokenAmounts[i] = makerTokenExchange.getEthToTokenInputPrice(
 | 
				
			||||||
 | 
					                    takerTokenAmounts[i]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                uint256 ethBought = takerTokenExchange.getTokenToEthInputPrice(
 | 
				
			||||||
 | 
					                    takerTokenAmounts[i]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                makerTokenAmounts[i] = makerTokenExchange.getEthToTokenInputPrice(
 | 
				
			||||||
 | 
					                    ethBought
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function sampleBuyFromUniswap(
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory makerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[] memory takerTokenAmounts)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint256 numSamples = makerTokenAmounts.length;
 | 
				
			||||||
 | 
					        takerTokenAmounts = new uint256[](numSamples);
 | 
				
			||||||
 | 
					        IUniswapExchange takerTokenExchange = takerToken == WETH_ADDRESS ?
 | 
				
			||||||
 | 
					            IUniswapExchange(0) :
 | 
				
			||||||
 | 
					            IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS).getExchange(takerToken);
 | 
				
			||||||
 | 
					        IUniswapExchange makerTokenExchange = makerToken == WETH_ADDRESS ?
 | 
				
			||||||
 | 
					            IUniswapExchange(0) :
 | 
				
			||||||
 | 
					            IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS).getExchange(makerToken);
 | 
				
			||||||
 | 
					        for (uint256 i = 0; i < numSamples; i++) {
 | 
				
			||||||
 | 
					            if (makerToken == WETH_ADDRESS) {
 | 
				
			||||||
 | 
					                takerTokenAmounts[i] = takerTokenExchange.getTokenToEthOutputPrice(
 | 
				
			||||||
 | 
					                    makerTokenAmounts[i]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } else if (takerToken == WETH_ADDRESS) {
 | 
				
			||||||
 | 
					                takerTokenAmounts[i] = makerTokenExchange.getEthToTokenOutputPrice(
 | 
				
			||||||
 | 
					                    makerTokenAmounts[i]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                uint256 ethSold = makerTokenExchange.getEthToTokenOutputPrice(
 | 
				
			||||||
 | 
					                    makerTokenAmounts[i]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                takerTokenAmounts[i] = takerTokenExchange.getTokenToEthOutputPrice(
 | 
				
			||||||
 | 
					                    ethSold
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function _sampleSellSource(
 | 
				
			||||||
 | 
					        address source,
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory takerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        private
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[] memory makerTokenAmounts)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (source == ETH2DAI_ADDRESS) {
 | 
				
			||||||
 | 
					            return sampleSellFromEth2Dai(takerToken, makerToken, takerTokenAmounts);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (source == UNISWAP_EXCHANGE_FACTORY_ADDRESS) {
 | 
				
			||||||
 | 
					            return sampleSellFromUniswap(takerToken, makerToken, takerTokenAmounts);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (source == KYBER_NETWORK_PROXY_ADDRESS) {
 | 
				
			||||||
 | 
					            return sampleSellFromKyberNetwork(takerToken, makerToken, takerTokenAmounts);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        revert("UNSUPPORTED_SOURCE");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function _sampleBuySource(
 | 
				
			||||||
 | 
					        address source,
 | 
				
			||||||
 | 
					        address takerToken,
 | 
				
			||||||
 | 
					        address makerToken,
 | 
				
			||||||
 | 
					        uint256[] memory makerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        private
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256[] memory takerTokenAmounts)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (source == ETH2DAI_ADDRESS) {
 | 
				
			||||||
 | 
					            return sampleBuyFromEth2Dai(takerToken, makerToken, makerTokenAmounts);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (source == UNISWAP_EXCHANGE_FACTORY_ADDRESS) {
 | 
				
			||||||
 | 
					            return sampleBuyFromUniswap(takerToken, makerToken, makerTokenAmounts);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        revert("UNSUPPORTED_SOURCE");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function _assetDataToTokenAddress(bytes memory assetData)
 | 
				
			||||||
 | 
					        private
 | 
				
			||||||
 | 
					        pure
 | 
				
			||||||
 | 
					        returns (address tokenAddress)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        require(assetData.length == 36, "INVALID_ASSET_DATA");
 | 
				
			||||||
 | 
					        bytes4 selector;
 | 
				
			||||||
 | 
					        assembly {
 | 
				
			||||||
 | 
					            selector := and(mload(add(assetData, 0x20)), 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
 | 
				
			||||||
 | 
					            tokenAddress := mload(add(assetData, 0x24))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        require(selector == ERC20_PROXY_ID, "UNSUPPORTED_ASSET_PROXY");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					pragma solidity ^0.5;
 | 
				
			||||||
 | 
					pragma experimental ABIEncoderV2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "./IExchange.sol";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IERC20BridgeSampler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Query native orders and sample sell orders on multiple DEXes at once.
 | 
				
			||||||
 | 
					    /// @param orders Native orders to query.
 | 
				
			||||||
 | 
					    /// @param sources Address of each DEX. Passing in an unknown DEX will throw.
 | 
				
			||||||
 | 
					    /// @param takerTokenAmounts Taker sell amount for each sample.
 | 
				
			||||||
 | 
					    /// @return orderInfos `OrderInfo`s for each order in `orders`.
 | 
				
			||||||
 | 
					    /// @return makerTokenAmountsBySource Maker amounts bought for each source at
 | 
				
			||||||
 | 
					    ///         each taker token amount. First indexed by source index, then sample
 | 
				
			||||||
 | 
					    ///         index.
 | 
				
			||||||
 | 
					    function queryOrdersAndSampleSells(
 | 
				
			||||||
 | 
					        IExchange.Order[] calldata orders,
 | 
				
			||||||
 | 
					        address[] calldata sources,
 | 
				
			||||||
 | 
					        uint256[] calldata takerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (
 | 
				
			||||||
 | 
					            IExchange.OrderInfo[] memory orderInfos,
 | 
				
			||||||
 | 
					            uint256[][] memory makerTokenAmountsBySource
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Query native orders and sample buy orders on multiple DEXes at once.
 | 
				
			||||||
 | 
					    /// @param orders Native orders to query.
 | 
				
			||||||
 | 
					    /// @param sources Address of each DEX. Passing in an unknown DEX will throw.
 | 
				
			||||||
 | 
					    /// @param makerTokenAmounts Maker sell amount for each sample.
 | 
				
			||||||
 | 
					    /// @return orderInfos `OrderInfo`s for each order in `orders`.
 | 
				
			||||||
 | 
					    /// @return takerTokenAmountsBySource Taker amounts sold for each source at
 | 
				
			||||||
 | 
					    ///         each maker token amount. First indexed by source index, then sample
 | 
				
			||||||
 | 
					    ///         index.
 | 
				
			||||||
 | 
					    function queryOrdersAndSampleBuys(
 | 
				
			||||||
 | 
					        IExchange.Order[] calldata orders,
 | 
				
			||||||
 | 
					        address[] calldata sources,
 | 
				
			||||||
 | 
					        uint256[] calldata makerTokenAmounts
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (
 | 
				
			||||||
 | 
					            IExchange.OrderInfo[] memory orderInfos,
 | 
				
			||||||
 | 
					            uint256[][] memory makerTokenAmountsBySource
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										21
									
								
								contracts/erc20-bridge-sampler/contracts/src/IEth2Dai.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								contracts/erc20-bridge-sampler/contracts/src/IEth2Dai.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					pragma solidity ^0.5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					contract IEth2Dai {
 | 
				
			||||||
 | 
					    function getBuyAmount(
 | 
				
			||||||
 | 
					        address buyToken,
 | 
				
			||||||
 | 
					        address payToken,
 | 
				
			||||||
 | 
					        uint256 payAmount
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256 buyAmount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function getPayAmount(
 | 
				
			||||||
 | 
					        address payToken,
 | 
				
			||||||
 | 
					        address buyToken,
 | 
				
			||||||
 | 
					        uint256 buyAmount
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256 payAmount);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								contracts/erc20-bridge-sampler/contracts/src/IExchange.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								contracts/erc20-bridge-sampler/contracts/src/IExchange.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					pragma solidity ^0.5;
 | 
				
			||||||
 | 
					pragma experimental ABIEncoderV2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IExchange {
 | 
				
			||||||
 | 
					    struct Order {
 | 
				
			||||||
 | 
					        address makerAddress;
 | 
				
			||||||
 | 
					        address takerAddress;
 | 
				
			||||||
 | 
					        address feeRecipientAddress;
 | 
				
			||||||
 | 
					        address senderAddress;
 | 
				
			||||||
 | 
					        uint256 makerAssetAmount;
 | 
				
			||||||
 | 
					        uint256 takerAssetAmount;
 | 
				
			||||||
 | 
					        uint256 makerFee;
 | 
				
			||||||
 | 
					        uint256 takerFee;
 | 
				
			||||||
 | 
					        uint256 expirationTimeSeconds;
 | 
				
			||||||
 | 
					        uint256 salt;
 | 
				
			||||||
 | 
					        bytes makerAssetData;
 | 
				
			||||||
 | 
					        bytes takerAssetData;
 | 
				
			||||||
 | 
					        // bytes makerFeeAssetData;
 | 
				
			||||||
 | 
					        // bytes takerFeeAssetData;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct OrderInfo {
 | 
				
			||||||
 | 
					        uint8 orderStatus;
 | 
				
			||||||
 | 
					        bytes32 orderHash;
 | 
				
			||||||
 | 
					        uint256 orderTakerAssetFilledAmount;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function getOrderInfo(Order calldata order)
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (OrderInfo memory orderInfo);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					pragma solidity ^0.5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					contract IKyberNetwork {
 | 
				
			||||||
 | 
					    function getExpectedRate(
 | 
				
			||||||
 | 
					        address fromToken,
 | 
				
			||||||
 | 
					        address toToken,
 | 
				
			||||||
 | 
					        uint256 fromAmount
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        public
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256 expectedRate, uint256 slippageRate);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					pragma solidity ^0.5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IUniswapExchange {
 | 
				
			||||||
 | 
					    function getEthToTokenInputPrice(
 | 
				
			||||||
 | 
					        uint256 ethSold
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256 tokensBought);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function getEthToTokenOutputPrice(
 | 
				
			||||||
 | 
					        uint256 tokensBought
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256 ethSold);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function getTokenToEthInputPrice(
 | 
				
			||||||
 | 
					        uint256 tokensSold
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256 ethBought);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function getTokenToEthOutputPrice(
 | 
				
			||||||
 | 
					        uint256 ethBought
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint256 tokensSold);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,98 @@
 | 
				
			|||||||
 | 
					pragma solidity ^0.5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					library LibERC20Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Calls `IERC20Token(token).approve()`.
 | 
				
			||||||
 | 
					    ///      Reverts if `false` is returned or if the return
 | 
				
			||||||
 | 
					    ///      data length is nonzero and not 32 bytes.
 | 
				
			||||||
 | 
					    /// @param token The address of the token contract.
 | 
				
			||||||
 | 
					    /// @param spender The address that receives an allowance.
 | 
				
			||||||
 | 
					    /// @param allowance The allowance to set.
 | 
				
			||||||
 | 
					    function approve(
 | 
				
			||||||
 | 
					        address token,
 | 
				
			||||||
 | 
					        address spender,
 | 
				
			||||||
 | 
					        uint256 allowance
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        internal
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        bytes memory callData = abi.encodeWithSelector(
 | 
				
			||||||
 | 
					            0x095ea7b3,
 | 
				
			||||||
 | 
					            spender,
 | 
				
			||||||
 | 
					            allowance
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        _callWithOptionalBooleanResult(token, callData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Calls `IERC20Token(token).transfer()`.
 | 
				
			||||||
 | 
					    ///      Reverts if `false` is returned or if the return
 | 
				
			||||||
 | 
					    ///      data length is nonzero and not 32 bytes.
 | 
				
			||||||
 | 
					    /// @param token The address of the token contract.
 | 
				
			||||||
 | 
					    /// @param to The address that receives the tokens
 | 
				
			||||||
 | 
					    /// @param amount Number of tokens to transfer.
 | 
				
			||||||
 | 
					    function transfer(
 | 
				
			||||||
 | 
					        address token,
 | 
				
			||||||
 | 
					        address to,
 | 
				
			||||||
 | 
					        uint256 amount
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        internal
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        bytes memory callData = abi.encodeWithSelector(
 | 
				
			||||||
 | 
					            0xa9059cbb,
 | 
				
			||||||
 | 
					            to,
 | 
				
			||||||
 | 
					            amount
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        _callWithOptionalBooleanResult(token, callData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Calls `IERC20Token(token).transferFrom()`.
 | 
				
			||||||
 | 
					    ///      Reverts if `false` is returned or if the return
 | 
				
			||||||
 | 
					    ///      data length is nonzero and not 32 bytes.
 | 
				
			||||||
 | 
					    /// @param token The address of the token contract.
 | 
				
			||||||
 | 
					    /// @param from The owner of the tokens.
 | 
				
			||||||
 | 
					    /// @param to The address that receives the tokens
 | 
				
			||||||
 | 
					    /// @param amount Number of tokens to transfer.
 | 
				
			||||||
 | 
					    function transferFrom(
 | 
				
			||||||
 | 
					        address token,
 | 
				
			||||||
 | 
					        address from,
 | 
				
			||||||
 | 
					        address to,
 | 
				
			||||||
 | 
					        uint256 amount
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        internal
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        bytes memory callData = abi.encodeWithSelector(
 | 
				
			||||||
 | 
					            0x23b872dd,
 | 
				
			||||||
 | 
					            from,
 | 
				
			||||||
 | 
					            to,
 | 
				
			||||||
 | 
					            amount
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        _callWithOptionalBooleanResult(token, callData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Executes a call on address `target` with calldata `callData`
 | 
				
			||||||
 | 
					    ///      and asserts that either nothing was returned or a single boolean
 | 
				
			||||||
 | 
					    ///      was returned equal to `true`.
 | 
				
			||||||
 | 
					    /// @param target The call target.
 | 
				
			||||||
 | 
					    /// @param callData The abi-encoded call data.
 | 
				
			||||||
 | 
					    function _callWithOptionalBooleanResult(
 | 
				
			||||||
 | 
					        address target,
 | 
				
			||||||
 | 
					        bytes memory callData
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        private
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        (bool didSucceed, bytes memory resultData) = target.call(callData);
 | 
				
			||||||
 | 
					        if (didSucceed) {
 | 
				
			||||||
 | 
					            if (resultData.length == 0) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (resultData.length == 32) {
 | 
				
			||||||
 | 
					                uint256 result;
 | 
				
			||||||
 | 
					                assembly { result := mload(add(resultData, 0x20)) }
 | 
				
			||||||
 | 
					                if (result == 1) {
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        assembly { revert(add(resultData, 0x20), mload(resultData)) }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										91
									
								
								contracts/erc20-bridge-sampler/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								contracts/erc20-bridge-sampler/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "name": "@0x/contracts-erc20-bridge-sampler",
 | 
				
			||||||
 | 
					    "version": "1.0.0-beta.1",
 | 
				
			||||||
 | 
					    "engines": {
 | 
				
			||||||
 | 
					        "node": ">=6.12"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "description": "Sampler contracts for the 0x asset-swapper",
 | 
				
			||||||
 | 
					    "main": "lib/src/index.js",
 | 
				
			||||||
 | 
					    "directories": {
 | 
				
			||||||
 | 
					        "test": "test"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "scripts": {
 | 
				
			||||||
 | 
					        "build": "yarn pre_build && tsc -b",
 | 
				
			||||||
 | 
					        "build:ci": "yarn build",
 | 
				
			||||||
 | 
					        "pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy",
 | 
				
			||||||
 | 
					        "test": "yarn run_mocha",
 | 
				
			||||||
 | 
					        "rebuild_and_test": "run-s build test",
 | 
				
			||||||
 | 
					        "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
 | 
				
			||||||
 | 
					        "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
 | 
				
			||||||
 | 
					        "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
 | 
				
			||||||
 | 
					        "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
 | 
				
			||||||
 | 
					        "compile": "sol-compiler",
 | 
				
			||||||
 | 
					        "watch": "sol-compiler -w",
 | 
				
			||||||
 | 
					        "clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
 | 
				
			||||||
 | 
					        "generate_contract_wrappers": "abi-gen --debug --abis  ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
 | 
				
			||||||
 | 
					        "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
				
			||||||
 | 
					        "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-wrappers/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
				
			||||||
 | 
					        "coverage:report:text": "istanbul report text",
 | 
				
			||||||
 | 
					        "coverage:report:html": "istanbul report html && open coverage/index.html",
 | 
				
			||||||
 | 
					        "profiler:report:html": "istanbul report html && open coverage/index.html",
 | 
				
			||||||
 | 
					        "coverage:report:lcov": "istanbul report lcov",
 | 
				
			||||||
 | 
					        "test:circleci": "yarn test",
 | 
				
			||||||
 | 
					        "contracts:gen": "contracts-gen generate",
 | 
				
			||||||
 | 
					        "contracts:copy": "contracts-gen copy",
 | 
				
			||||||
 | 
					        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
 | 
				
			||||||
 | 
					        "compile:truffle": "truffle compile"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "config": {
 | 
				
			||||||
 | 
					        "publicInterfaceContracts": "ERC20BridgeSampler",
 | 
				
			||||||
 | 
					        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
 | 
				
			||||||
 | 
					        "abis": "./test/generated-artifacts/@(Exchange|IAssetProxy|IAssetProxyDispatcher|IEIP1271Data|IEIP1271Wallet|IExchange|IExchangeCore|IMatchOrders|IProtocolFees|ISignatureValidator|ITransactions|ITransferSimulator|IWallet|IWrapperFunctions|IsolatedExchange|LibExchangeRichErrorDecoder|MixinAssetProxyDispatcher|MixinExchangeCore|MixinMatchOrders|MixinProtocolFees|MixinSignatureValidator|MixinTransactions|MixinTransferSimulator|MixinWrapperFunctions|ReentrancyTester|TestAssetProxyDispatcher|TestExchangeInternals|TestFillRounding|TestLibExchangeRichErrorDecoder|TestProtocolFeeCollector|TestProtocolFees|TestProtocolFeesReceiver|TestSignatureValidator|TestTransactions|TestValidatorWallet|TestWrapperFunctions).json"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "repository": {
 | 
				
			||||||
 | 
					        "type": "git",
 | 
				
			||||||
 | 
					        "url": "https://github.com/0xProject/0x-monorepo.git"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "license": "Apache-2.0",
 | 
				
			||||||
 | 
					    "bugs": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/0xProject/0x-monorepo/issues"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
 | 
				
			||||||
 | 
					    "devDependencies": {
 | 
				
			||||||
 | 
					        "@0x/abi-gen": "^4.4.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/contracts-asset-proxy": "^2.3.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/contracts-erc20": "^2.3.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/contracts-exchange-libs": "^3.1.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/contracts-gen": "^1.1.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/contracts-test-utils": "^3.2.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/contracts-utils": "^3.3.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/dev-utils": "^2.4.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/sol-compiler": "^3.2.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/tslint-config": "^3.1.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/web3-wrapper": "^6.1.0-beta.1",
 | 
				
			||||||
 | 
					        "@types/lodash": "4.14.104",
 | 
				
			||||||
 | 
					        "@types/mocha": "^5.2.7",
 | 
				
			||||||
 | 
					        "@types/node": "*",
 | 
				
			||||||
 | 
					        "chai": "^4.0.1",
 | 
				
			||||||
 | 
					        "chai-as-promised": "^7.1.0",
 | 
				
			||||||
 | 
					        "chai-bignumber": "^3.0.0",
 | 
				
			||||||
 | 
					        "dirty-chai": "^2.0.1",
 | 
				
			||||||
 | 
					        "make-promises-safe": "^1.1.0",
 | 
				
			||||||
 | 
					        "mocha": "^6.2.0",
 | 
				
			||||||
 | 
					        "npm-run-all": "^4.1.2",
 | 
				
			||||||
 | 
					        "shx": "^0.2.2",
 | 
				
			||||||
 | 
					        "solhint": "^1.4.1",
 | 
				
			||||||
 | 
					        "truffle": "^5.0.32",
 | 
				
			||||||
 | 
					        "tslint": "5.11.0",
 | 
				
			||||||
 | 
					        "typescript": "3.0.1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "dependencies": {
 | 
				
			||||||
 | 
					        "@0x/base-contract": "^5.5.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/types": "^2.5.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/typescript-typings": "^4.4.0-beta.1",
 | 
				
			||||||
 | 
					        "@0x/utils": "^4.6.0-beta.1",
 | 
				
			||||||
 | 
					        "ethereum-types": "^2.2.0-beta.1",
 | 
				
			||||||
 | 
					        "lodash": "^4.17.11"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "publishConfig": {
 | 
				
			||||||
 | 
					        "access": "public"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										0
									
								
								contracts/erc20-bridge-sampler/src/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								contracts/erc20-bridge-sampler/src/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								contracts/erc20-bridge-sampler/test/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								contracts/erc20-bridge-sampler/test/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										96
									
								
								contracts/erc20-bridge-sampler/truffle-config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								contracts/erc20-bridge-sampler/truffle-config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Use this file to configure your truffle project. It's seeded with some
 | 
				
			||||||
 | 
					 * common settings for different networks and features like migrations,
 | 
				
			||||||
 | 
					 * compilation and testing. Uncomment the ones you need or modify
 | 
				
			||||||
 | 
					 * them to suit your project as necessary.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * More information about configuration can be found at:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * truffleframework.com/docs/advanced/configuration
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider)
 | 
				
			||||||
 | 
					 * to sign your transactions before they're sent to a remote public node. Infura accounts
 | 
				
			||||||
 | 
					 * are available for free at: infura.io/register.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate
 | 
				
			||||||
 | 
					 * public/private key pairs. If you're publishing your code to GitHub make sure you load this
 | 
				
			||||||
 | 
					 * phrase from a file you've .gitignored so it doesn't accidentally become public.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// const HDWalletProvider = require('truffle-hdwallet-provider');
 | 
				
			||||||
 | 
					// const infuraKey = "fj4jll3k.....";
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// const fs = require('fs');
 | 
				
			||||||
 | 
					// const mnemonic = fs.readFileSync(".secret").toString().trim();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Networks define how you connect to your ethereum client and let you set the
 | 
				
			||||||
 | 
					     * defaults web3 uses to send transactions. If you don't specify one truffle
 | 
				
			||||||
 | 
					     * will spin up a development blockchain for you on port 9545 when you
 | 
				
			||||||
 | 
					     * run `develop` or `test`. You can ask a truffle command to use a specific
 | 
				
			||||||
 | 
					     * network from the command line, e.g
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * $ truffle test --network <network-name>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    networks: {
 | 
				
			||||||
 | 
					        // Useful for testing. The `development` name is special - truffle uses it by default
 | 
				
			||||||
 | 
					        // if it's defined here and no other network is specified at the command line.
 | 
				
			||||||
 | 
					        // You should run a client (like ganache-cli, geth or parity) in a separate terminal
 | 
				
			||||||
 | 
					        // tab if you use this network and you must also set the `host`, `port` and `network_id`
 | 
				
			||||||
 | 
					        // options below to some value.
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // development: {
 | 
				
			||||||
 | 
					        //  host: "127.0.0.1",     // Localhost (default: none)
 | 
				
			||||||
 | 
					        //  port: 8545,            // Standard Ethereum port (default: none)
 | 
				
			||||||
 | 
					        //  network_id: "*",       // Any network (default: none)
 | 
				
			||||||
 | 
					        // },
 | 
				
			||||||
 | 
					        // Another network with more advanced options...
 | 
				
			||||||
 | 
					        // advanced: {
 | 
				
			||||||
 | 
					        // port: 8777,             // Custom port
 | 
				
			||||||
 | 
					        // network_id: 1342,       // Custom network
 | 
				
			||||||
 | 
					        // gas: 8500000,           // Gas sent with each transaction (default: ~6700000)
 | 
				
			||||||
 | 
					        // gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)
 | 
				
			||||||
 | 
					        // from: <address>,        // Account to send txs from (default: accounts[0])
 | 
				
			||||||
 | 
					        // websockets: true        // Enable EventEmitter interface for web3 (default: false)
 | 
				
			||||||
 | 
					        // },
 | 
				
			||||||
 | 
					        // Useful for deploying to a public network.
 | 
				
			||||||
 | 
					        // NB: It's important to wrap the provider as a function.
 | 
				
			||||||
 | 
					        // ropsten: {
 | 
				
			||||||
 | 
					        // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
 | 
				
			||||||
 | 
					        // network_id: 3,       // Ropsten's id
 | 
				
			||||||
 | 
					        // gas: 5500000,        // Ropsten has a lower block limit than mainnet
 | 
				
			||||||
 | 
					        // confirmations: 2,    // # of confs to wait between deployments. (default: 0)
 | 
				
			||||||
 | 
					        // timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
 | 
				
			||||||
 | 
					        // skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
 | 
				
			||||||
 | 
					        // },
 | 
				
			||||||
 | 
					        // Useful for private networks
 | 
				
			||||||
 | 
					        // private: {
 | 
				
			||||||
 | 
					        // provider: () => new HDWalletProvider(mnemonic, `https://network.io`),
 | 
				
			||||||
 | 
					        // network_id: 2111,   // This network is yours, in the cloud.
 | 
				
			||||||
 | 
					        // production: true    // Treats this network as if it was a public net. (default: false)
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Set default mocha options here, use special reporters etc.
 | 
				
			||||||
 | 
					    mocha: {
 | 
				
			||||||
 | 
					        // timeout: 100000
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Configure your compilers
 | 
				
			||||||
 | 
					    compilers: {
 | 
				
			||||||
 | 
					        solc: {
 | 
				
			||||||
 | 
					            version: '0.5.9',
 | 
				
			||||||
 | 
					            settings: {
 | 
				
			||||||
 | 
					                evmVersion: 'constantinople',
 | 
				
			||||||
 | 
					                optimizer: {
 | 
				
			||||||
 | 
					                    enabled: true,
 | 
				
			||||||
 | 
					                    runs: 1000000,
 | 
				
			||||||
 | 
					                    details: { yul: true, deduplicate: true, cse: true, constantOptimizer: true },
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										46
									
								
								contracts/erc20-bridge-sampler/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								contracts/erc20-bridge-sampler/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "extends": "../../tsconfig",
 | 
				
			||||||
 | 
					    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
				
			||||||
 | 
					    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
				
			||||||
 | 
					    "files": [
 | 
				
			||||||
 | 
					        "generated-artifacts/Exchange.json",
 | 
				
			||||||
 | 
					        "generated-artifacts/IExchange.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/Exchange.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IAssetProxy.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IAssetProxyDispatcher.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IEIP1271Data.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IEIP1271Wallet.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IExchange.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IExchangeCore.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IMatchOrders.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IProtocolFees.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/ISignatureValidator.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/ITransactions.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/ITransferSimulator.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IWallet.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IWrapperFunctions.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IsolatedExchange.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/LibExchangeRichErrorDecoder.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/MixinAssetProxyDispatcher.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/MixinExchangeCore.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/MixinMatchOrders.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/MixinProtocolFees.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/MixinSignatureValidator.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/MixinTransactions.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/MixinTransferSimulator.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/MixinWrapperFunctions.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/ReentrancyTester.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestAssetProxyDispatcher.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestExchangeInternals.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestFillRounding.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestLibExchangeRichErrorDecoder.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestProtocolFeeCollector.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestProtocolFees.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestProtocolFeesReceiver.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestSignatureValidator.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestTransactions.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestValidatorWallet.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/TestWrapperFunctions.json"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "exclude": ["./deploy/solc/solc_bin"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								contracts/erc20-bridge-sampler/tslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								contracts/erc20-bridge-sampler/tslint.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "extends": ["@0x/tslint-config"],
 | 
				
			||||||
 | 
					    "rules": {
 | 
				
			||||||
 | 
					        "custom-no-magic-numbers": false,
 | 
				
			||||||
 | 
					        "max-file-line-count": false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "linterOptions": {
 | 
				
			||||||
 | 
					        "exclude": ["src/artifacts.ts"]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -14,6 +14,10 @@
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
 | 
					                "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
 | 
				
			||||||
                "pr": 2330
 | 
					                "pr": 2330
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "note": "Add `decimals()` to `LibERC20Token`.",
 | 
				
			||||||
 | 
					                "pr": "TODO"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        "timestamp": 1574030254
 | 
					        "timestamp": 1574030254
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@ import "../src/interfaces/IERC20Token.sol";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
library LibERC20Token {
 | 
					library LibERC20Token {
 | 
				
			||||||
 | 
					    bytes constant private DECIMALS_CALL_DATA = hex"313ce567";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// @dev Calls `IERC20Token(token).approve()`.
 | 
					    /// @dev Calls `IERC20Token(token).approve()`.
 | 
				
			||||||
    ///      Reverts if `false` is returned or if the return
 | 
					    ///      Reverts if `false` is returned or if the return
 | 
				
			||||||
@@ -91,6 +92,21 @@ library LibERC20Token {
 | 
				
			|||||||
        _callWithOptionalBooleanResult(token, callData);
 | 
					        _callWithOptionalBooleanResult(token, callData);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Retrieves the number of decimals for a token.
 | 
				
			||||||
 | 
					    ///      Returns `18` if the call reverts.
 | 
				
			||||||
 | 
					    /// @return The number of decimals places for the token.
 | 
				
			||||||
 | 
					    function decimals(address token)
 | 
				
			||||||
 | 
					        internal
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint8 tokenDecimals)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        tokenDecimals = 18;
 | 
				
			||||||
 | 
					        (bool didSucceed, bytes memory resultData) = token.staticcall(DECIMALS_CALL_DATA);
 | 
				
			||||||
 | 
					        if (didSucceed && resultData.length == 32) {
 | 
				
			||||||
 | 
					            tokenDecimals = uint8(LibBytes.readUint256(resultData, 0));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// @dev Executes a call on address `target` with calldata `callData`
 | 
					    /// @dev Executes a call on address `target` with calldata `callData`
 | 
				
			||||||
    ///      and asserts that either nothing was returned or a single boolean
 | 
					    ///      and asserts that either nothing was returned or a single boolean
 | 
				
			||||||
    ///      was returned equal to `true`.
 | 
					    ///      was returned equal to `true`.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,4 +69,16 @@ contract TestLibERC20Token {
 | 
				
			|||||||
        target.setBehavior(shouldRevert, revertData, returnData);
 | 
					        target.setBehavior(shouldRevert, revertData, returnData);
 | 
				
			||||||
        LibERC20Token.transferFrom(address(target), from, to, amount);
 | 
					        LibERC20Token.transferFrom(address(target), from, to, amount);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function testDecimals(
 | 
				
			||||||
 | 
					        bool shouldRevert,
 | 
				
			||||||
 | 
					        bytes calldata revertData,
 | 
				
			||||||
 | 
					        bytes calldata returnData
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        returns (uint8)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        target.setBehavior(shouldRevert, revertData, returnData);
 | 
				
			||||||
 | 
					        return LibERC20Token.decimals(address(target));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,14 @@ contract TestLibERC20TokenTarget {
 | 
				
			|||||||
        _execute();
 | 
					        _execute();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function decimals()
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (uint8)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        _execute();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function _execute() private view {
 | 
					    function _execute() private view {
 | 
				
			||||||
        if (_shouldRevert) {
 | 
					        if (_shouldRevert) {
 | 
				
			||||||
            bytes memory revertData = _revertData;
 | 
					            bytes memory revertData = _revertData;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ import { artifacts } from './artifacts';
 | 
				
			|||||||
blockchainTests('LibERC20Token', env => {
 | 
					blockchainTests('LibERC20Token', env => {
 | 
				
			||||||
    let testContract: TestLibERC20TokenContract;
 | 
					    let testContract: TestLibERC20TokenContract;
 | 
				
			||||||
    const REVERT_STRING = 'WHOOPSIE';
 | 
					    const REVERT_STRING = 'WHOOPSIE';
 | 
				
			||||||
 | 
					    const ENCODED_REVERT = new StringRevertError(REVERT_STRING).encode();
 | 
				
			||||||
    const ENCODED_TRUE = hexLeftPad(1);
 | 
					    const ENCODED_TRUE = hexLeftPad(1);
 | 
				
			||||||
    const ENCODED_FALSE = hexLeftPad(0);
 | 
					    const ENCODED_FALSE = hexLeftPad(0);
 | 
				
			||||||
    const ENCODED_TWO = hexLeftPad(2);
 | 
					    const ENCODED_TWO = hexLeftPad(2);
 | 
				
			||||||
@@ -31,16 +32,12 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function encodeRevert(message: string): string {
 | 
					 | 
				
			||||||
        return new StringRevertError(message).encode();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    describe('approve()', () => {
 | 
					    describe('approve()', () => {
 | 
				
			||||||
        it('calls the target with the correct arguments', async () => {
 | 
					        it('calls the target with the correct arguments', async () => {
 | 
				
			||||||
            const spender = randomAddress();
 | 
					            const spender = randomAddress();
 | 
				
			||||||
            const allowance = getRandomInteger(0, 100e18);
 | 
					            const allowance = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const { logs } = await testContract
 | 
					            const { logs } = await testContract
 | 
				
			||||||
                .testApprove(false, encodeRevert(REVERT_STRING), ENCODED_TRUE, spender, allowance)
 | 
					                .testApprove(false, ENCODED_REVERT, ENCODED_TRUE, spender, allowance)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            expect(logs).to.be.length(1);
 | 
					            expect(logs).to.be.length(1);
 | 
				
			||||||
            verifyEventsFromLogs(logs, [{ spender, allowance }], TestLibERC20TokenTargetEvents.ApproveCalled);
 | 
					            verifyEventsFromLogs(logs, [{ spender, allowance }], TestLibERC20TokenTargetEvents.ApproveCalled);
 | 
				
			||||||
@@ -50,7 +47,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const spender = randomAddress();
 | 
					            const spender = randomAddress();
 | 
				
			||||||
            const allowance = getRandomInteger(0, 100e18);
 | 
					            const allowance = getRandomInteger(0, 100e18);
 | 
				
			||||||
            await testContract
 | 
					            await testContract
 | 
				
			||||||
                .testApprove(false, encodeRevert(REVERT_STRING), ENCODED_TRUE, spender, allowance)
 | 
					                .testApprove(false, ENCODED_REVERT, ENCODED_TRUE, spender, allowance)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,7 +55,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const spender = randomAddress();
 | 
					            const spender = randomAddress();
 | 
				
			||||||
            const allowance = getRandomInteger(0, 100e18);
 | 
					            const allowance = getRandomInteger(0, 100e18);
 | 
				
			||||||
            await testContract
 | 
					            await testContract
 | 
				
			||||||
                .testApprove(false, encodeRevert(REVERT_STRING), constants.NULL_BYTES, spender, allowance)
 | 
					                .testApprove(false, ENCODED_REVERT, constants.NULL_BYTES, spender, allowance)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,7 +63,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const spender = randomAddress();
 | 
					            const spender = randomAddress();
 | 
				
			||||||
            const allowance = getRandomInteger(0, 100e18);
 | 
					            const allowance = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testApprove(false, encodeRevert(REVERT_STRING), ENCODED_FALSE, spender, allowance)
 | 
					                .testApprove(false, ENCODED_REVERT, ENCODED_FALSE, spender, allowance)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
					            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -76,7 +73,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const spender = randomAddress();
 | 
					            const spender = randomAddress();
 | 
				
			||||||
            const allowance = getRandomInteger(0, 100e18);
 | 
					            const allowance = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testApprove(false, encodeRevert(REVERT_STRING), ENCODED_TWO, spender, allowance)
 | 
					                .testApprove(false, ENCODED_REVERT, ENCODED_TWO, spender, allowance)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
					            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -86,7 +83,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const spender = randomAddress();
 | 
					            const spender = randomAddress();
 | 
				
			||||||
            const allowance = getRandomInteger(0, 100e18);
 | 
					            const allowance = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testApprove(false, encodeRevert(REVERT_STRING), ENCODED_SHORT_TRUE, spender, allowance)
 | 
					                .testApprove(false, ENCODED_REVERT, ENCODED_SHORT_TRUE, spender, allowance)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
					            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -96,7 +93,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const spender = randomAddress();
 | 
					            const spender = randomAddress();
 | 
				
			||||||
            const allowance = getRandomInteger(0, 100e18);
 | 
					            const allowance = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testApprove(false, encodeRevert(REVERT_STRING), ENCODED_LONG_TRUE, spender, allowance)
 | 
					                .testApprove(false, ENCODED_REVERT, ENCODED_LONG_TRUE, spender, allowance)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
					            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -106,7 +103,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const spender = randomAddress();
 | 
					            const spender = randomAddress();
 | 
				
			||||||
            const allowance = getRandomInteger(0, 100e18);
 | 
					            const allowance = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testApprove(true, encodeRevert(REVERT_STRING), ENCODED_TRUE, spender, allowance)
 | 
					                .testApprove(true, ENCODED_REVERT, ENCODED_TRUE, spender, allowance)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            return expect(tx).to.revertWith(REVERT_STRING);
 | 
					            return expect(tx).to.revertWith(REVERT_STRING);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@@ -126,7 +123,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const { logs } = await testContract
 | 
					            const { logs } = await testContract
 | 
				
			||||||
                .testTransfer(false, encodeRevert(REVERT_STRING), ENCODED_TRUE, to, amount)
 | 
					                .testTransfer(false, ENCODED_REVERT, ENCODED_TRUE, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            expect(logs).to.be.length(1);
 | 
					            expect(logs).to.be.length(1);
 | 
				
			||||||
            verifyEventsFromLogs(logs, [{ to, amount }], TestLibERC20TokenTargetEvents.TransferCalled);
 | 
					            verifyEventsFromLogs(logs, [{ to, amount }], TestLibERC20TokenTargetEvents.TransferCalled);
 | 
				
			||||||
@@ -136,7 +133,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            await testContract
 | 
					            await testContract
 | 
				
			||||||
                .testTransfer(false, encodeRevert(REVERT_STRING), ENCODED_TRUE, to, amount)
 | 
					                .testTransfer(false, ENCODED_REVERT, ENCODED_TRUE, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -144,7 +141,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            await testContract
 | 
					            await testContract
 | 
				
			||||||
                .testTransfer(false, encodeRevert(REVERT_STRING), constants.NULL_BYTES, to, amount)
 | 
					                .testTransfer(false, ENCODED_REVERT, constants.NULL_BYTES, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -152,7 +149,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransfer(false, encodeRevert(REVERT_STRING), ENCODED_FALSE, to, amount)
 | 
					                .testTransfer(false, ENCODED_REVERT, ENCODED_FALSE, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
					            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -162,7 +159,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransfer(false, encodeRevert(REVERT_STRING), ENCODED_TWO, to, amount)
 | 
					                .testTransfer(false, ENCODED_REVERT, ENCODED_TWO, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
					            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -172,7 +169,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransfer(false, encodeRevert(REVERT_STRING), ENCODED_SHORT_TRUE, to, amount)
 | 
					                .testTransfer(false, ENCODED_REVERT, ENCODED_SHORT_TRUE, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
					            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -182,7 +179,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransfer(false, encodeRevert(REVERT_STRING), ENCODED_LONG_TRUE, to, amount)
 | 
					                .testTransfer(false, ENCODED_REVERT, ENCODED_LONG_TRUE, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
					            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -192,7 +189,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransfer(true, encodeRevert(REVERT_STRING), ENCODED_TRUE, to, amount)
 | 
					                .testTransfer(true, ENCODED_REVERT, ENCODED_TRUE, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            return expect(tx).to.revertWith(REVERT_STRING);
 | 
					            return expect(tx).to.revertWith(REVERT_STRING);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@@ -213,7 +210,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const { logs } = await testContract
 | 
					            const { logs } = await testContract
 | 
				
			||||||
                .testTransferFrom(false, encodeRevert(REVERT_STRING), ENCODED_TRUE, owner, to, amount)
 | 
					                .testTransferFrom(false, ENCODED_REVERT, ENCODED_TRUE, owner, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            expect(logs).to.be.length(1);
 | 
					            expect(logs).to.be.length(1);
 | 
				
			||||||
            verifyEventsFromLogs(logs, [{ from: owner, to, amount }], TestLibERC20TokenTargetEvents.TransferFromCalled);
 | 
					            verifyEventsFromLogs(logs, [{ from: owner, to, amount }], TestLibERC20TokenTargetEvents.TransferFromCalled);
 | 
				
			||||||
@@ -224,7 +221,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            await testContract
 | 
					            await testContract
 | 
				
			||||||
                .testTransferFrom(false, encodeRevert(REVERT_STRING), ENCODED_TRUE, owner, to, amount)
 | 
					                .testTransferFrom(false, ENCODED_REVERT, ENCODED_TRUE, owner, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -233,7 +230,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            await testContract
 | 
					            await testContract
 | 
				
			||||||
                .testTransferFrom(false, encodeRevert(REVERT_STRING), constants.NULL_BYTES, owner, to, amount)
 | 
					                .testTransferFrom(false, ENCODED_REVERT, constants.NULL_BYTES, owner, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -242,7 +239,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransferFrom(false, encodeRevert(REVERT_STRING), ENCODED_FALSE, owner, to, amount)
 | 
					                .testTransferFrom(false, ENCODED_REVERT, ENCODED_FALSE, owner, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
					            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -253,7 +250,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransferFrom(false, encodeRevert(REVERT_STRING), ENCODED_TWO, owner, to, amount)
 | 
					                .testTransferFrom(false, ENCODED_REVERT, ENCODED_TWO, owner, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
					            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -264,7 +261,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransferFrom(false, encodeRevert(REVERT_STRING), ENCODED_SHORT_TRUE, owner, to, amount)
 | 
					                .testTransferFrom(false, ENCODED_REVERT, ENCODED_SHORT_TRUE, owner, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
					            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -275,7 +272,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransferFrom(false, encodeRevert(REVERT_STRING), ENCODED_LONG_TRUE, owner, to, amount)
 | 
					                .testTransferFrom(false, ENCODED_REVERT, ENCODED_LONG_TRUE, owner, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
					            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
				
			||||||
            return expect(tx).to.revertWith(expectedError);
 | 
					            return expect(tx).to.revertWith(expectedError);
 | 
				
			||||||
@@ -286,7 +283,7 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            const to = randomAddress();
 | 
					            const to = randomAddress();
 | 
				
			||||||
            const amount = getRandomInteger(0, 100e18);
 | 
					            const amount = getRandomInteger(0, 100e18);
 | 
				
			||||||
            const tx = testContract
 | 
					            const tx = testContract
 | 
				
			||||||
                .testTransferFrom(true, encodeRevert(REVERT_STRING), ENCODED_TRUE, owner, to, amount)
 | 
					                .testTransferFrom(true, ENCODED_REVERT, ENCODED_TRUE, owner, to, amount)
 | 
				
			||||||
                .awaitTransactionSuccessAsync();
 | 
					                .awaitTransactionSuccessAsync();
 | 
				
			||||||
            return expect(tx).to.revertWith(REVERT_STRING);
 | 
					            return expect(tx).to.revertWith(REVERT_STRING);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@@ -301,4 +298,39 @@ blockchainTests('LibERC20Token', env => {
 | 
				
			|||||||
            return expect(tx).to.be.rejectedWith('revert');
 | 
					            return expect(tx).to.be.rejectedWith('revert');
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    describe('decimals()', () => {
 | 
				
			||||||
 | 
					        const DEFAULT_DECIMALS = 18;
 | 
				
			||||||
 | 
					        const ENCODED_ZERO = hexLeftPad(0);
 | 
				
			||||||
 | 
					        const ENCODED_SHORT_ZERO = hexLeftPad(0, 31);
 | 
				
			||||||
 | 
					        const ENCODED_LONG_ZERO = hexLeftPad(0, 33);
 | 
				
			||||||
 | 
					        const randomDecimals = () => Math.floor(Math.random() * 256) + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it('returns the number of decimals defined by the token', async () => {
 | 
				
			||||||
 | 
					            const decimals = randomDecimals();
 | 
				
			||||||
 | 
					            const encodedDecimals = hexLeftPad(decimals);
 | 
				
			||||||
 | 
					            const result = await testContract.testDecimals(false, ENCODED_REVERT, encodedDecimals).callAsync();
 | 
				
			||||||
 | 
					            return expect(result).to.bignumber.eq(decimals);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it('returns 0 if the token returns 0', async () => {
 | 
				
			||||||
 | 
					            const result = await testContract.testDecimals(false, ENCODED_REVERT, ENCODED_ZERO).callAsync();
 | 
				
			||||||
 | 
					            return expect(result).to.bignumber.eq(0);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it('returns 18 if the token returns less than 32 bytes', async () => {
 | 
				
			||||||
 | 
					            const result = await testContract.testDecimals(false, ENCODED_REVERT, ENCODED_SHORT_ZERO).callAsync();
 | 
				
			||||||
 | 
					            return expect(result).to.bignumber.eq(DEFAULT_DECIMALS);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it('returns 18 if the token returns greater than 32 bytes', async () => {
 | 
				
			||||||
 | 
					            const result = await testContract.testDecimals(false, ENCODED_REVERT, ENCODED_LONG_ZERO).callAsync();
 | 
				
			||||||
 | 
					            return expect(result).to.bignumber.eq(DEFAULT_DECIMALS);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it('returns 18 if the token reverts', async () => {
 | 
				
			||||||
 | 
					            const result = await testContract.testDecimals(true, ENCODED_REVERT, ENCODED_ZERO).callAsync();
 | 
				
			||||||
 | 
					            return expect(result).to.bignumber.eq(DEFAULT_DECIMALS);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user