Skip to content

Commit

Permalink
feat: New UniswapV2LockstakeCallee (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
valiafetisov authored Aug 14, 2024
1 parent 3b080ec commit bc4b4eb
Show file tree
Hide file tree
Showing 14 changed files with 603 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
[submodule "lib/dss-crop-join"]
path = lib/dss-crop-join
url = https://github.com/makerdao/dss-crop-join
[submodule "lib/lockstake"]
path = lib/lockstake
url = https://github.com/makerdao/lockstake
1 change: 1 addition & 0 deletions lib/lockstake
Submodule lockstake added at 735e1e
4 changes: 2 additions & 2 deletions scripts/test.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env bash

if [[ $# -eq 0 ]] ; then
forge test --use solc:0.6.12 --fork-url "$ETH_RPC_URL"
forge test --fork-url "$ETH_RPC_URL"
else
forge test --use solc:0.6.12 --fork-url "$ETH_RPC_URL" -vvv --match-test ${1}
forge test --fork-url "$ETH_RPC_URL" -vvv --match-test ${1}
fi

2 changes: 1 addition & 1 deletion src/OasisDexCallee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;
pragma solidity 0.6.12;

interface VatLike {
function hope(address) external;
Expand Down
2 changes: 1 addition & 1 deletion src/OneInchCallee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

interface GemJoinLike {
Expand Down
2 changes: 1 addition & 1 deletion src/PSMCallee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

interface GemJoinLike {
Expand Down
2 changes: 1 addition & 1 deletion src/UniswapV2Callee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;
pragma solidity 0.6.12;

interface VatLike {
function hope(address) external;
Expand Down
134 changes: 134 additions & 0 deletions src/UniswapV2LockstakeCallee.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2020 Maker Ecosystem Growth Holdings, INC.
// Copyright (C) 2024 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity ^0.8.21;

interface TokenLike {
function approve(address, uint256) external;
function transfer(address, uint256) external;
function balanceOf(address) external view returns (uint256);
}

interface UniswapV2Router02Like {
function swapExactTokensForTokens(uint256, uint256, address[] calldata, address, uint256) external returns (uint256[] memory);
}

interface DaiJoinLike {
function dai() external view returns (address);
function join(address, uint256) external;
}

interface NstJoinLike {
function nst() external view returns (address);
function join(address, uint256) external;
}

interface MkrNgt {
function mkr() external view returns (address);
function ngt() external view returns (address);
function rate() external view returns (uint256);
function mkrToNgt(address, uint256) external;
}

contract UniswapV2LockstakeCallee {
UniswapV2Router02Like public immutable uniRouter02;
DaiJoinLike public immutable daiJoin;
TokenLike public immutable dai;
NstJoinLike public immutable nstJoin;
TokenLike public immutable nst;
MkrNgt public immutable mkrNgt;
TokenLike public immutable mkr;
TokenLike public immutable ngt;
uint256 public constant RAY = 10 ** 27;

constructor(address uniRouter02_, address daiJoin_, address nstJoin_, address mkrNgt_) {
uniRouter02 = UniswapV2Router02Like(uniRouter02_);

daiJoin = DaiJoinLike(daiJoin_);
dai = TokenLike(daiJoin.dai());
dai.approve(daiJoin_, type(uint256).max);

nstJoin = NstJoinLike(nstJoin_);
nst = TokenLike(nstJoin.nst());
nst.approve(nstJoin_, type(uint256).max);

mkrNgt = MkrNgt(mkrNgt_);
mkr = TokenLike(mkrNgt.mkr());
ngt = TokenLike(mkrNgt.ngt());
}

function divup(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x != 0 ? ((x - 1) / y) + 1 : 0;
}

function clipperCall(
address sender, // Clipper Caller and DAI/NST delivery address
uint256 dstAmt, // DAI/NST amount to payback [rad]
uint256 gemAmt, // Gem amount received [wad]
bytes calldata data // Extra data needed
) external {
(
address to, // Address to send remaining DAI/NST to
uint256 minProfit, // Minimum profit in DAI/NST to make [wad]
address[] memory path // Uniswap pool path
) = abi.decode(data, (address, uint256, address[]));

// Support NGT
TokenLike gem = mkr;
if (path[0] == address(ngt)) {
gem = ngt;
mkr.approve(address(mkrNgt), gemAmt);
mkrNgt.mkrToNgt(address(this), gemAmt);
gemAmt = gemAmt * mkrNgt.rate();
}

// Approve uniRouter02 to take gem
gem.approve(address(uniRouter02), gemAmt);

// Calculate amount of tokens to Join (as erc20 WAD value)
uint256 amtToJoin = divup(dstAmt, RAY);

// Exchange tokens based on the path (checking the profit is achieved)
uniRouter02.swapExactTokensForTokens(
gemAmt,
amtToJoin + minProfit,
path,
address(this),
block.timestamp
);

// Although Uniswap will accept all gems, this check is a sanity check, just in case
if (gem.balanceOf(address(this)) > 0) {
// Transfer any lingering gem to specified address
gem.transfer(to, gem.balanceOf(address(this)));
}

// Determine destination token
TokenLike dst = TokenLike(path[path.length - 1]);

// Convert tokens bought to internal vat value of the msg.sender of Clipper.take
if (address(dst) == address(dai)) {
daiJoin.join(sender, amtToJoin);
} else if (address(dst) == address(nst)) {
nstJoin.join(sender, amtToJoin);
}

// Transfer remaining tokens to specified address
dst.transfer(to, dst.balanceOf(address(this)));
}
}

2 changes: 1 addition & 1 deletion src/UniswapV2LpTokenCallee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;
pragma solidity 0.6.12;

interface VatLike {
function hope(address) external;
Expand Down
2 changes: 1 addition & 1 deletion src/UniswapV3Callee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

interface GemJoinLike {
Expand Down
2 changes: 1 addition & 1 deletion src/UniswapV3SplitRouteCallee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

interface GemJoinLike {
Expand Down
2 changes: 1 addition & 1 deletion src/WstETHCurveUniv3Callee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

interface GemJoinLike {
Expand Down
Loading

0 comments on commit bc4b4eb

Please sign in to comment.