Skip to content

Commit

Permalink
feat: added swell adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
Yashika Goyal committed Dec 21, 2023
1 parent d8591c2 commit e4905af
Show file tree
Hide file tree
Showing 7 changed files with 484 additions and 0 deletions.
6 changes: 6 additions & 0 deletions contracts/intent-adapters/liquid-staking/Swell/Interfaces.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

interface ISwellPool {
function deposit() external payable;
}
136 changes: 136 additions & 0 deletions contracts/intent-adapters/liquid-staking/Swell/SwellStakeEth.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

import {ISwellPool} from "./Interfaces.sol";
import {RouterIntentAdapter, Errors} from "router-intents/contracts/RouterIntentAdapter.sol";
import {NitroMessageHandler} from "router-intents/contracts/NitroMessageHandler.sol";
import {IERC20, SafeERC20} from "../../../utils/SafeERC20.sol";

/**
* @title SwellStakeEth
* @author Yashika Goyal
* @notice Staking ETH to receive swETH on Swell.
* @notice This contract is only for Ethereum chain.
*/
contract SwellStakeEth is RouterIntentAdapter, NitroMessageHandler {
using SafeERC20 for IERC20;

address private immutable _swEth;

event SwellStakeEthDest(
address _recipient,
uint256 _amount,
uint256 _receivedSwEth
);

constructor(
address __native,
address __wnative,
address __owner,
address __assetForwarder,
address __dexspan,
address __swEth
)
RouterIntentAdapter(__native, __wnative, __owner)
NitroMessageHandler(__assetForwarder, __dexspan)
{
_swEth = __swEth;
}

function swEth() public view returns (address) {
return _swEth;
}

function name() public pure override returns (string memory) {
return "SwellStakeEth";
}

/**
* @inheritdoc RouterIntentAdapter
*/
function execute(
address,
address,
bytes calldata data
) external payable override returns (address[] memory tokens) {
(address _recipient, uint256 _amount) = parseInputs(data);

// If the adapter is called using `call` and not `delegatecall`
if (address(this) == self()) {
require(
msg.value == _amount,
Errors.INSUFFICIENT_NATIVE_FUNDS_PASSED
);
}

bytes memory logData;

(tokens, logData) = _stake(_recipient, _amount);

emit ExecutionEvent(name(), logData);
return tokens;
}

/**
* @inheritdoc NitroMessageHandler
*/
function handleMessage(
address tokenSent,
uint256 amount,
bytes memory instruction
) external override onlyNitro nonReentrant {
address recipient = abi.decode(instruction, (address));

if (tokenSent != native()) {
withdrawTokens(tokenSent, recipient, amount);
emit OperationFailedRefundEvent(tokenSent, recipient, amount);
return;
}

try ISwellPool(_swEth).deposit{value: amount}() {
uint256 receivedSwEth = withdrawTokens(
_swEth,
recipient,
type(uint256).max
);

emit SwellStakeEthDest(recipient, amount, receivedSwEth);
} catch {
withdrawTokens(tokenSent, recipient, amount);
emit OperationFailedRefundEvent(tokenSent, recipient, amount);
}
}

//////////////////////////// ACTION LOGIC ////////////////////////////

function _stake(
address _recipient,
uint256 _amount
) internal returns (address[] memory tokens, bytes memory logData) {
ISwellPool(_swEth).deposit{value: _amount}();
uint256 receivedSwEth = withdrawTokens(
_swEth,
_recipient,
type(uint256).max
);

tokens = new address[](2);
tokens[0] = native();
tokens[1] = swEth();

logData = abi.encode(_recipient, _amount, receivedSwEth);
}

/**
* @dev function to parse input data.
* @param data input data.
*/
function parseInputs(
bytes memory data
) public pure returns (address, uint256) {
return abi.decode(data, (address, uint256));
}

// solhint-disable-next-line no-empty-blocks
receive() external payable {}
}
1 change: 1 addition & 0 deletions tasks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "./ankr";
import "./origin";
import "./benqi";
import "./rocketPool";
import "./swell";
import "./dexspan";
import "./erc20";
import "./uniswapV3";
Expand Down
102 changes: 102 additions & 0 deletions tasks/swell/SwellStakeEth.deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { HardhatRuntimeEnvironment, TaskArguments } from "hardhat/types";
import {
ASSET_FORWARDER,
CONTRACT_NAME,
DEFAULT_ENV,
DEFAULT_OWNER,
DEFAULT_REFUND_ADDRESS,
DEPLOY_SWELL_STAKE_ETH_ADAPTER,
DEXSPAN,
NATIVE,
VERIFY_SWELL_STAKE_ETH_ADAPTER,
WNATIVE,
} from "../constants";
import { task } from "hardhat/config";
import {
IDeployment,
getDeployments,
recordAllDeployments,
saveDeployments,
} from "../utils";
import { SWELL_SW_ETH } from "./constants";

const contractName: string = CONTRACT_NAME.SwellStakeEth;

task(DEPLOY_SWELL_STAKE_ETH_ADAPTER)
.addFlag("verify", "pass true to verify the contract")
.setAction(async function (
_taskArguments: TaskArguments,
_hre: HardhatRuntimeEnvironment
) {
let env = process.env.ENV;
if (!env) env = DEFAULT_ENV;

let defaultRefundAddress = process.env.DEFAULT_REFUND_ADDRESS;
if (!defaultRefundAddress) defaultRefundAddress = DEFAULT_REFUND_ADDRESS;

let owner = process.env.OWNER;
if (!owner) owner = DEFAULT_OWNER;

const network = await _hre.getChainId();

console.log(`Deploying ${contractName} Contract on chainId ${network}....`);
const factory = await _hre.ethers.getContractFactory(contractName);
const instance = await factory.deploy(
NATIVE,
WNATIVE[env][network],
owner,
ASSET_FORWARDER[env][network],
DEXSPAN[env][network],
SWELL_SW_ETH[network],
);
await instance.deployed();

const deployment: IDeployment = await recordAllDeployments(
env,
network,
contractName,
instance.address
);

await saveDeployments(deployment);

console.log(`${contractName} contract deployed at`, instance.address);

if (_taskArguments.verify === true) {
await _hre.run(VERIFY_SWELL_STAKE_ETH_ADAPTER);
}
});

task(VERIFY_SWELL_STAKE_ETH_ADAPTER).setAction(async function (
_taskArguments: TaskArguments,
_hre: HardhatRuntimeEnvironment
) {
let env = process.env.ENV;
if (!env) env = DEFAULT_ENV;

let defaultRefundAddress = process.env.DEFAULT_REFUND_ADDRESS;
if (!defaultRefundAddress) defaultRefundAddress = DEFAULT_REFUND_ADDRESS;

let owner = process.env.OWNER;
if (!owner) owner = DEFAULT_OWNER;

const network = await _hre.getChainId();

const deployments: IDeployment = getDeployments();
const address = deployments[env][network][contractName];

console.log(`Verifying ${contractName} Contract....`);
await _hre.run("verify:verify", {
address,
constructorArguments: [
NATIVE,
WNATIVE[env][network],
owner,
ASSET_FORWARDER[env][network],
DEXSPAN[env][network],
SWELL_SW_ETH[network],
],
});

console.log(`Verified ${contractName} contract address `, address);
});
4 changes: 4 additions & 0 deletions tasks/swell/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const SWELL_SW_ETH: { [chainId: string]: string } = {
"1": "0xf951E335afb289353dc249e82926178EaC7DEd78",
"5": "0x8bb383A752Ff3c1d510625C6F536E3332327068F",
};
1 change: 1 addition & 0 deletions tasks/swell/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "./SwellStakeEth.deploy";
Loading

0 comments on commit e4905af

Please sign in to comment.