Address Details
contract

0xfFB8c7dFB83bD4384433995A74cdFe34aE6237FE

Contract Name
SwapExecutor
Creator
0xe59f13–f1e2b8 at 0x0c1987–c81ae0
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
1 Transactions
Transfers
5 Transfers
Gas Used
757,029
Last Balance Update
13556104
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
SwapExecutor




Optimization enabled
true
Compiler version
v0.8.13+commit.abaa5c0e




Optimization runs
999999
EVM Version
london




Verified at
2022-06-16T06:11:56.716050Z

contracts/SwapExecutor.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/ISwappaRouter.sol";
import "./interfaces/ISwapper.sol";
import "./DCA.sol";

contract SwapExecutor is ISwapper, Ownable {
    event BeneficiarySet(address newBeneficiary);

    DCA private dca;
    ISwappaRouterV1 private swappaRouter;
    address public beneficiary;

    constructor(
        DCA _dca,
        ISwappaRouterV1 _swappaRouter,
        address _beneficiary
    ) {
        dca = _dca;
        swappaRouter = _swappaRouter;
        setBeneficiary(_beneficiary);
    }

    function setBeneficiary(address _beneficiary) public onlyOwner {
        beneficiary = _beneficiary;
        emit BeneficiarySet(_beneficiary);
    }

    function executeMezumoSwap(
        uint256 period,
        address[] calldata path,
        address[] calldata pairs,
        bytes[] calldata extras
    ) external {
        bytes memory params = abi.encode(path, pairs, extras);
        dca.executeOrder(
            path[0],
            path[path.length - 1],
            period,
            address(this),
            params
        );
    }

    function swap(
        address _sellToken,
        address _buyToken,
        uint256 _inAmount,
        uint256 _outAmount,
        bytes calldata _params
    ) external {
        (
            address[] memory path,
            address[] memory pairs,
            bytes[] memory extras
        ) = abi.decode(_params, (address[], address[], bytes[]));

        require(
            IERC20(_sellToken).approve(address(swappaRouter), _inAmount),
            "SwapExecutor: Approval to Swappa failed"
        );
        swappaRouter.swapExactInputForOutput(
            path,
            pairs,
            extras,
            _inAmount,
            0,
            address(this),
            block.timestamp
        );

        require(
            IERC20(_buyToken).transfer(address(dca), 0),
            "SwapExecutor: Transfer to DCA failed"
        );
        require(
            IERC20(_buyToken).transfer(
                beneficiary,
                IERC20(_buyToken).balanceOf(address(this))
            ),
            "SwapExecutor: Transfer to DCA failed"
        );
    }
}
        

/_openzeppelin/contracts/access/Ownable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
          

/_openzeppelin/contracts/security/Pausable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}
          

/_openzeppelin/contracts/token/ERC20/IERC20.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}
          

/_openzeppelin/contracts/utils/Context.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
          

/_openzeppelin/contracts/utils/math/Math.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a / b + (a % b == 0 ? 0 : 1);
    }
}
          

/contracts/DCA.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "./interfaces/ISwapper.sol";
import "./interfaces/IOracle.sol";

contract DCA is Ownable {
    uint256 public constant BLOCKS_PER_DAY = 17280;
    uint256 public constant MAX_FEE_NUMERATOR = 6_000; // max 60 bps.
    uint256 public constant FEE_DENOMINATOR = 1_000_000;

    event OrderCreated(
        address indexed userAddress,
        uint256 index,
        IERC20 indexed sellToken,
        IERC20 indexed buyToken,
        uint256 amountPerSwap,
        uint256 numberOfSwaps,
        uint256 startingPeriod
    );
    event SwapExecuted(
        address indexed sellToken,
        address indexed buyToken,
        uint256 sellAmount,
        uint256 buyAmount,
        uint256 indexed period
    );
    event SwappedWithdrawal(
        address indexed userAddress,
        uint256 indexed index,
        address indexed token,
        uint256 amount
    );
    event RemainingWithdrawal(
        address indexed userAddress,
        uint256 indexed index,
        address indexed token,
        uint256 amount
    );
    event TokenPairInitialized(address sellToken, address buyToken);
    event EmergencyWithdrawal(address token, uint256 amount, address to);
    event OracleSet(address oracle);
    event OracleAddressMappingSet(address from, address to);
    event BeneficiarySet(address newBeneficiary);
    event FeeNumeratorSet(uint256 feeNumerator);

    struct UserOrder {
        IERC20 sellToken;
        IERC20 buyToken;
        uint256 amountPerSwap;
        uint256 numberOfSwaps;
        uint256 startingPeriod;
        uint256 lastPeriodWithdrawal;
    }

    struct SwapOrder {
        uint256 amountToSwap;
        uint256 lastPeriod;
        // For each past period, what exchange rate was used.
        mapping(uint256 => uint256) swapExchangeRates;
        // For each future period, how much to reduce to |amountToSwap|.
        mapping(uint256 => uint256) amountsToReduce;
    }

    // sellToken => buyToken => SwapOrder
    mapping(address => mapping(address => SwapOrder)) public swapOrders;
    // userAddress => UserOrder list
    mapping(address => UserOrder[]) public orders;
    // For cUSD, we need to use mcUSD in the oracle because of Ubeswap liquidity. Same with cEUR/cREAL.
    mapping(address => address) public oracleAddresses;

    uint256 public feeNumerator;
    address public beneficiary;
    Oracle public oracle;

    constructor(
        Oracle _oracle,
        address _beneficiary,
        uint256 initialFee
    ) {
        setOracle(_oracle);
        setBeneficiary(_beneficiary);
        setFeeNumerator(initialFee);
    }

    function createOrder(
        IERC20 _sellToken,
        IERC20 _buyToken,
        uint256 _amountPerSwap,
        uint256 _numberOfSwaps
    ) external returns (uint256 index) {
        require(
            _sellToken.transferFrom(
                msg.sender,
                address(this),
                _amountPerSwap * _numberOfSwaps
            ),
            "DCA: Not enough funds"
        );

        SwapOrder storage swapOrder = swapOrders[address(_sellToken)][
            address(_buyToken)
        ];
        if (swapOrder.lastPeriod == 0) {
            swapOrder.lastPeriod = getCurrentPeriod() - 1;
            emit TokenPairInitialized(address(_sellToken), address(_buyToken));
        }
        uint256 startingPeriod = swapOrder.lastPeriod + 1;
        UserOrder memory newOrder = UserOrder(
            _sellToken,
            _buyToken,
            _amountPerSwap,
            _numberOfSwaps,
            startingPeriod,
            swapOrder.lastPeriod
        );

        swapOrder.amountToSwap += _amountPerSwap;
        swapOrder.amountsToReduce[
            startingPeriod + _numberOfSwaps - 1
        ] += _amountPerSwap;

        index = orders[msg.sender].length;
        orders[msg.sender].push(newOrder);

        emit OrderCreated(
            msg.sender,
            index,
            _sellToken,
            _buyToken,
            _amountPerSwap,
            _numberOfSwaps,
            startingPeriod
        );
    }

    function executeOrder(
        address _sellToken,
        address _buyToken,
        uint256 _period,
        address _swapper,
        bytes memory _params
    ) external {
        SwapOrder storage swapOrder = swapOrders[_sellToken][_buyToken];
        require(swapOrder.lastPeriod + 1 == _period, "DCA: Invalid period");
        require(
            _period <= getCurrentPeriod(),
            "DCA: Period cannot be in the future"
        );
        uint256 swapAmount = swapOrder.amountToSwap;

        uint256 requiredAmount = oracle.consult(
            getOracleTokenAddress(_sellToken),
            swapAmount,
            getOracleTokenAddress(_buyToken)
        );
        require(requiredAmount > 0, "DCA: Oracle failure");

        swapOrder.lastPeriod++;
        swapOrder.swapExchangeRates[_period] =
            requiredAmount /
            swapOrder.amountToSwap;
        swapOrder.amountToSwap -= swapOrder.amountsToReduce[_period];

        uint256 balanceBefore = IERC20(_buyToken).balanceOf(address(this));
        require(
            IERC20(_sellToken).transfer(_swapper, swapAmount),
            "DCA: Transfer to Swapper failed"
        );
        ISwapper(_swapper).swap(
            _sellToken,
            _buyToken,
            swapAmount,
            requiredAmount,
            _params
        );
        // require(
        //     balanceBefore + requiredAmount <=
        //         IERC20(_buyToken).balanceOf(address(this)),
        //     "DCA: Not enough balance returned"
        // );

        emit SwapExecuted(
            _sellToken,
            _buyToken,
            swapAmount,
            requiredAmount,
            _period
        );
    }

    function withdrawSwapped(uint256 index) public {
        UserOrder storage order = orders[msg.sender][index];
        (
            uint256 amountToWithdraw,
            uint256 finalPeriod
        ) = calculateAmountToWithdraw(order);
        order.lastPeriodWithdrawal = finalPeriod;

        require(
            order.buyToken.transfer(msg.sender, amountToWithdraw),
            "DCA: Not enough funds to withdraw"
        );

        emit SwappedWithdrawal(
            msg.sender,
            index,
            address(order.buyToken),
            amountToWithdraw
        );
    }

    function withdrawAll(uint256 index) external {
        withdrawSwapped(index);

        UserOrder storage order = orders[msg.sender][index];
        SwapOrder storage swapOrder = swapOrders[address(order.sellToken)][
            address(order.buyToken)
        ];

        uint256 finalPeriod = order.startingPeriod + order.numberOfSwaps - 1;

        if (finalPeriod > swapOrder.lastPeriod) {
            swapOrder.amountToSwap -= order.amountPerSwap;
            swapOrder.amountsToReduce[finalPeriod] -= order.amountPerSwap;
            uint256 amountToWithdraw = order.amountPerSwap *
                (finalPeriod - swapOrder.lastPeriod);
            order.lastPeriodWithdrawal = finalPeriod;

            require(
                order.sellToken.transfer(msg.sender, amountToWithdraw),
                "DCA: Not enough funds to withdraw"
            );

            emit RemainingWithdrawal(
                msg.sender,
                index,
                address(order.sellToken),
                amountToWithdraw
            );
        }
    }

    function emergencyWithdrawal(IERC20 token, address to) external onlyOwner {
        uint256 balance = token.balanceOf(address(this));
        require(token.transfer(to, balance), "DCA: Emergency transfer failed");
        emit EmergencyWithdrawal(address(token), balance, to);
    }

    // Parameter setters

    function setOracle(Oracle _newOracle) public onlyOwner {
        oracle = _newOracle;
        emit OracleSet(address(oracle));
    }

    function setBeneficiary(address _beneficiary) public onlyOwner {
        beneficiary = _beneficiary;
        emit BeneficiarySet(_beneficiary);
    }

    function setFeeNumerator(uint256 _feeNumerator) public onlyOwner {
        feeNumerator = _feeNumerator;
        emit FeeNumeratorSet(_feeNumerator);
    }

    function addAddressMapping(address _from, address _to) external onlyOwner {
        oracleAddresses[_from] = _to;
        emit OracleAddressMappingSet(_from, _to);
    }

    // Views

    function calculateAmountToWithdraw(UserOrder memory order)
        public
        view
        returns (uint256 amountToWithdraw, uint256 finalPeriod)
    {
        SwapOrder storage swapOrder = swapOrders[address(order.sellToken)][
            address(order.buyToken)
        ];
        finalPeriod = Math.min(
            swapOrder.lastPeriod,
            order.startingPeriod + order.numberOfSwaps - 1
        );
        amountToWithdraw = 0;
        for (
            uint256 period = order.lastPeriodWithdrawal + 1;
            period <= finalPeriod;
            period++
        ) {
            amountToWithdraw +=
                swapOrder.swapExchangeRates[period] *
                order.amountPerSwap;
        }
    }

    function calculateAmountWithdrawn(UserOrder memory order)
        public
        view
        returns (uint256 amountWithdrawn)
    {
        SwapOrder storage swapOrder = swapOrders[address(order.sellToken)][
            address(order.buyToken)
        ];

        amountWithdrawn = 0;
        for (
            uint256 period = order.startingPeriod;
            period <= swapOrder.lastPeriod;
            period++
        ) {
            amountWithdrawn +=
                swapOrder.swapExchangeRates[period] *
                order.amountPerSwap;
        }
    }

    function getUserOrders(address userAddress)
        external
        view
        returns (UserOrder[] memory)
    {
        return orders[userAddress];
    }

    function getUserOrdersWithExtras(address userAddress)
        external
        view
        returns (
            UserOrder[] memory,
            uint256[] memory,
            uint256[] memory,
            uint256[] memory,
            uint256
        )
    {
        UserOrder[] memory userOrders = orders[userAddress];
        uint256[] memory ordersLastPeriod = new uint256[](userOrders.length);
        uint256[] memory amountsToWithdraw = new uint256[](userOrders.length);
        uint256[] memory amountsWithdrawn = new uint256[](userOrders.length);

        for (uint256 i = 0; i < userOrders.length; i++) {
            UserOrder memory order = userOrders[i];
            (
                uint256 amountToWithdraw,
                uint256 finalPeriod
            ) = calculateAmountToWithdraw(order);
            ordersLastPeriod[i] = finalPeriod;
            amountsToWithdraw[i] = amountToWithdraw;
            amountsWithdrawn[i] = calculateAmountWithdrawn(order);
        }

        return (
            userOrders,
            ordersLastPeriod,
            amountsToWithdraw,
            amountsWithdrawn,
            getCurrentPeriod()
        );
    }

    function getOrder(address userAddress, uint256 index)
        external
        view
        returns (UserOrder memory)
    {
        return orders[userAddress][index];
    }

    function getSwapOrderAmountToReduce(
        address _sellToken,
        address _buyToken,
        uint256 _period
    ) external view returns (uint256) {
        return swapOrders[_sellToken][_buyToken].amountsToReduce[_period];
    }

    function getSwapOrderExchangeRate(
        address _sellToken,
        address _buyToken,
        uint256 _period
    ) external view returns (uint256) {
        return swapOrders[_sellToken][_buyToken].swapExchangeRates[_period];
    }

    function getOracleTokenAddress(address token)
        public
        view
        returns (address)
    {
        address mappedToken = oracleAddresses[token];
        if (mappedToken != address(0)) {
            return mappedToken;
        } else {
            return token;
        }
    }

    function getCurrentPeriod() public view returns (uint256 period) {
        period = block.number / BLOCKS_PER_DAY;
    }
}
          

/contracts/interfaces/IOracle.sol

pragma solidity ^0.8.0;

interface Oracle {
    function consult(
        address tokenIn,
        uint256 amountIn,
        address tokenOut
    ) external view returns (uint256 amountOut);
}
          

/contracts/interfaces/ISwappaRouter.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ISwappaRouterV1 {
    function getOutputAmount(
        address[] calldata path,
        address[] calldata pairs,
        bytes[] calldata extras,
        uint256 inputAmount
    ) external view returns (uint256 outputAmount);

    function swapExactInputForOutput(
        address[] calldata path,
        address[] calldata pairs,
        bytes[] calldata extras,
        uint256 inputAmount,
        uint256 minOutputAmount,
        address to,
        uint256 deadline
    ) external returns (uint256 outputAmount);

    function swapExactInputForOutputWithPrecheck(
        address[] calldata path,
        address[] calldata pairs,
        bytes[] calldata extras,
        uint256 inputAmount,
        uint256 minOutputAmount,
        address to,
        uint256 deadline
    ) external returns (uint256 outputAmount);
}
          

/contracts/interfaces/ISwapper.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

interface ISwapper {
    function swap(
        address _sellToken,
        address _buyToken,
        uint256 _inAmount,
        uint256 _outAmount,
        bytes calldata _params
    ) external;
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_dca","internalType":"contract DCA"},{"type":"address","name":"_swappaRouter","internalType":"contract ISwappaRouterV1"},{"type":"address","name":"_beneficiary","internalType":"address"}]},{"type":"event","name":"BeneficiarySet","inputs":[{"type":"address","name":"newBeneficiary","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"beneficiary","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeMezumoSwap","inputs":[{"type":"uint256","name":"period","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address[]","name":"pairs","internalType":"address[]"},{"type":"bytes[]","name":"extras","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBeneficiary","inputs":[{"type":"address","name":"_beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swap","inputs":[{"type":"address","name":"_sellToken","internalType":"address"},{"type":"address","name":"_buyToken","internalType":"address"},{"type":"uint256","name":"_inAmount","internalType":"uint256"},{"type":"uint256","name":"_outAmount","internalType":"uint256"},{"type":"bytes","name":"_params","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
              

Contract Creation Code

0x60803461007e57601f61137d38819003918201601f19168301916001600160401b038311848410176100835780849260609460405283398101031261007e57805161006f9161004d82610099565b604060208201519161005e83610099565b01519161006a83610099565b6100aa565b60405161123b90816101428239f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381160361007e57565b907f04d55a8be181fb8d75b76f2d48aa0b2ee40f47e53d6e61763eeeec46feea8a24926020926000549160018060a01b03199233848216176000556040519460018060a01b0380948193823391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060008ba3168560015416176001551683600254161760025516809160035416176003558152a156fe60806040526004361015610013575b600080fd5b6000803560e01c9081631c31f710146100a2575080632506c0181461009957806338af3eed146100905780635dbd944c14610087578063715018a61461007e5780638da5cb5b146100755763f2fde38b1461006d57600080fd5b61000e61060c565b5061000e6105b9565b5061000e610514565b5061000e61029f565b5061000e61021b565b5061000e61017c565b3461015b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015b577f04d55a8be181fb8d75b76f2d48aa0b2ee40f47e53d6e61763eeeec46feea8a2460206004356101008161015e565b73ffffffffffffffffffffffffffffffffffffffff90610124828654163314610700565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006003541617600355604051908152a1604051f35b80fd5b73ffffffffffffffffffffffffffffffffffffffff81160361000e57565b503461000e5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576004356101b88161015e565b602435906101c58261015e565b6084359167ffffffffffffffff9182841161000e573660238501121561000e57836004013592831161000e57366024848601011161000e57602461020e94019160443591610e98565b005b600091031261000e57565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602073ffffffffffffffffffffffffffffffffffffffff60035416604051908152f35b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b503461000e5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60243581811161000e576102f090369060040161026e565b909160443581811161000e5761030a90369060040161026e565b60643583811161000e576103269093929193369060040161026e565b939060405194859261037a602091606083870152610348608087018b8d6107d4565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe097888884030160408901526107d4565b8585820301606086015282815281810196828460051b83010197856000935b8685106104995750505050505050506103b892039081018352826108b9565b61041c6104076103f96103e060015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b9461040c61040786836108fa565b610942565b946104168161094f565b91610932565b92803b1561000e576104689360008094604051968795869485937f06dc1f6a00000000000000000000000000000000000000000000000000000000855230916004359160048701610a1a565b03925af1801561048c575b61047957005b8061048661020e92610898565b80610210565b610494610a5f565b610473565b919395975091939597988982820301845288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181121561000e57830190813586811161000e57803603851361000e576104fe899283928360019601610829565b9a0194019501929593918a979591999899610399565b503461000e576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015b5780547fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff82169161058b338414610700565b16825581604051917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08284a3f35b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576004356106488161015e565b73ffffffffffffffffffffffffffffffffffffffff61066c81600054163314610700565b81161561067c5761020e90610765565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b1561070757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6000549073ffffffffffffffffffffffffffffffffffffffff80911691827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b91908082526020809201929160005b8281106107f1575050505090565b90919293828060019273ffffffffffffffffffffffffffffffffffffffff883561081a8161015e565b168152019501939291016107e3565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff81116108ac57604052565b6108b4610868565b604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108ac57604052565b90156109035790565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156109035760051b0190565b3561094c8161015e565b90565b6001811061097c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b91908251928382526000905b848210610a025750601f84602094957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093116109f5575b0116010190565b60008582860101526109ee565b906020908180828501015190828601015201906109b7565b91909360a09361094c969573ffffffffffffffffffffffffffffffffffffffff93848092168652166020850152604084015216606082015281608082015201906109ab565b506040513d6000823e3d90fd5b60209067ffffffffffffffff8111610a86575b60051b0190565b610a8e610868565b610a7f565b81601f8201121561000e57803591610aaa83610a6c565b92610ab860405194856108b9565b808452602092838086019260051b82010192831161000e578301905b828210610ae2575050505090565b8380918335610af08161015e565b815201910190610ad4565b909160608284031261000e5767ffffffffffffffff91803583811161000e5784610b26918301610a93565b936020908183013585811161000e5781610b41918501610a93565b94604093848101359082821161000e570191601f81818501121561000e57833591610b6b83610a6c565b96610b78815198896108b9565b838852868089019460051b8701019582871161000e57878101945b878610610ba65750505050505050505090565b853587811161000e57820184603f8201121561000e578981013591888311610c26575b8451610bfb8c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a87011601826108b9565b8381528686858501011161000e5760008c858196898397018386013783010152815201950194610b93565b610c2e610868565b610bc9565b9081602091031261000e5751801515810361000e5790565b15610c5257565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f537761704578656375746f723a20417070726f76616c20746f2053776170706160448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152fd5b9081602091031261000e575190565b90815180825260208080930193019160005b828110610d05575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101610cf7565b93969594929190610d4b610d5a9160e0875260e0870190610ce5565b60209286820384880152610ce5565b9084820360408601528251908183528083019281808460051b8301019501936000915b848310610dc25750505050505060c09291610dbe919660608401526000608084015260a083019073ffffffffffffffffffffffffffffffffffffffff169052565b0152565b9091929394958480610dfe837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a516109ab565b9801930193019194939290610d7d565b15610e1557565b60846040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f537761704578656375746f723a205472616e7366657220746f2044434120666160448201527f696c6564000000000000000000000000000000000000000000000000000000006064820152fd5b91939290928101610ea891610afb565b939092600254610ecb9073ffffffffffffffffffffffffffffffffffffffff1690565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018890526000969095602095869593949192869283908a9060449082908e908b165af19a8b1561110f9c6110f69b610f55926111f8575b8d916111db575b50610c4b565b8a610f786103e060025473ffffffffffffffffffffffffffffffffffffffff1690565b92610fb6604051978896879586947f0862d12f0000000000000000000000000000000000000000000000000000000086524293309360048801610d2f565b03925af180156111ce575b6111b1575b5016610fea6103e060015473ffffffffffffffffffffffffffffffffffffffff1690565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff9290921660048201526000602482015290919061105b9084816044818b875af19081156111a4575b8891611187575b50610e0e565b6003546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529273ffffffffffffffffffffffffffffffffffffffff9091169087908585602481875afa94851561117a575b829561114b575b50604051978895869485938452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af192831561113e575b92611111575b5050610e0e565b565b6111309250803d10611137575b61112881836108b9565b810190610c33565b3880611108565b503d61111e565b611146610a5f565b611102565b61116c919550863d8811611173575b61116481836108b9565b810190610cd6565b93386110bd565b503d61115a565b611182610a5f565b6110b6565b61119e9150853d87116111375761112881836108b9565b38611055565b6111ac610a5f565b61104e565b6111c790843d86116111735761116481836108b9565b5038610fc6565b6111d6610a5f565b610fc1565b6111f29150863d88116111375761112881836108b9565b38610f4f565b611200610a5f565b610f4856fea2646970667358221220b91642cd7dfcd68d26b8dab0ad7ad3f363f01ae7259df05cfe98752cad38902964736f6c634300080d0033000000000000000000000000a5690741a1ca30c6d787b6f17699b7d0bd84e0b8000000000000000000000000f35ed7156babf2541e032b3bb8625210316e283200000000000000000000000076efd61146049612a78fa3e0e9bd0a8febc9dce0

Deployed ByteCode

0x60806040526004361015610013575b600080fd5b6000803560e01c9081631c31f710146100a2575080632506c0181461009957806338af3eed146100905780635dbd944c14610087578063715018a61461007e5780638da5cb5b146100755763f2fde38b1461006d57600080fd5b61000e61060c565b5061000e6105b9565b5061000e610514565b5061000e61029f565b5061000e61021b565b5061000e61017c565b3461015b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015b577f04d55a8be181fb8d75b76f2d48aa0b2ee40f47e53d6e61763eeeec46feea8a2460206004356101008161015e565b73ffffffffffffffffffffffffffffffffffffffff90610124828654163314610700565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006003541617600355604051908152a1604051f35b80fd5b73ffffffffffffffffffffffffffffffffffffffff81160361000e57565b503461000e5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576004356101b88161015e565b602435906101c58261015e565b6084359167ffffffffffffffff9182841161000e573660238501121561000e57836004013592831161000e57366024848601011161000e57602461020e94019160443591610e98565b005b600091031261000e57565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602073ffffffffffffffffffffffffffffffffffffffff60035416604051908152f35b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b503461000e5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60243581811161000e576102f090369060040161026e565b909160443581811161000e5761030a90369060040161026e565b60643583811161000e576103269093929193369060040161026e565b939060405194859261037a602091606083870152610348608087018b8d6107d4565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe097888884030160408901526107d4565b8585820301606086015282815281810196828460051b83010197856000935b8685106104995750505050505050506103b892039081018352826108b9565b61041c6104076103f96103e060015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b9461040c61040786836108fa565b610942565b946104168161094f565b91610932565b92803b1561000e576104689360008094604051968795869485937f06dc1f6a00000000000000000000000000000000000000000000000000000000855230916004359160048701610a1a565b03925af1801561048c575b61047957005b8061048661020e92610898565b80610210565b610494610a5f565b610473565b919395975091939597988982820301845288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181121561000e57830190813586811161000e57803603851361000e576104fe899283928360019601610829565b9a0194019501929593918a979591999899610399565b503461000e576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015b5780547fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff82169161058b338414610700565b16825581604051917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08284a3f35b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576004356106488161015e565b73ffffffffffffffffffffffffffffffffffffffff61066c81600054163314610700565b81161561067c5761020e90610765565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b1561070757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6000549073ffffffffffffffffffffffffffffffffffffffff80911691827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b91908082526020809201929160005b8281106107f1575050505090565b90919293828060019273ffffffffffffffffffffffffffffffffffffffff883561081a8161015e565b168152019501939291016107e3565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff81116108ac57604052565b6108b4610868565b604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108ac57604052565b90156109035790565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156109035760051b0190565b3561094c8161015e565b90565b6001811061097c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b91908251928382526000905b848210610a025750601f84602094957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093116109f5575b0116010190565b60008582860101526109ee565b906020908180828501015190828601015201906109b7565b91909360a09361094c969573ffffffffffffffffffffffffffffffffffffffff93848092168652166020850152604084015216606082015281608082015201906109ab565b506040513d6000823e3d90fd5b60209067ffffffffffffffff8111610a86575b60051b0190565b610a8e610868565b610a7f565b81601f8201121561000e57803591610aaa83610a6c565b92610ab860405194856108b9565b808452602092838086019260051b82010192831161000e578301905b828210610ae2575050505090565b8380918335610af08161015e565b815201910190610ad4565b909160608284031261000e5767ffffffffffffffff91803583811161000e5784610b26918301610a93565b936020908183013585811161000e5781610b41918501610a93565b94604093848101359082821161000e570191601f81818501121561000e57833591610b6b83610a6c565b96610b78815198896108b9565b838852868089019460051b8701019582871161000e57878101945b878610610ba65750505050505050505090565b853587811161000e57820184603f8201121561000e578981013591888311610c26575b8451610bfb8c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a87011601826108b9565b8381528686858501011161000e5760008c858196898397018386013783010152815201950194610b93565b610c2e610868565b610bc9565b9081602091031261000e5751801515810361000e5790565b15610c5257565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f537761704578656375746f723a20417070726f76616c20746f2053776170706160448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152fd5b9081602091031261000e575190565b90815180825260208080930193019160005b828110610d05575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101610cf7565b93969594929190610d4b610d5a9160e0875260e0870190610ce5565b60209286820384880152610ce5565b9084820360408601528251908183528083019281808460051b8301019501936000915b848310610dc25750505050505060c09291610dbe919660608401526000608084015260a083019073ffffffffffffffffffffffffffffffffffffffff169052565b0152565b9091929394958480610dfe837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a516109ab565b9801930193019194939290610d7d565b15610e1557565b60846040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f537761704578656375746f723a205472616e7366657220746f2044434120666160448201527f696c6564000000000000000000000000000000000000000000000000000000006064820152fd5b91939290928101610ea891610afb565b939092600254610ecb9073ffffffffffffffffffffffffffffffffffffffff1690565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018890526000969095602095869593949192869283908a9060449082908e908b165af19a8b1561110f9c6110f69b610f55926111f8575b8d916111db575b50610c4b565b8a610f786103e060025473ffffffffffffffffffffffffffffffffffffffff1690565b92610fb6604051978896879586947f0862d12f0000000000000000000000000000000000000000000000000000000086524293309360048801610d2f565b03925af180156111ce575b6111b1575b5016610fea6103e060015473ffffffffffffffffffffffffffffffffffffffff1690565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff9290921660048201526000602482015290919061105b9084816044818b875af19081156111a4575b8891611187575b50610e0e565b6003546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529273ffffffffffffffffffffffffffffffffffffffff9091169087908585602481875afa94851561117a575b829561114b575b50604051978895869485938452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af192831561113e575b92611111575b5050610e0e565b565b6111309250803d10611137575b61112881836108b9565b810190610c33565b3880611108565b503d61111e565b611146610a5f565b611102565b61116c919550863d8811611173575b61116481836108b9565b810190610cd6565b93386110bd565b503d61115a565b611182610a5f565b6110b6565b61119e9150853d87116111375761112881836108b9565b38611055565b6111ac610a5f565b61104e565b6111c790843d86116111735761116481836108b9565b5038610fc6565b6111d6610a5f565b610fc1565b6111f29150863d88116111375761112881836108b9565b38610f4f565b611200610a5f565b610f4856fea2646970667358221220b91642cd7dfcd68d26b8dab0ad7ad3f363f01ae7259df05cfe98752cad38902964736f6c634300080d0033