add weth/eth wrap/unwrap support for bancorv3

This commit is contained in:
Noah Khamliche 2022-06-02 20:14:02 -04:00 committed by Noah Khamliche
parent f5c486050b
commit 9b131199ad
5 changed files with 56 additions and 14 deletions

View File

@ -75,6 +75,7 @@ contract EthereumBridgeAdapter is
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
public public
MixinBancor(weth) MixinBancor(weth)
MixinBancorV3(weth)
MixinCompound(weth) MixinCompound(weth)
MixinCurve(weth) MixinCurve(weth)
MixinLido(weth) MixinLido(weth)

View File

@ -23,6 +23,8 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
/* /*
BancorV3 BancorV3
@ -42,25 +44,37 @@ interface IBancorV3 {
uint256 minReturnAmount, uint256 minReturnAmount,
uint256 deadline, uint256 deadline,
address beneficiary address beneficiary
) external returns (uint256 amount); ) external payable returns (uint256 amount);
} }
contract MixinBancorV3 { contract MixinBancorV3 {
using LibERC20TokenV06 for IERC20TokenV06; using LibERC20TokenV06 for IERC20TokenV06;
IERC20TokenV06 constant public BANCORV3_ETH_ADDRESS =
IERC20TokenV06(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
IEtherTokenV06 private immutable WETH;
constructor(IEtherTokenV06 weth)
public
{
WETH = weth;
}
function _tradeBancorV3( function _tradeBancorV3(
IERC20TokenV06 buyToken, IERC20TokenV06 buyToken,
uint256 sellAmount, uint256 sellAmount,
bytes memory bridgeData bytes memory bridgeData
) )
public internal
returns (uint256 amountOut) returns (uint256 amountOut)
{ {
IBancorV3 router; IBancorV3 router;
IERC20TokenV06[] memory path; IERC20TokenV06[] memory path;
address[] memory _path; address[] memory _path;
uint256 payableAmount = 0;
{ {
(router, _path) = abi.decode(bridgeData, (IBancorV3, address[])); (router, _path) = abi.decode(bridgeData, (IBancorV3, address[]));
// To get around `abi.decode()` not supporting interface array types. // To get around `abi.decode()` not supporting interface array types.
@ -72,11 +86,26 @@ contract MixinBancorV3 {
path[path.length - 1] == buyToken, path[path.length - 1] == buyToken,
"MixinBancorV3/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN" "MixinBancorV3/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
); );
//swap WETH->ETH as Bancor only deals in ETH
if(_path[0] == address(WETH)) {
//withdraw the sell amount of WETH for ETH
WETH.withdraw(sellAmount);
payableAmount = sellAmount;
// set _path[0] to the ETH address if WETH is our buy token
_path[0] = address(BANCORV3_ETH_ADDRESS);
} else {
// Grant the BancorV3 router an allowance to sell the first token. // Grant the BancorV3 router an allowance to sell the first token.
path[0].approveIfBelow(address(router), sellAmount); path[0].approveIfBelow(address(router), sellAmount);
}
// if we are buying WETH we need to swap to ETH and deposit into WETH after the swap
if(_path[1] == address(WETH)){
_path[1] = address(BANCORV3_ETH_ADDRESS);
}
uint256 amountOut = router.tradeBySourceAmount( uint256 amountOut = router.tradeBySourceAmount{value: payableAmount}(
_path[0], _path[0],
_path[1], _path[1],
// Sell all tokens we hold. // Sell all tokens we hold.
@ -89,6 +118,11 @@ contract MixinBancorV3 {
address(this) address(this)
); );
// if we want to return WETH deposit the ETH amount we sold
if(buyToken == WETH){
WETH.deposit{value: amountOut}();
}
return amountOut; return amountOut;
} }
} }

View File

@ -34,7 +34,8 @@
"contracts:gen": "contracts-gen generate", "contracts:gen": "contracts-gen generate",
"contracts:copy": "contracts-gen copy", "contracts:copy": "contracts-gen copy",
"publish:private": "yarn build && gitpkg publish", "publish:private": "yarn build && gitpkg publish",
"sampler-size": "jq .compilerOutput.evm.deployedBytecode.object -- test/generated-artifacts/ERC20BridgeSampler.json | echo $(( $(wc -c) / 2 - 1 ))" "sampler-size": "jq .compilerOutput.evm.deployedBytecode.object -- test/generated-artifacts/ERC20BridgeSampler.json | echo $(( $(wc -c) / 2 - 1 ))",
"list:deps": "yarn lerna list -l"
}, },
"config": { "config": {
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker", "publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker",

View File

@ -208,6 +208,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.Platypus, 'Platypus'); return encodeBridgeSourceId(BridgeProtocol.Platypus, 'Platypus');
case ERC20BridgeSource.MeshSwap: case ERC20BridgeSource.MeshSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MeshSwap'); return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MeshSwap');
case ERC20BridgeSource.BancorV3:
return encodeBridgeSourceId(BridgeProtocol.BancorV3, 'BancorV3');
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);
} }
@ -387,7 +389,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
break; break;
case ERC20BridgeSource.BancorV3: case ERC20BridgeSource.BancorV3:
const bancorV3FillData = (order as OptimizedMarketBridgeOrder<BancorFillData>).fillData; const bancorV3FillData = (order as OptimizedMarketBridgeOrder<BancorFillData>).fillData;
bridgeData = encoder.encode([bancorV3FillData.networkAddress, bancorFillData.path, bancor]); bridgeData = encoder.encode([bancorV3FillData.networkAddress, bancorV3FillData.path]);
break; break;
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);

View File

@ -713,6 +713,7 @@ export class SamplerOperations {
public getBancorV3SellQuotes( public getBancorV3SellQuotes(
networkAddress: string, networkAddress: string,
networkInfoAddress: string,
path: string[], path: string[],
takerFillAmounts: BigNumber[], takerFillAmounts: BigNumber[],
): SourceQuoteOperation<BancorFillData> { ): SourceQuoteOperation<BancorFillData> {
@ -721,13 +722,14 @@ export class SamplerOperations {
fillData: { networkAddress, path}, fillData: { networkAddress, path},
contract: this._samplerContract, contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromBancorV3, function: this._samplerContract.sampleBuysFromBancorV3,
params: [networkAddress, path, takerFillAmounts], params: [networkInfoAddress, path, takerFillAmounts],
}); });
} }
// Unimplemented // Unimplemented
public getBancorV3BuyQuotes( public getBancorV3BuyQuotes(
networkAddress: string, networkAddress: string,
networkInfoAddress: string,
path: string[], path: string[],
makerFillAmounts: BigNumber[], makerFillAmounts: BigNumber[],
): SourceQuoteOperation<BancorFillData> { ): SourceQuoteOperation<BancorFillData> {
@ -736,7 +738,7 @@ export class SamplerOperations {
fillData: { networkAddress, path}, fillData: { networkAddress, path},
contract: this._samplerContract, contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromBancorV3, function: this._samplerContract.sampleBuysFromBancorV3,
params: [networkAddress, path, makerFillAmounts], params: [networkInfoAddress, path, makerFillAmounts],
}); });
} }
@ -1710,9 +1712,10 @@ export class SamplerOperations {
} }
case ERC20BridgeSource.BancorV3: { case ERC20BridgeSource.BancorV3: {
return this.getBancorV3SellQuotes( return this.getBancorV3SellQuotes(
BANCORV3_NETWORK_BY_CHAIN_ID[this.chainId],
BANCORV3_NETWORK_INFO_BY_CHAIN_ID[this.chainId], BANCORV3_NETWORK_INFO_BY_CHAIN_ID[this.chainId],
[takerToken, makerToken], [takerToken, makerToken],
takerFillAmounts takerFillAmounts,
); );
} }
default: default:
@ -2044,10 +2047,11 @@ export class SamplerOperations {
); );
} }
case ERC20BridgeSource.BancorV3: { case ERC20BridgeSource.BancorV3: {
return this.getBancorV3SellQuotes( return this.getBancorV3BuyQuotes(
BANCORV3_NETWORK_BY_CHAIN_ID[this.chainId],
BANCORV3_NETWORK_INFO_BY_CHAIN_ID[this.chainId], BANCORV3_NETWORK_INFO_BY_CHAIN_ID[this.chainId],
[takerToken, makerToken], [takerToken, makerToken],
makerFillAmounts makerFillAmounts,
); );
} }
default: default: