Compare commits

...

16 Commits

Author SHA1 Message Date
Michael Zhu
7f240ffc89 Update Multiplex and NativeOrders contracts to fill RFQ orders using ETH 2021-05-04 18:27:18 -07:00
mzhu25
c68b5d7844 Fix/staking epoch finalization (#221)
* Patch staking and recover state in constructor

* Add ganache mainnet fork test

* Add ganache mainnet fork test

* update changelog

* hardcode last pool ID

* Separate patch contract to unbreak tests
2021-05-04 11:29:16 -07:00
Jacob Evans
09ed106d4c feat: Deployed Balancer V2 and Curve ETH support (#225) 2021-05-04 16:52:36 +10:00
Jacob Evans
a6b92fc658 fix: Fix test forever with new sources being added 2021-05-04 16:49:16 +10:00
mzhu25
4be4a1a30b Fix exchangeProxyGasOverhead used to compute fallback orders (#215)
* Fix exchangeProxyGasOverhead used to compute fallback orders

* update changelog
2021-05-04 13:41:21 +10:00
Romain Butteaud
9bede5d331 fix: reactive PancakeSwap, BakerySwap VIP on BSC (#222) 2021-05-04 13:40:57 +10:00
Romain Butteaud
b50d4aee6d Chore: adding xSigma liquidity source [TKR-59] (#201)
* Chore: adding xSigma liquidity source

* fix: prettier
2021-05-03 19:50:26 -07:00
Jacob Evans
55bc367bd6 feat: Add LUSD Curve pool (#218) 2021-05-04 08:08:27 +10:00
Github Actions
7a59b7eafe Publish
- @0x/contracts-integrations@2.7.39
 - @0x/contracts-zero-ex@0.22.3
 - @0x/asset-swapper@6.9.1
 - @0x/contract-wrappers-test@12.2.44
 - @0x/migrations@8.0.5
2021-05-01 01:03:24 +00:00
Github Actions
9e59d41e44 Updated CHANGELOGS & MD docs 2021-05-01 01:03:19 +00:00
Jacob Evans
475e6c7bca fix: Temporarily remove PancakeV2/Bakery from VIP (#217) 2021-05-01 10:35:54 +10:00
Github Actions
dbc5a5293e Publish
- @0x/contracts-integrations@2.7.38
 - @0x/contracts-treasury@1.1.5
 - @0x/contracts-zero-ex@0.22.2
 - @0x/asset-swapper@6.9.0
 - @0x/contract-wrappers-test@12.2.43
 - @0x/migrations@8.0.4
2021-04-30 23:39:46 +00:00
Github Actions
f4bd2bd0d8 Updated CHANGELOGS & MD docs 2021-04-30 23:39:42 +00:00
Romain Butteaud
f1782a83ba chore: BSC PancakeSwap forks VIP, PancakeSwapV2, Saddle BTC pool, Curve gas schedule [TKR-41] [TKR-11] [TKR-79] [TKR-86] (#208)
* chore: popular BSC Uniswap clones, Curve gas schedule update, Saddle BTC pool

* chore: adding PancakeSwapV2 VIP

* fix: yarn prettier
2021-05-01 08:48:10 +10:00
Jacob Evans
cbade0d558 fix: Ban colliding Kyber reserve (#216) 2021-04-29 15:24:39 +10:00
mzhu25
fe0c26387c Fix treasury voting power calculation (#214)
* Fix treasury voting power calculation

* Update changelog
2021-04-28 10:22:52 -07:00
44 changed files with 849 additions and 176 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-integrations",
"version": "2.7.37",
"version": "2.7.39",
"private": true,
"engines": {
"node": ">=6.12"
@@ -65,7 +65,7 @@
"@0x/contracts-utils": "^4.7.7",
"@0x/coordinator-server": "^1.0.5",
"@0x/dev-utils": "^4.2.6",
"@0x/migrations": "^8.0.3",
"@0x/migrations": "^8.0.5",
"@0x/order-utils": "^10.4.20",
"@0x/protocol-utils": "^1.5.1",
"@0x/sol-compiler": "^4.7.2",
@@ -93,7 +93,7 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/asset-swapper": "^6.8.0",
"@0x/asset-swapper": "^6.9.1",
"@0x/base-contract": "^6.3.2",
"@0x/contracts-asset-proxy": "^3.7.10",
"@0x/contracts-erc1155": "^2.1.28",
@@ -103,7 +103,7 @@
"@0x/contracts-multisig": "^4.1.29",
"@0x/contracts-staking": "^2.0.36",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-zero-ex": "^0.22.1",
"@0x/contracts-zero-ex": "^0.22.3",
"@0x/subproviders": "^6.5.2",
"@0x/types": "^3.3.3",
"@0x/typescript-typings": "^5.2.0",

View File

@@ -1,4 +1,13 @@
[
{
"version": "2.0.37",
"changes": [
{
"note": "Patch epoch finalization issue",
"pr": 221
}
]
},
{
"timestamp": 1619596077,
"version": "2.0.36",

View File

@@ -0,0 +1,55 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "./interfaces/IStaking.sol";
import "./sys/MixinParams.sol";
import "./stake/MixinStake.sol";
import "./fees/MixinExchangeFees.sol";
contract StakingPatch is
IStaking,
MixinParams,
MixinStake,
MixinExchangeFees
{
/// @dev Initialize storage owned by this contract.
/// This function should not be called directly.
/// The StakingProxy contract will call it in `attachStakingContract()`.
function init()
public
onlyAuthorized
{
uint256 currentEpoch_ = currentEpoch;
uint256 prevEpoch = currentEpoch_.safeSub(1);
// Patch corrupted state
aggregatedStatsByEpoch[prevEpoch].numPoolsToFinalize = 0;
this.endEpoch();
uint256 lastPoolId_ = 57;
for (uint256 i = 1; i <= lastPoolId_; i++) {
this.finalizePool(bytes32(i));
}
// Ensure that current epoch's state is not corrupted
aggregatedStatsByEpoch[currentEpoch_].numPoolsToFinalize = 0;
}
}

View File

@@ -53,6 +53,10 @@ contract MixinExchangeFees is
{
_assertValidProtocolFee(protocolFee);
if (protocolFee == 0) {
return;
}
// Transfer the protocol fee to this address if it should be paid in
// WETH.
if (msg.value == 0) {

View File

@@ -41,7 +41,7 @@
"config": {
"publicInterfaceContracts": "IStaking,IStakingEvents,IStakingProxy,IZrxVault,LibStakingRichErrors,Staking,StakingProxy,ZrxVault,TestStaking",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(IStaking|IStakingEvents|IStakingProxy|IStorage|IStorageInit|IStructs|IZrxVault|LibCobbDouglas|LibFixedMath|LibFixedMathRichErrors|LibSafeDowncast|LibStakingRichErrors|MixinAbstract|MixinConstants|MixinCumulativeRewards|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinFinalizer|MixinParams|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakeStorage|MixinStakingPool|MixinStakingPoolRewards|MixinStorage|Staking|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestExchangeManager|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibSafeDowncast|TestMixinCumulativeRewards|TestMixinParams|TestMixinScheduler|TestMixinStake|TestMixinStakeBalances|TestMixinStakeStorage|TestMixinStakingPool|TestMixinStakingPoolRewards|TestProtocolFees|TestProxyDestination|TestStaking|TestStakingNoWETH|TestStakingProxy|TestStakingProxyUnit|TestStorageLayoutAndConstants|ZrxVault).json"
"abis": "./test/generated-artifacts/@(IStaking|IStakingEvents|IStakingProxy|IStorage|IStorageInit|IStructs|IZrxVault|LibCobbDouglas|LibFixedMath|LibFixedMathRichErrors|LibSafeDowncast|LibStakingRichErrors|MixinAbstract|MixinConstants|MixinCumulativeRewards|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinFinalizer|MixinParams|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakeStorage|MixinStakingPool|MixinStakingPoolRewards|MixinStorage|Staking|StakingPatch|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestExchangeManager|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibSafeDowncast|TestMixinCumulativeRewards|TestMixinParams|TestMixinScheduler|TestMixinStake|TestMixinStakeBalances|TestMixinStakeStorage|TestMixinStakingPool|TestMixinStakingPoolRewards|TestProtocolFees|TestProxyDestination|TestStaking|TestStakingNoWETH|TestStakingProxy|TestStakingProxyUnit|TestStorageLayoutAndConstants|ZrxVault).json"
},
"repository": {
"type": "git",

View File

@@ -33,6 +33,7 @@ import * as MixinStakingPool from '../test/generated-artifacts/MixinStakingPool.
import * as MixinStakingPoolRewards from '../test/generated-artifacts/MixinStakingPoolRewards.json';
import * as MixinStorage from '../test/generated-artifacts/MixinStorage.json';
import * as Staking from '../test/generated-artifacts/Staking.json';
import * as StakingPatch from '../test/generated-artifacts/StakingPatch.json';
import * as StakingProxy from '../test/generated-artifacts/StakingProxy.json';
import * as TestAssertStorageParams from '../test/generated-artifacts/TestAssertStorageParams.json';
import * as TestCobbDouglas from '../test/generated-artifacts/TestCobbDouglas.json';
@@ -61,6 +62,7 @@ import * as TestStorageLayoutAndConstants from '../test/generated-artifacts/Test
import * as ZrxVault from '../test/generated-artifacts/ZrxVault.json';
export const artifacts = {
Staking: Staking as ContractArtifact,
StakingPatch: StakingPatch as ContractArtifact,
StakingProxy: StakingProxy as ContractArtifact,
ZrxVault: ZrxVault as ContractArtifact,
MixinExchangeFees: MixinExchangeFees as ContractArtifact,

View File

@@ -0,0 +1,66 @@
import { blockchainTests, constants, expect, filterLogsToArguments } from '@0x/contracts-test-utils';
import { BigNumber, logUtils } from '@0x/utils';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { StakingEvents, StakingPatchContract, StakingProxyContract, StakingProxyEvents } from './wrappers';
const abis = _.mapValues(artifacts, v => v.compilerOutput.abi);
const STAKING_PROXY = '0xa26e80e7dea86279c6d778d702cc413e6cffa777';
const STAKING_OWNER = '0x7d3455421bbc5ed534a83c88fd80387dc8271392';
const EXCHANGE_PROXY = '0xdef1c0ded9bec7f1a1670819833240f027b25eff';
blockchainTests.configure({
fork: {
unlockedAccounts: [STAKING_OWNER, EXCHANGE_PROXY],
},
});
blockchainTests.fork('Staking patch mainnet fork tests', env => {
let stakingProxyContract: StakingProxyContract;
let patchedStakingPatchContract: StakingPatchContract;
before(async () => {
stakingProxyContract = new StakingProxyContract(STAKING_PROXY, env.provider, undefined, abis);
patchedStakingPatchContract = await StakingPatchContract.deployFrom0xArtifactAsync(
artifacts.Staking,
env.provider,
env.txDefaults,
artifacts,
);
});
it('Staking proxy successfully attaches to patched logic', async () => {
const tx = await stakingProxyContract
.attachStakingContract(patchedStakingPatchContract.address)
.awaitTransactionSuccessAsync({ from: STAKING_OWNER, gasPrice: 0 }, { shouldValidate: false });
expect(filterLogsToArguments(tx.logs, StakingProxyEvents.StakingContractAttachedToProxy)).to.deep.equal([
{
newStakingPatchContractAddress: patchedStakingPatchContract.address,
},
]);
expect(filterLogsToArguments(tx.logs, StakingEvents.EpochEnded).length).to.equal(1);
expect(filterLogsToArguments(tx.logs, StakingEvents.EpochFinalized).length).to.equal(1);
logUtils.log(`${tx.gasUsed} gas used`);
});
it('Patched staking handles 0 gas protocol fees', async () => {
const staking = new StakingPatchContract(STAKING_PROXY, env.provider, undefined, abis);
const maker = '0x7b1886e49ab5433bb46f7258548092dc8cdca28b';
const zeroFeeTx = await staking
.payProtocolFee(maker, constants.NULL_ADDRESS, constants.ZERO_AMOUNT)
.awaitTransactionSuccessAsync({ from: EXCHANGE_PROXY, gasPrice: 0 }, { shouldValidate: false });
// StakingPoolEarnedRewardsInEpoch should _not_ be emitted for a zero protocol fee.
// tslint:disable-next-line:no-unused-expression
expect(filterLogsToArguments(zeroFeeTx.logs, StakingEvents.StakingPoolEarnedRewardsInEpoch)).to.be.empty;
// Coincidentally there's some ETH in the ExchangeProxy
const nonZeroFeeTx = await staking
.payProtocolFee(maker, constants.NULL_ADDRESS, new BigNumber(1))
.awaitTransactionSuccessAsync({ from: EXCHANGE_PROXY, gasPrice: 0, value: 1 }, { shouldValidate: false });
// StakingPoolEarnedRewardsInEpoch _should_ be emitted for a non-zero protocol fee.
expect(
filterLogsToArguments(nonZeroFeeTx.logs, StakingEvents.StakingPoolEarnedRewardsInEpoch),
).to.have.lengthOf(1);
});
});
// tslint:enable:no-unnecessary-type-assertion

View File

@@ -31,6 +31,7 @@ export * from '../test/generated-wrappers/mixin_staking_pool';
export * from '../test/generated-wrappers/mixin_staking_pool_rewards';
export * from '../test/generated-wrappers/mixin_storage';
export * from '../test/generated-wrappers/staking';
export * from '../test/generated-wrappers/staking_patch';
export * from '../test/generated-wrappers/staking_proxy';
export * from '../test/generated-wrappers/test_assert_storage_params';
export * from '../test/generated-wrappers/test_cobb_douglas';

View File

@@ -40,6 +40,7 @@
"test/generated-artifacts/MixinStakingPoolRewards.json",
"test/generated-artifacts/MixinStorage.json",
"test/generated-artifacts/Staking.json",
"test/generated-artifacts/StakingPatch.json",
"test/generated-artifacts/StakingProxy.json",
"test/generated-artifacts/TestAssertStorageParams.json",
"test/generated-artifacts/TestCobbDouglas.json",

View File

@@ -1,4 +1,14 @@
[
{
"version": "1.1.5",
"changes": [
{
"note": "Patched votingPower logic",
"pr": 214
}
],
"timestamp": 1619825976
},
{
"timestamp": 1619596077,
"version": "1.1.4",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.1.5 - _April 30, 2021_
* Patched votingPower logic (#214)
## v1.1.4 - _April 28, 2021_
* Dependencies updated

View File

@@ -30,6 +30,7 @@ interface IZrxTreasury {
uint256 votingPeriod;
uint256 proposalThreshold;
uint256 quorumThreshold;
bytes32 defaultPoolId;
}
struct ProposedAction {

View File

@@ -20,8 +20,6 @@
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
@@ -32,7 +30,6 @@ import "./IZrxTreasury.sol";
contract ZrxTreasury is
IZrxTreasury
{
using LibERC20TokenV06 for IERC20TokenV06;
using LibSafeMathV06 for uint256;
using LibRichErrorsV06 for bytes;
using LibBytesV06 for bytes;
@@ -52,11 +49,9 @@ contract ZrxTreasury is
/// @dev Initializes the ZRX treasury and creates the default
/// staking pool.
/// @param stakingProxy_ The 0x staking proxy contract.
/// @param weth_ The WETH token contract.
/// @param params Immutable treasury parameters.
constructor(
IStaking stakingProxy_,
IERC20TokenV06 weth_,
TreasuryParameters memory params
)
public
@@ -66,15 +61,12 @@ contract ZrxTreasury is
"VOTING_PERIOD_TOO_LONG"
);
stakingProxy = stakingProxy_;
DefaultPoolOperator defaultPoolOperator_ = new DefaultPoolOperator(
stakingProxy_,
weth_
);
defaultPoolOperator = defaultPoolOperator_;
defaultPoolId = defaultPoolOperator_.poolId();
votingPeriod = params.votingPeriod;
proposalThreshold = params.proposalThreshold;
quorumThreshold = params.quorumThreshold;
defaultPoolId = params.defaultPoolId;
IStaking.Pool memory defaultPool = stakingProxy_.getStakingPool(params.defaultPoolId);
defaultPoolOperator = DefaultPoolOperator(defaultPool.operator);
}
// solhint-disable
@@ -286,6 +278,12 @@ contract ZrxTreasury is
// Add voting power for operated staking pools.
for (uint256 i = 0; i != operatedPoolIds.length; i++) {
for (uint256 j = 0; j != i; j++) {
require(
operatedPoolIds[i] != operatedPoolIds[j],
"getVotingPower/DUPLICATE_POOL_ID"
);
}
IStaking.Pool memory pool = stakingProxy.getStakingPool(operatedPoolIds[i]);
require(
pool.operator == account,

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-treasury",
"version": "1.1.4",
"version": "1.1.5",
"engines": {
"node": ">=6.12"
},

View File

@@ -28,6 +28,7 @@ blockchainTests.resets('Treasury governance', env => {
votingPeriod: new BigNumber(3).times(stakingConstants.ONE_DAY_IN_SECONDS),
proposalThreshold: new BigNumber(100),
quorumThreshold: new BigNumber(1000),
defaultPoolId: stakingConstants.INITIAL_POOL_ID,
};
const PROPOSAL_DESCRIPTION = 'A very compelling proposal!';
const TREASURY_BALANCE = constants.INITIAL_ERC20_BALANCE;
@@ -135,6 +136,16 @@ blockchainTests.resets('Treasury governance', env => {
.approve(erc20ProxyContract.address, constants.INITIAL_ERC20_ALLOWANCE)
.awaitTransactionSuccessAsync({ from: delegator });
defaultPoolOperator = await DefaultPoolOperatorContract.deployFrom0xArtifactAsync(
artifacts.DefaultPoolOperator,
env.provider,
env.txDefaults,
{ ...artifacts, ...erc20Artifacts },
staking.address,
weth.address,
);
defaultPoolId = stakingConstants.INITIAL_POOL_ID;
const createStakingPoolTx = staking.createStakingPool(stakingConstants.PPM, false);
nonDefaultPoolId = await createStakingPoolTx.callAsync({ from: poolOperator });
await createStakingPoolTx.awaitTransactionSuccessAsync({ from: poolOperator });
@@ -145,9 +156,9 @@ blockchainTests.resets('Treasury governance', env => {
env.txDefaults,
{ ...artifacts, ...erc20Artifacts },
staking.address,
weth.address,
TREASURY_PARAMS,
);
await zrx.mint(TREASURY_BALANCE).awaitTransactionSuccessAsync();
await zrx.transfer(treasury.address, TREASURY_BALANCE).awaitTransactionSuccessAsync();
actions = [
@@ -166,10 +177,6 @@ blockchainTests.resets('Treasury governance', env => {
value: constants.ZERO_AMOUNT,
},
];
defaultPoolId = await treasury.defaultPoolId().callAsync();
const defaultPoolOperatorAddress = await treasury.defaultPoolOperator().callAsync();
defaultPoolOperator = new DefaultPoolOperatorContract(defaultPoolOperatorAddress, env.provider, env.txDefaults);
});
describe('getVotingPower()', () => {
it('Unstaked ZRX has no voting power', async () => {
@@ -222,6 +229,19 @@ blockchainTests.resets('Treasury governance', env => {
const operatorVotingPower = await treasury.getVotingPower(poolOperator, [nonDefaultPoolId]).callAsync();
expect(operatorVotingPower).to.bignumber.equal(TREASURY_PARAMS.proposalThreshold.dividedBy(2));
});
it('Reverts if given duplicate pool IDs', async () => {
await staking.stake(TREASURY_PARAMS.proposalThreshold).awaitTransactionSuccessAsync({ from: delegator });
await staking
.moveStake(
new StakeInfo(StakeStatus.Undelegated),
new StakeInfo(StakeStatus.Delegated, nonDefaultPoolId),
TREASURY_PARAMS.proposalThreshold,
)
.awaitTransactionSuccessAsync({ from: delegator });
await fastForwardToNextEpochAsync();
const tx = treasury.getVotingPower(poolOperator, [nonDefaultPoolId, nonDefaultPoolId]).callAsync();
return expect(tx).to.revertWith('getVotingPower/DUPLICATE_POOL_ID');
});
it('Correctly sums voting power delegated to multiple pools', async () => {
await staking
.stake(TREASURY_PARAMS.proposalThreshold.times(2))

View File

@@ -1,4 +1,22 @@
[
{
"timestamp": 1619830995,
"version": "0.22.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1619825976,
"version": "0.22.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.22.1",
"changes": [
@@ -25,6 +43,10 @@
"changes": [
{
"note": "Dependencies updated"
},
{
"note": "BSC Uniswap clones (ApeSwap, CafeSwap, CheeseSwap, JulSwap)",
"pr": 208
}
]
},

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.22.3 - _May 1, 2021_
* Dependencies updated
## v0.22.2 - _April 30, 2021_
* Dependencies updated
## v0.22.1 - _April 28, 2021_
* bump feature version to 1.2 (#213)
@@ -16,6 +24,7 @@ CHANGELOG
## v0.21.1 - _April 12, 2021_
* Dependencies updated
* BSC Uniswap clones (ApeSwap, CafeSwap, CheeseSwap, JulSwap) (#208)
## v0.21.0 - _April 1, 2021_

View File

@@ -478,7 +478,7 @@ contract MetaTransactionsFeature is
/// @dev Execute a `INativeOrdersFeature.fillRfqOrder()` meta-transaction call
/// by decoding the call args and translating the call to the internal
/// `INativeOrdersFeature._fillRfqOrder()` variant, where we can overrideunimpleme
/// `INativeOrdersFeature._fillRfqOrder()` variant, where we can override
/// the taker address.
function _executeFillRfqOrderCall(ExecuteState memory state)
private

View File

@@ -55,7 +55,7 @@ contract MultiplexFeature is
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "MultiplexFeature";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
/// @dev The WETH token contract.
IEtherTokenV06 private immutable weth;
@@ -231,26 +231,55 @@ contract MultiplexFeature is
);
continue;
}
require(
order.takerToken == fillData.inputToken &&
order.makerToken == fillData.outputToken,
"MultiplexFeature::_batchFill/RFQ_ORDER_INVALID_TOKENS"
);
// Try filling the RFQ order. Swallows reverts.
try
INativeOrdersFeature(address(this))._fillRfqOrder
(
order,
signature,
inputTokenAmount.safeDowncastToUint128(),
msg.sender
)
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
{
// Increment the sold and bought amounts.
soldAmount = soldAmount.safeAdd(takerTokenFilledAmount);
outputTokenAmount = outputTokenAmount.safeAdd(makerTokenFilledAmount);
} catch {}
if (fillData.inputToken.isTokenETH()) {
require(
order.takerToken == weth &&
order.makerToken == fillData.outputToken,
"MultiplexFeature::_batchFill/RFQ_ORDER_INVALID_TOKENS"
);
inputTokenAmount = LibSafeMathV06.min256(
inputTokenAmount,
remainingEth
);
// Try filling the RFQ order. Swallows reverts.
try
INativeOrdersFeature(address(this))._fillRfqOrderWithEth
{value: inputTokenAmount}
(
order,
signature,
inputTokenAmount.safeDowncastToUint128(),
msg.sender
)
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
{
// Increment the sold and bought amounts.
soldAmount = soldAmount.safeAdd(takerTokenFilledAmount);
outputTokenAmount = outputTokenAmount.safeAdd(makerTokenFilledAmount);
remainingEth = remainingEth.safeSub(takerTokenFilledAmount);
} catch {}
} else {
require(
order.takerToken == fillData.inputToken &&
order.makerToken == fillData.outputToken,
"MultiplexFeature::_batchFill/RFQ_ORDER_INVALID_TOKENS"
);
// Try filling the RFQ order. Swallows reverts.
try
INativeOrdersFeature(address(this))._fillRfqOrder
(
order,
signature,
inputTokenAmount.safeDowncastToUint128(),
msg.sender
)
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
{
// Increment the sold and bought amounts.
soldAmount = soldAmount.safeAdd(takerTokenFilledAmount);
outputTokenAmount = outputTokenAmount.safeAdd(makerTokenFilledAmount);
} catch {}
}
} else if (wrappedCall.selector == this._sellToUniswap.selector) {
(address[] memory tokens, bool isSushi) = abi.decode(
wrappedCall.data,

View File

@@ -34,7 +34,7 @@ contract NativeOrdersFeature is
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "LimitOrders";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 2, 0);
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 3, 0);
constructor(
address zeroExAddress,
@@ -69,6 +69,7 @@ contract NativeOrdersFeature is
_registerFeatureFunction(this.fillOrKillRfqOrder.selector);
_registerFeatureFunction(this._fillLimitOrder.selector);
_registerFeatureFunction(this._fillRfqOrder.selector);
_registerFeatureFunction(this._fillRfqOrderWithEth.selector);
_registerFeatureFunction(this.cancelLimitOrder.selector);
_registerFeatureFunction(this.cancelRfqOrder.selector);
_registerFeatureFunction(this.batchCancelLimitOrders.selector);

View File

@@ -37,22 +37,44 @@ contract PancakeSwapFeature is
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "PancakeSwapFeature";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 2);
/// @dev WBNB contract.
IEtherTokenV06 private immutable WBNB;
// 0xFF + address of the PancakeSwap factory contract.
uint256 constant private FF_PANCAKESWAP_FACTORY = 0xffbcfccbde45ce874adcb698cc183debcf179528120000000000000000000000;
// 0xFF + address of the PancakeSwapV2 factory contract.
uint256 constant private FF_PANCAKESWAPV2_FACTORY = 0xffca143ce32fe78f1f7019d7d551a6402fc5350c730000000000000000000000;
// 0xFF + address of the BakerySwap factory contract.
uint256 constant private FF_BAKERYSWAP_FACTORY = 0xff01bf7c66c6bd861915cdaae475042d3c4bae16a70000000000000000000000;
// 0xFF + address of the SushiSwap factory contract.
uint256 constant private FF_SUSHISWAP_FACTORY = 0xffc35DADB65012eC5796536bD9864eD8773aBc74C40000000000000000000000;
// 0xFF + address of the ApeSwap factory contract.
uint256 constant private FF_APESWAP_FACTORY = 0xff0841bd0b734e4f5853f0dd8d7ea041c241fb0da60000000000000000000000;
// 0xFF + address of the CafeSwap factory contract.
uint256 constant private FF_CAFESWAP_FACTORY = 0xff3e708fdbe3ada63fc94f8f61811196f1302137ad0000000000000000000000;
// 0xFF + address of the CheeseSwap factory contract.
uint256 constant private FF_CHEESESWAP_FACTORY = 0xffdd538e4fd1b69b7863e1f741213276a6cf1efb3b0000000000000000000000;
// 0xFF + address of the JulSwap factory contract.
uint256 constant private FF_JULSWAP_FACTORY = 0xff553990f2cba90272390f62c5bdb1681ffc8996750000000000000000000000;
// Init code hash of the PancakeSwap pair contract.
uint256 constant private PANCAKESWAP_PAIR_INIT_CODE_HASH = 0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66;
// Init code hash of the PancakeSwapV2 pair contract.
uint256 constant private PANCAKESWAPV2_PAIR_INIT_CODE_HASH = 0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5;
// Init code hash of the BakerySwap pair contract.
uint256 constant private BAKERYSWAP_PAIR_INIT_CODE_HASH = 0xe2e87433120e32c4738a7d8f3271f3d872cbe16241d67537139158d90bac61d3;
// Init code hash of the SushiSwap pair contract.
uint256 constant private SUSHISWAP_PAIR_INIT_CODE_HASH = 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303;
// Init code hash of the ApeSwap pair contract.
uint256 constant private APESWAP_PAIR_INIT_CODE_HASH = 0xf4ccce374816856d11f00e4069e7cada164065686fbef53c6167a63ec2fd8c5b;
// Init code hash of the CafeSwap pair contract.
uint256 constant private CAFESWAP_PAIR_INIT_CODE_HASH = 0x90bcdb5d0bf0e8db3852b0b7d7e05cc8f7c6eb6d511213c5ba02d1d1dbeda8d3;
// Init code hash of the CheeseSwap pair contract.
uint256 constant private CHEESESWAP_PAIR_INIT_CODE_HASH = 0xf52c5189a89e7ca2ef4f19f2798e3900fba7a316de7cef6c5a9446621ba86286;
// Init code hash of the JulSwap pair contract.
uint256 constant private JULSWAP_PAIR_INIT_CODE_HASH = 0xb1e98e21a5335633815a8cfb3b580071c2e4561c50afd57a8746def9ed890b18;
// Mask of the lower 20 bytes of a bytes32.
uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
// BNB pseudo-token address.
@@ -258,7 +280,7 @@ contract PancakeSwapFeature is
// Call pair.swap()
switch mload(0xA20) // fork
case 1 {
case 2 {
mstore(0xB00, BAKERYSWAP_PAIR_SWAP_CALL_SELECTOR_32)
}
default {
@@ -352,15 +374,40 @@ contract PancakeSwapFeature is
mstore(0xB35, PANCAKESWAP_PAIR_INIT_CODE_HASH)
}
case 1 {
mstore(0xB00, FF_PANCAKESWAPV2_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, PANCAKESWAPV2_PAIR_INIT_CODE_HASH)
}
case 2 {
mstore(0xB00, FF_BAKERYSWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, BAKERYSWAP_PAIR_INIT_CODE_HASH)
}
default {
case 3 {
mstore(0xB00, FF_SUSHISWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, SUSHISWAP_PAIR_INIT_CODE_HASH)
}
case 4 {
mstore(0xB00, FF_APESWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, APESWAP_PAIR_INIT_CODE_HASH)
}
case 5 {
mstore(0xB00, FF_CAFESWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, CAFESWAP_PAIR_INIT_CODE_HASH)
}
case 6 {
mstore(0xB00, FF_CHEESESWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, CHEESESWAP_PAIR_INIT_CODE_HASH)
}
default {
mstore(0xB00, FF_JULSWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, JULSWAP_PAIR_INIT_CODE_HASH)
}
pair := and(ADDRESS_MASK, keccak256(0xB00, 0x55))
}

View File

@@ -137,6 +137,24 @@ interface INativeOrdersFeature is
external
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
/// @dev Fill an RFQ order using ETH. Taker token must be WETH.
/// Internal variant.
/// @param order The RFQ order.
/// @param signature The order signature.
/// @param takerTokenFillAmount Maximum taker token to fill this order with.
/// @param taker The order taker.
/// @return takerTokenFilledAmount How much maker token was filled.
/// @return makerTokenFilledAmount How much maker token was filled.
function _fillRfqOrderWithEth(
LibNativeOrder.RfqOrder calldata order,
LibSignature.Signature calldata signature,
uint128 takerTokenFillAmount,
address taker
)
external
payable
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
/// @dev Cancel a single limit order. The caller must be the maker or a valid order signer.
/// Silently succeeds if the order has already been cancelled.
/// @param order The limit order.

View File

@@ -23,16 +23,21 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
/// @dev VIP PancakeSwap/BakerySwap/SushiSwap fill functions.
/// @dev VIP PancakeSwap (and forks) fill functions.
interface IPancakeSwapFeature {
enum ProtocolFork {
PancakeSwap,
PancakeSwapV2,
BakerySwap,
SushiSwap
SushiSwap,
ApeSwap,
CafeSwap,
CheeseSwap,
JulSwap
}
/// @dev Efficiently sell directly to PancakeSwap/BakerySwap/Sushiswap.
/// @dev Efficiently sell directly to PancakeSwap (and forks).
/// @param tokens Sell path.
/// @param sellAmount of `tokens[0]` Amount to sell.
/// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.

View File

@@ -66,6 +66,8 @@ abstract contract NativeOrdersSettlement is
uint128 takerTokenFillAmount;
// How much taker token amount has already been filled in this order.
uint128 takerTokenFilledAmount;
bool useEthBalance;
}
/// @dev Params for `_fillLimitOrderPrivate()`
@@ -158,7 +160,8 @@ abstract contract NativeOrdersSettlement is
order,
signature,
takerTokenFillAmount,
msg.sender
msg.sender,
false
);
(takerTokenFilledAmount, makerTokenFilledAmount) = (
results.takerTokenFilledAmount,
@@ -224,7 +227,8 @@ abstract contract NativeOrdersSettlement is
order,
signature,
takerTokenFillAmount,
msg.sender
msg.sender,
false
);
// Must have filled exactly the amount requested.
if (results.takerTokenFilledAmount < takerTokenFillAmount) {
@@ -273,9 +277,7 @@ abstract contract NativeOrdersSettlement is
);
}
/// @dev Fill an RFQ order. Internal variant. ETH protocol fees can be
/// attached to this call. Any unspent ETH will be refunded to
/// `msg.sender` (not `sender`).
/// @dev Fill an RFQ order. Internal variant.
/// @param order The RFQ order.
/// @param signature The order signature.
/// @param takerTokenFillAmount Maximum taker token to fill this order with.
@@ -298,7 +300,8 @@ abstract contract NativeOrdersSettlement is
order,
signature,
takerTokenFillAmount,
taker
taker,
false
);
(takerTokenFilledAmount, makerTokenFilledAmount) = (
results.takerTokenFilledAmount,
@@ -306,6 +309,49 @@ abstract contract NativeOrdersSettlement is
);
}
/// @dev Fill an RFQ order using ETH. Taker token must be WETH.
/// Internal variant.
/// @param order The RFQ order.
/// @param signature The order signature.
/// @param takerTokenFillAmount Maximum taker token to fill this order with.
/// @param taker The order taker.
/// @return takerTokenFilledAmount How much maker token was filled.
/// @return makerTokenFilledAmount How much maker token was filled.
function _fillRfqOrderWithEth(
LibNativeOrder.RfqOrder memory order,
LibSignature.Signature memory signature,
uint128 takerTokenFillAmount,
address taker
)
public
virtual
payable
onlySelf
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
{
require(
msg.value == takerTokenFillAmount,
"NativeOrdersFeature/ETH_FILL_AMOUNT_MISMATCH"
);
FillNativeOrderResults memory results =
_fillRfqOrderPrivate(
order,
signature,
takerTokenFillAmount,
taker,
true
);
(takerTokenFilledAmount, makerTokenFilledAmount) = (
results.takerTokenFilledAmount,
results.makerTokenFilledAmount
);
if (takerTokenFilledAmount < msg.value) {
uint256 refundAmount = msg.value.safeSub(takerTokenFilledAmount);
(bool success,) = msg.sender.call{value: refundAmount}("");
require(success, "NativeOrdersFeature/ETH_REFUND_FAILED");
}
}
/// @dev Mark what tx.origin addresses are allowed to fill an order that
/// specifies the message sender as its txOrigin.
/// @param origins An array of origin addresses to update.
@@ -393,7 +439,8 @@ abstract contract NativeOrdersSettlement is
makerAmount: params.order.makerAmount,
takerAmount: params.order.takerAmount,
takerTokenFillAmount: params.takerTokenFillAmount,
takerTokenFilledAmount: orderInfo.takerTokenFilledAmount
takerTokenFilledAmount: orderInfo.takerTokenFilledAmount,
useEthBalance: false
})
);
@@ -437,7 +484,8 @@ abstract contract NativeOrdersSettlement is
LibNativeOrder.RfqOrder memory order,
LibSignature.Signature memory signature,
uint128 takerTokenFillAmount,
address taker
address taker,
bool useEthBalance
)
private
returns (FillNativeOrderResults memory results)
@@ -498,7 +546,8 @@ abstract contract NativeOrdersSettlement is
makerAmount: order.makerAmount,
takerAmount: order.takerAmount,
takerTokenFillAmount: takerTokenFillAmount,
takerTokenFilledAmount: orderInfo.takerTokenFilledAmount
takerTokenFilledAmount: orderInfo.takerTokenFilledAmount,
useEthBalance: useEthBalance
})
);
@@ -549,13 +598,22 @@ abstract contract NativeOrdersSettlement is
// function if the order is cancelled.
settleInfo.takerTokenFilledAmount.safeAdd128(takerTokenFilledAmount);
// Transfer taker -> maker.
_transferERC20Tokens(
settleInfo.takerToken,
settleInfo.taker,
settleInfo.maker,
takerTokenFilledAmount
);
if (settleInfo.useEthBalance) {
require(
settleInfo.takerToken == WETH,
"NativeOrdersFeature/USE_ETH_BALANCE_INVALID"
);
WETH.deposit{value: takerTokenFilledAmount}();
WETH.transfer(settleInfo.maker, takerTokenFilledAmount);
} else {
// Transfer taker -> maker.
_transferERC20Tokens(
settleInfo.takerToken,
settleInfo.taker,
settleInfo.maker,
takerTokenFilledAmount
);
}
// Transfer maker -> taker.
_transferERC20Tokens(

View File

@@ -32,12 +32,12 @@ abstract contract FixinProtocolFees {
/// @dev The protocol fee multiplier.
uint32 public immutable PROTOCOL_FEE_MULTIPLIER;
/// @dev The WETH token contract.
IEtherTokenV06 internal immutable WETH;
/// @dev The `FeeCollectorController` contract.
FeeCollectorController private immutable FEE_COLLECTOR_CONTROLLER;
/// @dev Hash of the fee collector init code.
bytes32 private immutable FEE_COLLECTOR_INIT_CODE_HASH;
/// @dev The WETH token contract.
IEtherTokenV06 private immutable WETH;
/// @dev The staking contract.
IStaking private immutable STAKING;

View File

@@ -87,6 +87,60 @@ abstract contract FixinTokenSpender {
}
}
/// @dev Transfers ERC20 tokens from `address(this)` to `to`.
/// @param token The token to spend.
/// @param to The recipient of the tokens.
/// @param amount The amount of `token` to transfer.
function _transferERC20Tokens(
IERC20TokenV06 token,
address to,
uint256 amount
)
internal
{
require(address(token) != address(this), "FixinTokenSpender/CANNOT_INVOKE_SELF");
assembly {
let ptr := mload(0x40) // free memory pointer
// selector for transfer(address,uint256)
mstore(ptr, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(ptr, 0x04), and(to, ADDRESS_MASK))
mstore(add(ptr, 0x24), amount)
let success := call(
gas(),
and(token, ADDRESS_MASK),
0,
ptr,
0x44,
ptr,
32
)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
returndatacopy(ptr, 0, rdsize)
revert(ptr, rdsize)
}
}
}
/// @dev Gets the maximum amount of an ERC20 token `token` that can be
/// pulled from `owner` by this address.
/// @param token The token to spend.

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-zero-ex",
"version": "0.22.1",
"version": "0.22.3",
"engines": {
"node": ">=6.12"
},

View File

@@ -1,4 +1,45 @@
[
{
"version": "6.10.1",
"changes": [
{
"note": "Reactivate PancakeSwapV2 and BakerySwap VIP on BSC",
"pr": 222
}
]
},
{
"version": "6.10.0",
"changes": [
{
"note": "Add LUSD Curve pool",
"pr": 218
},
{
"note": "Fix exchangeProxyGasOverhead for fallback path",
"pr": 215
}
]
},
{
"version": "6.9.1",
"changes": [
{
"note": "Temporarily remove PancakeV2 and BakerySwap from VIP"
}
],
"timestamp": 1619830995
},
{
"version": "6.9.0",
"changes": [
{
"note": "Remove conflicting Kyber reserve",
"pr": 216
}
],
"timestamp": 1619825976
},
{
"version": "6.8.0",
"changes": [
@@ -38,6 +79,10 @@
{
"note": "Support `Ropsten` network",
"pr": 203
},
{
"note": "BSC Uniswap clones (ApeSwap, CafeSwap, CheeseSwap, JulSwap), Saddle BTC pool, Curve gas schedule",
"pr": 208
}
],
"timestamp": 1618592834

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v6.9.1 - _May 1, 2021_
* Temporarily remove PancakeV2 and BakerySwap from VIP
## v6.9.0 - _April 30, 2021_
* Remove conflicting Kyber reserve (#216)
## v6.8.0 - _April 28, 2021_
* Prune paths which cannot improve the best path (#183)
@@ -21,6 +29,7 @@ CHANGELOG
## v6.6.0 - _April 16, 2021_
* Support `Ropsten` network (#203)
* BSC Uniswap clones (ApeSwap, CafeSwap, CheeseSwap, JulSwap), Saddle BTC pool, Curve gas schedule (#208)
## v6.5.3 - _April 14, 2021_

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/asset-swapper",
"version": "6.8.0",
"version": "6.9.1",
"engines": {
"node": ">=6.12"
},
@@ -62,7 +62,7 @@
"@0x/contract-addresses": "^6.0.0",
"@0x/contract-wrappers": "^13.16.0",
"@0x/contracts-erc20": "^3.3.7",
"@0x/contracts-zero-ex": "^0.22.1",
"@0x/contracts-zero-ex": "^0.22.3",
"@0x/dev-utils": "^4.2.6",
"@0x/json-schemas": "^6.1.2",
"@0x/protocol-utils": "^1.5.1",
@@ -97,7 +97,7 @@
"@0x/contracts-test-utils": "^5.3.25",
"@0x/contracts-utils": "^4.7.7",
"@0x/mesh-rpc-client": "^9.4.2",
"@0x/migrations": "^8.0.3",
"@0x/migrations": "^8.0.5",
"@0x/sol-compiler": "^4.7.2",
"@0x/subproviders": "^6.5.2",
"@0x/ts-doc-gen": "^0.0.28",

View File

@@ -65,7 +65,18 @@ import {
// tslint:disable-next-line:custom-no-magic-numbers
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants;
const PANCAKE_SWAP_FORKS = [ERC20BridgeSource.PancakeSwap, ERC20BridgeSource.BakerySwap, ERC20BridgeSource.SushiSwap];
// use the same order in IPancakeSwapFeature.sol
const PANCAKE_SWAP_FORKS = [
ERC20BridgeSource.PancakeSwap,
ERC20BridgeSource.PancakeSwapV2,
ERC20BridgeSource.BakerySwap,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.ApeSwap,
ERC20BridgeSource.CafeSwap,
ERC20BridgeSource.CheeseSwap,
ERC20BridgeSource.JulSwap,
];
const DUMMY_WETH_CONTRACT = new WETH9Contract(NULL_ADDRESS, {
sendAsync(): void {
return;
@@ -186,8 +197,13 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
this.chainId === ChainId.BSC &&
isDirectSwapCompatible(quote, optsWithDefaults, [
ERC20BridgeSource.PancakeSwap,
ERC20BridgeSource.PancakeSwapV2,
ERC20BridgeSource.BakerySwap,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.ApeSwap,
ERC20BridgeSource.CafeSwap,
ERC20BridgeSource.CheeseSwap,
ERC20BridgeSource.JulSwap,
])
) {
const source = slippedOrders[0].source;

View File

@@ -2,12 +2,17 @@ import { ChainId } from '@0x/contract-addresses';
import { BigNumber, NULL_BYTES } from '@0x/utils';
import {
APESWAP_ROUTER_BY_CHAIN_ID,
BAKERYSWAP_ROUTER_BY_CHAIN_ID,
BELT_BSC_INFOS,
CAFESWAP_ROUTER_BY_CHAIN_ID,
CHEESESWAP_ROUTER_BY_CHAIN_ID,
COMPONENT_POOLS_BY_CHAIN_ID,
CRYPTO_COM_ROUTER_BY_CHAIN_ID,
CURVE_MAINNET_INFOS,
ELLIPSIS_BSC_INFOS,
JULSWAP_ROUTER_BY_CHAIN_ID,
KYBER_BANNED_RESERVES,
KYBER_BRIDGED_LIQUIDITY_PREFIX,
KYBER_DMM_ROUTER_BY_CHAIN_ID,
MAX_DODOV2_POOLS_QUERIED,
@@ -15,7 +20,7 @@ import {
NERVE_BSC_INFOS,
NULL_ADDRESS,
PANCAKESWAP_ROUTER_BY_CHAIN_ID,
PANCAKESWAP_V2_ROUTER_BY_CHAIN_ID,
PANCAKESWAPV2_ROUTER_BY_CHAIN_ID,
SADDLE_MAINNET_INFOS,
SHELL_POOLS_BY_CHAIN_ID,
SMOOTHY_BSC_INFOS,
@@ -24,6 +29,7 @@ import {
SUSHISWAP_ROUTER_BY_CHAIN_ID,
SWERVE_MAINNET_INFOS,
UNISWAPV2_ROUTER_BY_CHAIN_ID,
XSIGMA_MAINNET_INFOS,
} from './constants';
import { CurveInfo, ERC20BridgeSource } from './types';
@@ -32,7 +38,11 @@ import { CurveInfo, ERC20BridgeSource } from './types';
* @param reserveId Kyber reserveId
*/
export function isAllowedKyberReserveId(reserveId: string): boolean {
return reserveId !== NULL_BYTES && !reserveId.startsWith(KYBER_BRIDGED_LIQUIDITY_PREFIX);
return (
reserveId !== NULL_BYTES &&
!reserveId.startsWith(KYBER_BRIDGED_LIQUIDITY_PREFIX) &&
!KYBER_BANNED_RESERVES.includes(reserveId)
);
}
// tslint:disable-next-line: completed-docs ban-types
@@ -194,6 +204,19 @@ export function getSaddleInfosForPair(chainId: ChainId, takerToken: string, make
);
}
export function getXSigmaInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.Mainnet) {
return [];
}
return Object.values(XSIGMA_MAINNET_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
(c.tokens.includes(t) && c.metaToken !== undefined && [makerToken, takerToken].includes(c.metaToken)),
),
);
}
export function getShellLikeInfosForPair(
chainId: ChainId,
takerToken: string,
@@ -222,7 +245,8 @@ export function getCurveLikeInfosForPair(
| ERC20BridgeSource.Belt
| ERC20BridgeSource.Ellipsis
| ERC20BridgeSource.Smoothy
| ERC20BridgeSource.Saddle,
| ERC20BridgeSource.Saddle
| ERC20BridgeSource.XSigma,
): CurveInfo[] {
switch (source) {
case ERC20BridgeSource.Curve:
@@ -241,6 +265,8 @@ export function getCurveLikeInfosForPair(
return getSmoothyInfosForPair(chainId, takerToken, makerToken);
case ERC20BridgeSource.Saddle:
return getSaddleInfosForPair(chainId, takerToken, makerToken);
case ERC20BridgeSource.XSigma:
return getXSigmaInfosForPair(chainId, takerToken, makerToken);
default:
throw new Error(`Unknown Curve like source ${source}`);
}
@@ -253,9 +279,13 @@ export function uniswapV2LikeRouterAddress(
| ERC20BridgeSource.SushiSwap
| ERC20BridgeSource.CryptoCom
| ERC20BridgeSource.PancakeSwap
| ERC20BridgeSource.PancakeSwapV2
| ERC20BridgeSource.BakerySwap
| ERC20BridgeSource.KyberDmm
| ERC20BridgeSource.PancakeSwapV2,
| ERC20BridgeSource.ApeSwap
| ERC20BridgeSource.CafeSwap
| ERC20BridgeSource.CheeseSwap
| ERC20BridgeSource.JulSwap,
): string {
switch (source) {
case ERC20BridgeSource.UniswapV2:
@@ -266,12 +296,20 @@ export function uniswapV2LikeRouterAddress(
return CRYPTO_COM_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.PancakeSwap:
return PANCAKESWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.PancakeSwapV2:
return PANCAKESWAPV2_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.BakerySwap:
return BAKERYSWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.KyberDmm:
return KYBER_DMM_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.PancakeSwapV2:
return PANCAKESWAP_V2_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.ApeSwap:
return APESWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.CafeSwap:
return CAFESWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.CheeseSwap:
return CHEESESWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.JulSwap:
return JULSWAP_ROUTER_BY_CHAIN_ID[chainId];
default:
throw new Error(`Unknown UniswapV2 like source ${source}`);
}

View File

@@ -86,6 +86,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Smoothy,
ERC20BridgeSource.Component,
ERC20BridgeSource.Saddle,
ERC20BridgeSource.XSigma,
]),
[ChainId.Ropsten]: new SourceFilters([
ERC20BridgeSource.Kyber,
@@ -107,9 +108,13 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.MultiHop,
ERC20BridgeSource.Nerve,
ERC20BridgeSource.PancakeSwap,
ERC20BridgeSource.PancakeSwapV2,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Smoothy,
ERC20BridgeSource.PancakeSwapV2,
ERC20BridgeSource.ApeSwap,
ERC20BridgeSource.CafeSwap,
ERC20BridgeSource.CheeseSwap,
ERC20BridgeSource.JulSwap,
]),
},
@@ -148,6 +153,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Smoothy,
ERC20BridgeSource.Component,
ERC20BridgeSource.Saddle,
ERC20BridgeSource.XSigma,
]),
[ChainId.Ropsten]: new SourceFilters([
ERC20BridgeSource.Kyber,
@@ -169,9 +175,13 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.MultiHop,
ERC20BridgeSource.Nerve,
ERC20BridgeSource.PancakeSwap,
ERC20BridgeSource.PancakeSwapV2,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Smoothy,
ERC20BridgeSource.PancakeSwapV2,
ERC20BridgeSource.ApeSwap,
ERC20BridgeSource.CafeSwap,
ERC20BridgeSource.CheeseSwap,
ERC20BridgeSource.JulSwap,
]),
},
new SourceFilters([]),
@@ -285,6 +295,7 @@ export const MAINNET_TOKENS = {
STABLEx: '0xcd91538b91b4ba7797d39a2f66e63810b50a33d0',
alUSD: '0xbc6da0fe9ad5f3b0d58160288917aa56653660e9',
FRAX: '0x853d955acef822db058eb8505911ed77f175b99e',
LUSD: '0x5f98805a4e8be255a32880fdec7f6728c6568ba0',
};
export const BSC_TOKENS = {
@@ -334,6 +345,7 @@ export const CURVE_POOLS = {
STABLEx: '0x3252efd4ea2d6c78091a1f43982ee2c3659cc3d1',
alUSD: '0x43b4fdfd4ff969587185cdb6f0bd875c5fc83f8c',
FRAX: '0xd632f22692fac7611d2aa1c0d552930d43caed3b',
LUSD: '0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca',
};
export const SWERVE_POOLS = {
@@ -367,6 +379,10 @@ export const ELLIPSIS_POOLS = {
threePool: '0x160caed03795365f3a589f10c379ffa7d75d4e76',
};
export const XSIGMA_POOLS = {
stable: '0x3333333ACdEdBbC9Ad7bda0876e60714195681c5',
};
export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
{
[ChainId.Mainnet]: [
@@ -478,147 +494,152 @@ export const CURVE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
[CURVE_POOLS.compound]: createCurveExchangeUnderlyingPool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC],
pool: CURVE_POOLS.compound,
gasSchedule: 597e3,
gasSchedule: 587e3,
}),
[CURVE_POOLS.PAX]: createCurveExchangeUnderlyingPool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT, MAINNET_TOKENS.PAX],
pool: CURVE_POOLS.PAX,
gasSchedule: 752e3,
gasSchedule: 742e3,
}),
[CURVE_POOLS.sUSD]: createCurveExchangeUnderlyingPool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT, MAINNET_TOKENS.sUSD],
pool: CURVE_POOLS.sUSD,
gasSchedule: 312e3,
gasSchedule: 302e3,
}),
[CURVE_POOLS.renBTC]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.WBTC],
pool: CURVE_POOLS.renBTC,
gasSchedule: 181e3,
gasSchedule: 171e3,
}),
[CURVE_POOLS.sBTC]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.WBTC, MAINNET_TOKENS.sBTC],
pool: CURVE_POOLS.sBTC,
gasSchedule: 337e3,
gasSchedule: 327e3,
}),
[CURVE_POOLS.HBTC]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.hBTC, MAINNET_TOKENS.WBTC],
pool: CURVE_POOLS.HBTC,
gasSchedule: 220e3,
gasSchedule: 210e3,
}),
[CURVE_POOLS.TRI]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT],
pool: CURVE_POOLS.TRI,
gasSchedule: 186e3,
gasSchedule: 176e3,
}),
[CURVE_POOLS.GUSD]: createCurveMetaTriPool({
token: MAINNET_TOKENS.GUSD,
pool: CURVE_POOLS.GUSD,
gasSchedule: 421e3,
gasSchedule: 411e3,
}),
[CURVE_POOLS.HUSD]: createCurveMetaTriPool({
token: MAINNET_TOKENS.HUSD,
pool: CURVE_POOLS.HUSD,
gasSchedule: 406e3,
gasSchedule: 396e3,
}),
[CURVE_POOLS.USDN]: createCurveMetaTriPool({
token: MAINNET_TOKENS.USDN,
pool: CURVE_POOLS.USDN,
gasSchedule: 408e3,
gasSchedule: 398e3,
}),
[CURVE_POOLS.mUSD]: createCurveMetaTriPool({
token: MAINNET_TOKENS.mUSD,
pool: CURVE_POOLS.mUSD,
gasSchedule: 395e3,
gasSchedule: 385e3,
}),
[CURVE_POOLS.dUSD]: createCurveMetaTriPool({
token: MAINNET_TOKENS.dUSD,
pool: CURVE_POOLS.dUSD,
gasSchedule: 381e3,
gasSchedule: 371e3,
}),
[CURVE_POOLS.tBTC]: createCurveMetaTriBtcPool({
token: MAINNET_TOKENS.tBTC,
pool: CURVE_POOLS.tBTC,
gasSchedule: 492e3,
gasSchedule: 482e3,
}),
[CURVE_POOLS.pBTC]: createCurveMetaTriBtcPool({
token: MAINNET_TOKENS.pBTC,
pool: CURVE_POOLS.pBTC,
gasSchedule: 513e3,
gasSchedule: 503e3,
}),
[CURVE_POOLS.bBTC]: createCurveMetaTriBtcPool({
token: MAINNET_TOKENS.bBTC,
pool: CURVE_POOLS.bBTC,
gasSchedule: 507e3,
gasSchedule: 497e3,
}),
[CURVE_POOLS.oBTC]: createCurveMetaTriBtcPool({
token: MAINNET_TOKENS.oBTC,
pool: CURVE_POOLS.oBTC,
gasSchedule: 498e3,
gasSchedule: 488e3,
}),
[CURVE_POOLS.UST]: createCurveMetaTriPool({
token: MAINNET_TOKENS.UST,
pool: CURVE_POOLS.UST,
gasSchedule: 350e3,
gasSchedule: 340e3,
}),
[CURVE_POOLS.eurs]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.EURS, MAINNET_TOKENS.sEUR],
pool: CURVE_POOLS.eurs,
gasSchedule: 330e3,
gasSchedule: 320e3,
}),
[CURVE_POOLS.aave]: createCurveExchangeUnderlyingPool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT],
pool: CURVE_POOLS.aave,
gasSchedule: 590e3,
gasSchedule: 580e3,
}),
[CURVE_POOLS.aave]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.aDAI, MAINNET_TOKENS.aUSDC, MAINNET_TOKENS.aUSDT],
pool: CURVE_POOLS.aave,
gasSchedule: 590e3,
gasSchedule: 580e3,
}),
[CURVE_POOLS.saave]: createCurveExchangeUnderlyingPool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.sUSD],
pool: CURVE_POOLS.saave,
gasSchedule: 590e3,
gasSchedule: 580e3,
}),
[CURVE_POOLS.saave]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.aDAI, MAINNET_TOKENS.aSUSD],
pool: CURVE_POOLS.saave,
gasSchedule: 590e3,
gasSchedule: 580e3,
}),
[CURVE_POOLS.USDP]: createCurveMetaTriPool({
token: MAINNET_TOKENS.USDP,
pool: CURVE_POOLS.USDP,
gasSchedule: 384e3,
gasSchedule: 374e3,
}),
[CURVE_POOLS.ib]: createCurveExchangeUnderlyingPool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT],
pool: CURVE_POOLS.ib,
gasSchedule: 656e3,
gasSchedule: 646e3,
}),
[CURVE_POOLS.link]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.LINK, MAINNET_TOKENS.sLINK],
pool: CURVE_POOLS.link,
gasSchedule: 329e3,
gasSchedule: 319e3,
}),
[CURVE_POOLS.TUSD]: createCurveMetaTriPool({
token: MAINNET_TOKENS.TUSD,
pool: CURVE_POOLS.TUSD,
gasSchedule: 414e3,
gasSchedule: 404e3,
}),
[CURVE_POOLS.STABLEx]: createCurveMetaTriPool({
token: MAINNET_TOKENS.STABLEx,
pool: CURVE_POOLS.STABLEx,
gasSchedule: 407e3,
gasSchedule: 397e3,
}),
[CURVE_POOLS.alUSD]: createCurveMetaTriPool({
token: MAINNET_TOKENS.alUSD,
pool: CURVE_POOLS.alUSD,
gasSchedule: 397e3,
gasSchedule: 387e3,
}),
[CURVE_POOLS.FRAX]: createCurveMetaTriPool({
token: MAINNET_TOKENS.FRAX,
pool: CURVE_POOLS.FRAX,
gasSchedule: 397e3,
gasSchedule: 387e3,
}),
[CURVE_POOLS.LUSD]: createCurveMetaTriPool({
token: MAINNET_TOKENS.LUSD,
pool: CURVE_POOLS.LUSD,
gasSchedule: 387e3,
}),
};
@@ -626,7 +647,7 @@ export const SWERVE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
[SWERVE_POOLS.y]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT, MAINNET_TOKENS.TUSD],
pool: SWERVE_POOLS.y,
gasSchedule: 150e3,
gasSchedule: 140e3,
}),
};
@@ -634,22 +655,22 @@ export const SNOWSWAP_MAINNET_INFOS: { [name: string]: CurveInfo } = {
[SNOWSWAP_POOLS.yUSD]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.yUSD, MAINNET_TOKENS.ybCRV],
pool: SNOWSWAP_POOLS.yUSD,
gasSchedule: 1000e3,
gasSchedule: 990e3,
}),
[SNOWSWAP_POOLS.yUSD]: createCurveExchangeUnderlyingPool({
tokens: [MAINNET_TOKENS.yCRV, MAINNET_TOKENS.bCRV],
pool: SNOWSWAP_POOLS.yUSD,
gasSchedule: 1000e3,
gasSchedule: 990e3,
}),
[SNOWSWAP_POOLS.yVault]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.yDAI, MAINNET_TOKENS.yUSDC, MAINNET_TOKENS.yUSDT, MAINNET_TOKENS.yTUSD],
pool: SNOWSWAP_POOLS.yVault,
gasSchedule: 1500e3,
gasSchedule: 1490e3,
}),
[SNOWSWAP_POOLS.eth]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.WETH, MAINNET_TOKENS.vETH, MAINNET_TOKENS.ankrETH, MAINNET_TOKENS.crETH],
pool: SNOWSWAP_POOLS.eth,
gasSchedule: 1000e3,
gasSchedule: 990e3,
}),
};
@@ -657,7 +678,7 @@ export const BELT_BSC_INFOS: { [name: string]: CurveInfo } = {
[BELT_POOLS.vPool]: createCurveExchangeUnderlyingPool({
tokens: [BSC_TOKENS.DAI, BSC_TOKENS.USDC, BSC_TOKENS.USDT, BSC_TOKENS.BUSD],
pool: BELT_POOLS.vPool,
gasSchedule: 4500e3,
gasSchedule: 4490e3,
}),
};
@@ -665,6 +686,14 @@ export const ELLIPSIS_BSC_INFOS: { [name: string]: CurveInfo } = {
[ELLIPSIS_POOLS.threePool]: createCurveExchangePool({
tokens: [BSC_TOKENS.BUSD, BSC_TOKENS.USDC, BSC_TOKENS.USDT],
pool: ELLIPSIS_POOLS.threePool,
gasSchedule: 140e3,
}),
};
export const XSIGMA_MAINNET_INFOS: { [name: string]: CurveInfo } = {
[XSIGMA_POOLS.stable]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT],
pool: XSIGMA_POOLS.stable,
gasSchedule: 150e3,
}),
};
@@ -678,18 +707,17 @@ export const SADDLE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
poolAddress: SADDLE_POOLS.stables,
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT],
metaToken: undefined,
gasSchedule: 220e3,
gasSchedule: 150e3,
},
[SADDLE_POOLS.bitcoins]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: SADDLE_POOLS.bitcoins,
tokens: [MAINNET_TOKENS.tBTC, MAINNET_TOKENS.WBTC, MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.sBTC],
metaToken: undefined,
gasSchedule: 150e3,
},
// TODO:Romain having "Cannot swap more than you own" error when running simbot
// [SADDLE_POOLS.bitcoins]: {
// exchangeFunctionSelector: CurveFunctionSelectors.swap,
// sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
// buyQuoteFunctionSelector: CurveFunctionSelectors.None,
// poolAddress: SADDLE_POOLS.stables,
// tokens: [MAINNET_TOKENS.tBTC, MAINNET_TOKENS.WBTC, MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.sBTC],
// metaToken: undefined,
// gasSchedule: 220e3,
// },
};
export const SMOOTHY_MAINNET_INFOS: { [name: string]: CurveInfo } = {
@@ -709,7 +737,7 @@ export const SMOOTHY_MAINNET_INFOS: { [name: string]: CurveInfo } = {
MAINNET_TOKENS.GUSD,
],
metaToken: undefined,
gasSchedule: 200e3,
gasSchedule: 190e3,
},
};
@@ -721,7 +749,7 @@ export const SMOOTHY_BSC_INFOS: { [name: string]: CurveInfo } = {
poolAddress: SMOOTHY_POOLS.syUSD,
tokens: [BSC_TOKENS.BUSD, BSC_TOKENS.USDT, BSC_TOKENS.USDC, BSC_TOKENS.DAI, BSC_TOKENS.PAX, BSC_TOKENS.UST],
metaToken: undefined,
gasSchedule: 100e3,
gasSchedule: 90e3,
},
};
@@ -733,7 +761,7 @@ export const NERVE_BSC_INFOS: { [name: string]: CurveInfo } = {
poolAddress: NERVE_POOLS.threePool,
tokens: [BSC_TOKENS.BUSD, BSC_TOKENS.USDT, BSC_TOKENS.USDC],
metaToken: undefined,
gasSchedule: 150e3,
gasSchedule: 140e3,
},
};
@@ -744,6 +772,7 @@ export const NERVE_BSC_INFOS: { [name: string]: CurveInfo } = {
* 0xbb Bridged price reserve (i.e Uniswap/Curve)
*/
export const KYBER_BRIDGED_LIQUIDITY_PREFIX = '0xbb';
export const KYBER_BANNED_RESERVES = ['0xff4f6e65426974205175616e7400000000000000000000000000000000000000'];
export const MAX_KYBER_RESERVES_QUERIED = 5;
export const KYBER_CONFIG_BY_CHAIN_ID = valueByChainId<KyberSamplerOpts>(
{
@@ -992,7 +1021,7 @@ export const PANCAKESWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
NULL_ADDRESS,
);
export const PANCAKESWAP_V2_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
export const PANCAKESWAPV2_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0x10ed43c718714eb63d5aa57b78b54704e256024e',
},
@@ -1006,6 +1035,34 @@ export const BAKERYSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
NULL_ADDRESS,
);
export const APESWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0xc0788a3ad43d79aa53b09c2eacc313a787d1d607',
},
NULL_ADDRESS,
);
export const CAFESWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0x933daea3a5995fb94b14a7696a5f3ffd7b1e385a',
},
NULL_ADDRESS,
);
export const CHEESESWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0x3047799262d8d2ef41ed2a222205968bc9b0d895',
},
NULL_ADDRESS,
);
export const JULSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0xbd67d157502a23309db761c41965600c2ec788b2',
},
NULL_ADDRESS,
);
/**
* Calculated gross gas cost of the underlying exchange.
* The cost of switching from one source to another, assuming
@@ -1037,6 +1094,7 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.Ellipsis]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.Smoothy]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.Saddle]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.XSigma]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.MultiBridge]: () => 350e3,
[ERC20BridgeSource.UniswapV2]: (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
@@ -1136,6 +1194,15 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
}
return gas;
},
[ERC20BridgeSource.PancakeSwapV2]: (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
let gas = 90e3;
const path = (fillData as UniswapV2FillData).tokenAddressPath;
if (path.length > 2) {
gas += (path.length - 2) * 60e3; // +60k for each hop.
}
return gas;
},
[ERC20BridgeSource.BakerySwap]: (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
let gas = 90e3;
@@ -1145,7 +1212,34 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
}
return gas;
},
[ERC20BridgeSource.PancakeSwapV2]: (fillData?: FillData) => {
[ERC20BridgeSource.ApeSwap]: (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
let gas = 90e3;
const path = (fillData as UniswapV2FillData).tokenAddressPath;
if (path.length > 2) {
gas += (path.length - 2) * 60e3; // +60k for each hop.
}
return gas;
},
[ERC20BridgeSource.CafeSwap]: (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
let gas = 90e3;
const path = (fillData as UniswapV2FillData).tokenAddressPath;
if (path.length > 2) {
gas += (path.length - 2) * 60e3; // +60k for each hop.
}
return gas;
},
[ERC20BridgeSource.CheeseSwap]: (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
let gas = 90e3;
const path = (fillData as UniswapV2FillData).tokenAddressPath;
if (path.length > 2) {
gas += (path.length - 2) * 60e3; // +60k for each hop.
}
return gas;
},
[ERC20BridgeSource.JulSwap]: (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
let gas = 90e3;
const path = (fillData as UniswapV2FillData).tokenAddressPath;

View File

@@ -560,7 +560,12 @@ export class MarketOperationUtils {
// We create a fallback path that is exclusive of Native liquidity
// This is the optimal on-chain path for the entire input amount
const nonNativeFills = fills.filter(p => p.length > 0 && p[0].source !== ERC20BridgeSource.Native);
const nonNativeOptimalPath = await findOptimalPathAsync(side, nonNativeFills, inputAmount, opts.runLimit);
const nonNativeOptimalPath = await findOptimalPathAsync(side, nonNativeFills, inputAmount, opts.runLimit, {
...penaltyOpts,
exchangeProxyOverhead: (sourceFlags: number) =>
// tslint:disable-next-line: no-bitwise
penaltyOpts.exchangeProxyOverhead(sourceFlags | optimalPath.sourceFlags),
});
// Calculate the slippage of on-chain sources compared to the most optimal path
if (
nonNativeOptimalPath !== undefined &&

View File

@@ -120,6 +120,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'Linkswap');
case ERC20BridgeSource.PancakeSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwap');
case ERC20BridgeSource.PancakeSwapV2:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwapV2');
case ERC20BridgeSource.BakerySwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'BakerySwap');
case ERC20BridgeSource.Nerve:
@@ -134,8 +136,16 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Smoothy');
case ERC20BridgeSource.Saddle:
return encodeBridgeSourceId(BridgeProtocol.Nerve, 'Saddle');
case ERC20BridgeSource.PancakeSwapV2:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwapV2');
case ERC20BridgeSource.XSigma:
return encodeBridgeSourceId(BridgeProtocol.Curve, 'xSigma');
case ERC20BridgeSource.ApeSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'ApeSwap');
case ERC20BridgeSource.CafeSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'CafeSwap');
case ERC20BridgeSource.CheeseSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'CheeseSwap');
case ERC20BridgeSource.JulSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'JulSwap');
default:
throw new Error(AggregationError.NoBridgeForSource);
}
@@ -165,6 +175,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
case ERC20BridgeSource.Ellipsis:
case ERC20BridgeSource.Smoothy:
case ERC20BridgeSource.Saddle:
case ERC20BridgeSource.XSigma:
const curveFillData = (order as OptimizedMarketBridgeOrder<CurveFillData>).fillData;
bridgeData = encoder.encode([
curveFillData.pool.poolAddress,
@@ -187,9 +198,13 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
case ERC20BridgeSource.CryptoCom:
case ERC20BridgeSource.Linkswap:
case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.ApeSwap:
case ERC20BridgeSource.CafeSwap:
case ERC20BridgeSource.CheeseSwap:
case ERC20BridgeSource.JulSwap:
const uniswapV2FillData = (order as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]);
break;
@@ -316,6 +331,7 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.Ellipsis]: curveEncoder,
[ERC20BridgeSource.Smoothy]: curveEncoder,
[ERC20BridgeSource.Saddle]: curveEncoder,
[ERC20BridgeSource.XSigma]: curveEncoder,
// UniswapV2 like, (router, address[])
[ERC20BridgeSource.Bancor]: routerAddressPathEncoder,
[ERC20BridgeSource.UniswapV2]: routerAddressPathEncoder,
@@ -323,6 +339,14 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder,
[ERC20BridgeSource.Linkswap]: routerAddressPathEncoder,
[ERC20BridgeSource.KyberDmm]: routerAddressPathEncoder,
// BSC
[ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder,
[ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder,
[ERC20BridgeSource.ApeSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.CafeSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.CheeseSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.JulSwap]: routerAddressPathEncoder,
// Generic pools
[ERC20BridgeSource.Shell]: poolEncoder,
[ERC20BridgeSource.Component]: poolEncoder,
@@ -334,10 +358,6 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.Uniswap]: poolEncoder,
// Custom integrations
[ERC20BridgeSource.MakerPsm]: makerPsmEncoder,
// BSC
[ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder,
[ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder,
};
function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] {

View File

@@ -1100,9 +1100,13 @@ export class SamplerOperations {
case ERC20BridgeSource.SushiSwap:
case ERC20BridgeSource.CryptoCom:
case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.ApeSwap:
case ERC20BridgeSource.CafeSwap:
case ERC20BridgeSource.CheeseSwap:
case ERC20BridgeSource.JulSwap:
const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source);
if (!isValidAddress(uniLikeRouter)) {
return [];
@@ -1128,6 +1132,7 @@ export class SamplerOperations {
case ERC20BridgeSource.Belt:
case ERC20BridgeSource.Ellipsis:
case ERC20BridgeSource.Saddle:
case ERC20BridgeSource.XSigma:
return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getCurveSellQuotes(
pool,
@@ -1310,9 +1315,13 @@ export class SamplerOperations {
case ERC20BridgeSource.SushiSwap:
case ERC20BridgeSource.CryptoCom:
case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.ApeSwap:
case ERC20BridgeSource.CafeSwap:
case ERC20BridgeSource.CheeseSwap:
case ERC20BridgeSource.JulSwap:
const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source);
if (!isValidAddress(uniLikeRouter)) {
return [];
@@ -1338,6 +1347,7 @@ export class SamplerOperations {
case ERC20BridgeSource.Belt:
case ERC20BridgeSource.Ellipsis:
case ERC20BridgeSource.Saddle:
case ERC20BridgeSource.XSigma:
return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getCurveBuyQuotes(
pool,

View File

@@ -63,13 +63,18 @@ export enum ERC20BridgeSource {
Smoothy = 'Smoothy',
Component = 'Component',
Saddle = 'Saddle',
XSigma = 'xSigma',
// BSC only
PancakeSwap = 'PancakeSwap',
PancakeSwapV2 = 'PancakeSwap_V2',
BakerySwap = 'BakerySwap',
Nerve = 'Nerve',
Belt = 'Belt',
Ellipsis = 'Ellipsis',
PancakeSwapV2 = 'PancakeSwap_V2',
ApeSwap = 'ApeSwap',
CafeSwap = 'CafeSwap',
CheeseSwap = 'CheeseSwap',
JulSwap = 'JulSwap',
}
// tslint:disable: enum-naming

View File

@@ -47,33 +47,16 @@ import {
const MAKER_TOKEN = randomAddress();
const TAKER_TOKEN = randomAddress();
const DEFAULT_EXCLUDED = [
ERC20BridgeSource.UniswapV2,
ERC20BridgeSource.Curve,
ERC20BridgeSource.Balancer,
ERC20BridgeSource.MStable,
ERC20BridgeSource.Mooniswap,
ERC20BridgeSource.Bancor,
ERC20BridgeSource.Swerve,
ERC20BridgeSource.SnowSwap,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.MultiHop,
ERC20BridgeSource.Shell,
ERC20BridgeSource.Cream,
ERC20BridgeSource.Dodo,
ERC20BridgeSource.DodoV2,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.CryptoCom,
ERC20BridgeSource.Linkswap,
ERC20BridgeSource.PancakeSwap,
ERC20BridgeSource.BakerySwap,
ERC20BridgeSource.MakerPsm,
ERC20BridgeSource.KyberDmm,
ERC20BridgeSource.Smoothy,
ERC20BridgeSource.Component,
ERC20BridgeSource.Saddle,
ERC20BridgeSource.PancakeSwapV2,
const DEFAULT_INCLUDED = [
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.Kyber,
ERC20BridgeSource.Native,
ERC20BridgeSource.Uniswap,
];
const DEFAULT_EXCLUDED = SELL_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources.filter(
s => !DEFAULT_INCLUDED.includes(s),
);
const BUY_SOURCES = BUY_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources;
const SELL_SOURCES = SELL_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources;
const TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = { default: [] };

View File

@@ -1,4 +1,12 @@
[
{
"version": "6.1.0",
"changes": [
{
"note": "Deployed FQT on mainnet and ropsten for `Balancer_V2`"
}
]
},
{
"version": "6.0.0",
"changes": [

View File

@@ -36,7 +36,7 @@
"wethTransformer": "0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7",
"payTakerTransformer": "0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e",
"affiliateFeeTransformer": "0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f",
"fillQuoteTransformer": "0xb8e40acea68db2a7a2020a3eba2664ba4c3b3e3d",
"fillQuoteTransformer": "0x025b4124732b1bf90cdd574975a99a6215de4a55",
"positiveSlippageFeeTransformer": "0xa9416ce1dbde8d331210c07b5c253d94ee4cc3fd"
}
},
@@ -77,7 +77,7 @@
"wethTransformer": "0x05ad19aa3826e0609a19568ffbd1dfe86c6c7184",
"payTakerTransformer": "0x6d0ebf2bcd9cc93ec553b60ad201943dcca4e291",
"affiliateFeeTransformer": "0x6588256778ca4432fa43983ac685c45efb2379e2",
"fillQuoteTransformer": "0xc0c6fc6911978a65fe3b17391bb30b630bfc637d",
"fillQuoteTransformer": "0x27cd03bf6c49c15b7a2f5e9cde56329ebfaf153f",
"positiveSlippageFeeTransformer": "0x8b332f700fd37e71c5c5b26c4d78b5ca63dd33b2"
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contract-wrappers-test",
"version": "12.2.42",
"version": "12.2.44",
"engines": {
"node": ">=6.12"
},
@@ -34,7 +34,7 @@
"@0x/contract-wrappers": "^13.16.0",
"@0x/contracts-test-utils": "^5.3.25",
"@0x/dev-utils": "^4.2.6",
"@0x/migrations": "^8.0.3",
"@0x/migrations": "^8.0.5",
"@0x/order-utils": "^10.4.20",
"@0x/subproviders": "^6.5.2",
"@0x/ts-doc-gen": "^0.0.28",

View File

@@ -1,4 +1,22 @@
[
{
"timestamp": 1619830995,
"version": "8.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1619825976,
"version": "8.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1619596077,
"version": "8.0.3",

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v8.0.5 - _May 1, 2021_
* Dependencies updated
## v8.0.4 - _April 30, 2021_
* Dependencies updated
## v8.0.3 - _April 28, 2021_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/migrations",
"version": "8.0.3",
"version": "8.0.5",
"engines": {
"node": ">=6.12"
},
@@ -81,7 +81,7 @@
"@0x/contracts-multisig": "^4.1.29",
"@0x/contracts-staking": "^2.0.36",
"@0x/contracts-utils": "^4.7.7",
"@0x/contracts-zero-ex": "^0.22.1",
"@0x/contracts-zero-ex": "^0.22.3",
"@0x/sol-compiler": "^4.7.2",
"@0x/subproviders": "^6.5.2",
"@0x/typescript-typings": "^5.2.0",