Skip to content

Commit

Permalink
Tasks: Implement Odos swap task (#159)
Browse files Browse the repository at this point in the history
Co-authored-by: Facu Spagnuolo <facundo_spagnuolo@icloud.com>
  • Loading branch information
PedroAraoz and facuspagnuolo committed Aug 16, 2024
1 parent 561915e commit 340bb2c
Show file tree
Hide file tree
Showing 6 changed files with 609 additions and 2 deletions.
27 changes: 27 additions & 0 deletions packages/tasks/contracts/interfaces/swap/IOdosV2Swapper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

pragma solidity >=0.8.0;

import './IBaseSwapTask.sol';

/**
* @dev Odos swapper task interface
*/
interface IOdosV2Swapper is IBaseSwapTask {
/**
* @dev Execution function
*/
function call(address tokenIn, uint256 amountIn, uint256 slippage, bytes memory data) external;
}
113 changes: 113 additions & 0 deletions packages/tasks/contracts/swap/OdosV2Swapper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

pragma solidity ^0.8.0;

import '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol';
import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol';
import '@mimic-fi/v3-connectors/contracts/interfaces/odos/IOdosV2Connector.sol';

import './BaseSwapTask.sol';
import '../interfaces/swap/IOdosV2Swapper.sol';

/**
* @title Odos v2 swapper
* @dev Task that extends the base swap task to use Odos v2
*/
contract OdosV2Swapper is IOdosV2Swapper, BaseSwapTask {
using FixedPoint for uint256;
using BytesHelpers for bytes;

// Execution type for relayers
bytes32 public constant override EXECUTION_TYPE = keccak256('ODOS_V2_SWAPPER');

/**
* @dev Odos v2 swap config. Only used in the initializer.
*/
struct OdosV2SwapConfig {
BaseSwapConfig baseSwapConfig;
}

/**
* @dev Initializes the Odos v2 swapper
* @param config Odos v2 swap config
*/
function initialize(OdosV2SwapConfig memory config) external virtual initializer {
__OdosV2Swapper_init(config);
}

/**
* @dev Initializes the Odos v2 swapper. It does call upper contracts initializers.
* @param config Odos v2 swap config
*/
function __OdosV2Swapper_init(OdosV2SwapConfig memory config) internal onlyInitializing {
__BaseSwapTask_init(config.baseSwapConfig);
__OdosV2Swapper_init_unchained(config);
}

/**
* @dev Initializes the Odos v2 swapper. It does not call upper contracts initializers.
* @param config Odos v2 swap config
*/
function __OdosV2Swapper_init_unchained(OdosV2SwapConfig memory config) internal onlyInitializing {
// solhint-disable-previous-line no-empty-blocks
}

/**
* @dev Executes the Odos V2 swapper task
*/
function call(address tokenIn, uint256 amountIn, uint256 slippage, bytes memory data)
external
override
authP(authParams(tokenIn, amountIn, slippage))
{
if (amountIn == 0) amountIn = getTaskAmount(tokenIn);
_beforeOdosV2Swapper(tokenIn, amountIn, slippage);

address tokenOut = getTokenOut(tokenIn);
uint256 price = _getPrice(tokenIn, tokenOut);
uint256 minAmountOut = amountIn.mulUp(price).mulUp(FixedPoint.ONE - slippage);
bytes memory connectorData = abi.encodeWithSelector(
IOdosV2Connector.execute.selector,
tokenIn,
tokenOut,
amountIn,
minAmountOut,
data
);

bytes memory result = ISmartVault(smartVault).execute(connector, connectorData);
_afterOdosV2Swapper(tokenIn, amountIn, slippage, tokenOut, result.toUint256());
}

/**
* @dev Before Odos v2 swapper hook
*/
function _beforeOdosV2Swapper(address token, uint256 amount, uint256 slippage) internal virtual {
_beforeBaseSwapTask(token, amount, slippage);
}

/**
* @dev After Odos v2 swapper hook
*/
function _afterOdosV2Swapper(
address tokenIn,
uint256 amountIn,
uint256 slippage,
address tokenOut,
uint256 amountOut
) internal virtual {
_afterBaseSwapTask(tokenIn, amountIn, slippage, tokenOut, amountOut);
}
}
27 changes: 27 additions & 0 deletions packages/tasks/contracts/test/swap/OdosV2ConnectorMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

pragma solidity ^0.8.0;

contract OdosV2ConnectorMock {
event LogExecute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes data);

function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data)
external
returns (uint256)
{
emit LogExecute(tokenIn, tokenOut, amountIn, minAmountOut, data);
return minAmountOut;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('BalancerV2BoostedSwapper', function () {

before('deploy connector', async () => {
connector = await deploy(
'@mimic-fi/v3-connectors/artifacts/contracts/swap/balancer/BalancerV2SwapConnector.sol/BalancerV2SwapConnector',
'@mimic-fi/v3-connectors/artifacts/contracts/balancer/BalancerV2SwapConnector.sol/BalancerV2SwapConnector',
[BALANCER_VAULT]
)
const overrideConnectorCheckRole = smartVault.interface.getSighash('overrideConnectorCheck')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('BalancerV2LinearSwapper', function () {

before('deploy connector', async () => {
connector = await deploy(
'@mimic-fi/v3-connectors/artifacts/contracts/swap/balancer/BalancerV2SwapConnector.sol/BalancerV2SwapConnector',
'@mimic-fi/v3-connectors/artifacts/contracts/balancer/BalancerV2SwapConnector.sol/BalancerV2SwapConnector',
[BALANCER_VAULT]
)
const overrideConnectorCheckRole = smartVault.interface.getSighash('overrideConnectorCheck')
Expand Down
Loading

0 comments on commit 340bb2c

Please sign in to comment.