Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stcelo] add support for StCelo and RStCelo #46

Merged
merged 2 commits into from
Jul 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions contracts/interfaces/stCelo/IAccount.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pragma solidity 0.6.8;

interface IAccount {
function getTotalCelo() external view returns (uint256);
}
8 changes: 8 additions & 0 deletions contracts/interfaces/stCelo/IManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pragma solidity 0.6.8;

interface IManager {
function deposit() external payable;

function toStakedCelo(uint256 celoAmount) external view returns (uint256);
function toCelo(uint256 stCeloAmount) external view returns (uint256);
}
9 changes: 9 additions & 0 deletions contracts/interfaces/stCelo/IRebasedStakedCelo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pragma solidity 0.6.8;

interface IRebasedStakedCelo {
function deposit(uint256 stCeloAmount) external;
function withdraw(uint256 stCeloAmount) external;

function toStakedCelo(uint256 rstCeloAmount) external view returns (uint256);
function toRebasedStakedCelo(uint256 stCeloAmount) external view returns (uint256);
}
5 changes: 5 additions & 0 deletions contracts/interfaces/stCelo/IStakedCelo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pragma solidity 0.6.8;

interface IStakedCelo {
function totalSupply() external view returns (uint256);
}
52 changes: 52 additions & 0 deletions contracts/swappa/PairRStCelo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.6.8;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../interfaces/stCelo/IRebasedStakedCelo.sol";
import "./ISwappaPairV1.sol";

contract PairRStCelo is ISwappaPairV1 {
using SafeMath for uint;

function swap(
address input,
address output,
address to,
bytes calldata data
) external override {
(address rebaseAddr, uint8 inputType) = parseData(data);
uint inputAmount = ERC20(input).balanceOf(address(this));

if (inputType == 1) {
// rstCelo -> stCelo
uint stCeloAmount = IRebasedStakedCelo(rebaseAddr).toStakedCelo(inputAmount);
IRebasedStakedCelo(rebaseAddr).withdraw(stCeloAmount);
} else if (inputType == 2) {
// stCelo -> rstCelo
require(ERC20(input).approve(rebaseAddr, inputAmount));
IRebasedStakedCelo(rebaseAddr).deposit(inputAmount);
}
uint outputAmount = ERC20(output).balanceOf(address(this));
require(ERC20(output).transfer(to, outputAmount), "PairRStCelo: Transfer Failed");
}

function parseData(bytes memory data) private pure returns (address rebaseAddr, uint8 inputType) {
require(data.length == 21, "PairRStCelo: invalid data!");
inputType = uint8(data[20]);
assembly {
rebaseAddr := mload(add(data, 20))
}
}

function getOutputAmount(
address,
address,
uint amountIn,
bytes calldata
) external view override returns (uint amountOut) {
return amountIn;
}

receive() external payable {}
}
45 changes: 45 additions & 0 deletions contracts/swappa/PairStCelo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.6.8;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../interfaces/stCelo/IManager.sol";
import "./ISwappaPairV1.sol";

contract PairStCelo is ISwappaPairV1 {
using SafeMath for uint;

address constant CELO_ADDRESS = 0x471EcE3750Da237f93B8E339c536989b8978a438;

function swap(
address input,
address output,
address to,
bytes calldata data
) external override {
require(input == CELO_ADDRESS, "PairStCelo: Incorrect Input");
address payable managerAddr = parseData(data);
uint inputAmount = ERC20(input).balanceOf(address(this));
IManager(managerAddr).deposit{value: inputAmount}();
uint outputAmount = ERC20(output).balanceOf(address(this));
require(ERC20(output).transfer(to, outputAmount), "PairStCelo: Transfer Failed");
}

function parseData(bytes memory data) private pure returns (address payable managerAddr) {
require(data.length == 20, "PairStCelo: invalid data!");
assembly {
managerAddr := mload(add(data, 20))
}
}

function getOutputAmount(
address,
address,
uint amountIn,
bytes calldata
) external view override returns (uint amountOut) {
return amountIn;
}

receive() external payable {}
}
234 changes: 117 additions & 117 deletions contracts/swappa/PairUniswapV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,129 +14,129 @@ import "./ISwappaPairV1.sol";


contract PairUniswapV3 is ISwappaPairV1, IUniswapV3SwapCallback {
using SafeMath for uint256;
using SafeCast for uint256;
using SafeMath for uint256;
using SafeCast for uint256;

function swap(
address input,
address,
address to,
bytes calldata data
) external override {
address pairAddr = parseData(data);
uint256 inputAmount = ERC20(input).balanceOf(address(this));
IUniswapV3Pool pair = IUniswapV3Pool(pairAddr);
bool zeroForOne = pair.token0() == input;
// calling swap will trigger the uniswapV3SwapCallback
pair.swap(
to,
zeroForOne,
inputAmount.toInt256(),
zeroForOne
? TickMath.MIN_SQRT_RATIO + 1
: TickMath.MAX_SQRT_RATIO - 1,
new bytes(0)
);
}
function swap(
address input,
address,
address to,
bytes calldata data
) external override {
address pairAddr = parseData(data);
uint256 inputAmount = ERC20(input).balanceOf(address(this));
IUniswapV3Pool pair = IUniswapV3Pool(pairAddr);
bool zeroForOne = pair.token0() == input;
// calling swap will trigger the uniswapV3SwapCallback
pair.swap(
to,
zeroForOne,
inputAmount.toInt256(),
zeroForOne
? TickMath.MIN_SQRT_RATIO + 1
: TickMath.MAX_SQRT_RATIO - 1,
new bytes(0)
);
}

function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata
) external override {
ERC20 token;
uint256 amount;
if (amount0Delta > 0) {
amount = uint256(amount0Delta);
token = ERC20(IUniswapV3Pool(msg.sender).token0());
} else if (amount1Delta > 0) {
amount = uint256(amount1Delta);
token = ERC20(IUniswapV3Pool(msg.sender).token1());
}
require(
token.transfer(msg.sender, amount),
"PairUniswapV3: transfer failed!"
);
}
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata
) external override {
ERC20 token;
uint256 amount;
if (amount0Delta > 0) {
amount = uint256(amount0Delta);
token = ERC20(IUniswapV3Pool(msg.sender).token0());
} else if (amount1Delta > 0) {
amount = uint256(amount1Delta);
token = ERC20(IUniswapV3Pool(msg.sender).token1());
}
require(
token.transfer(msg.sender, amount),
"PairUniswapV3: transfer failed!"
);
}

function parseData(bytes memory data)
private
pure
returns (address pairAddr)
{
require(data.length == 20, "PairUniswapV3: invalid data!");
assembly {
pairAddr := mload(add(data, 20))
}
}
function parseData(bytes memory data)
private
pure
returns (address pairAddr)
{
require(data.length == 20, "PairUniswapV3: invalid data!");
assembly {
pairAddr := mload(add(data, 20))
}
}

function getOutputAmount(
address input,
address,
uint256 amountIn,
bytes calldata data
) external view override returns (uint256 amountOut) {
address pairAddr = parseData(data);
IUniswapV3Pool pair = IUniswapV3Pool(pairAddr);
bool zeroForOne = pair.token0() == input;
// amount0, amount1 are delta of the pair reserves
(int256 amount0, int256 amount1) = Quoter.quote(
pair,
zeroForOne,
amountIn.toInt256(),
zeroForOne
? TickMath.MIN_SQRT_RATIO + 1
: TickMath.MAX_SQRT_RATIO - 1
);
return uint256(-(zeroForOne ? amount1 : amount0));
}
function getOutputAmount(
address input,
address,
uint256 amountIn,
bytes calldata data
) external view override returns (uint256 amountOut) {
address pairAddr = parseData(data);
IUniswapV3Pool pair = IUniswapV3Pool(pairAddr);
bool zeroForOne = pair.token0() == input;
// amount0, amount1 are delta of the pair reserves
(int256 amount0, int256 amount1) = Quoter.quote(
pair,
zeroForOne,
amountIn.toInt256(),
zeroForOne
? TickMath.MIN_SQRT_RATIO + 1
: TickMath.MAX_SQRT_RATIO - 1
);
return uint256(-(zeroForOne ? amount1 : amount0));
}

function getInputAmount(
address input,
address,
uint256 amountOut,
bytes calldata data
) external view returns (uint256 amountIn) {
address pairAddr = parseData(data);
IUniswapV3Pool pair = IUniswapV3Pool(pairAddr);
bool zeroForOne = pair.token0() == input;
// amount0, amount1 are delta of the pair reserves
(int256 amount0, int256 amount1) = Quoter.quote(
pair,
zeroForOne,
-amountOut.toInt256(),
zeroForOne
? TickMath.MIN_SQRT_RATIO + 1
: TickMath.MAX_SQRT_RATIO - 1
);
return uint256(zeroForOne ? amount0 : amount1);
}
function getInputAmount(
address input,
address,
uint256 amountOut,
bytes calldata data
) external view returns (uint256 amountIn) {
address pairAddr = parseData(data);
IUniswapV3Pool pair = IUniswapV3Pool(pairAddr);
bool zeroForOne = pair.token0() == input;
// amount0, amount1 are delta of the pair reserves
(int256 amount0, int256 amount1) = Quoter.quote(
pair,
zeroForOne,
-amountOut.toInt256(),
zeroForOne
? TickMath.MIN_SQRT_RATIO + 1
: TickMath.MAX_SQRT_RATIO - 1
);
return uint256(zeroForOne ? amount0 : amount1);
}

function getSpotTicks(IUniswapV3Pool pool)
public
view
returns (
uint160 sqrtPriceX96,
int24 tick,
TickLens.PopulatedTick[] memory populatedTicksTwiceAbove,
TickLens.PopulatedTick[] memory populatedTicksAbove,
TickLens.PopulatedTick[] memory populatedTicksSpot,
TickLens.PopulatedTick[] memory populatedTicksBelow,
TickLens.PopulatedTick[] memory populatedTicksTwiceBelow
)
{
return TickLens.getSpotTicks(pool);
}
function getSpotTicks(IUniswapV3Pool pool)
public
view
returns (
uint160 sqrtPriceX96,
int24 tick,
TickLens.PopulatedTick[] memory populatedTicksTwiceAbove,
TickLens.PopulatedTick[] memory populatedTicksAbove,
TickLens.PopulatedTick[] memory populatedTicksSpot,
TickLens.PopulatedTick[] memory populatedTicksBelow,
TickLens.PopulatedTick[] memory populatedTicksTwiceBelow
)
{
return TickLens.getSpotTicks(pool);
}

function getPopulatedTicksInWord(IUniswapV3Pool pool, int16 tickBitmapIndex)
public
view
returns (TickLens.PopulatedTick[] memory populatedTicks)
{
return TickLens.getPopulatedTicksInWord(pool, tickBitmapIndex);
}
function getPopulatedTicksInWord(IUniswapV3Pool pool, int16 tickBitmapIndex)
public
view
returns (TickLens.PopulatedTick[] memory populatedTicks)
{
return TickLens.getPopulatedTicksInWord(pool, tickBitmapIndex);
}

function recoverERC20(ERC20 token) public {
token.transfer(msg.sender, token.balanceOf(address(this)));
}
function recoverERC20(ERC20 token) public {
token.transfer(msg.sender, token.balanceOf(address(this)));
}
}
Loading