-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Yashika Goyal
committed
Dec 21, 2023
1 parent
d8591c2
commit e4905af
Showing
7 changed files
with
484 additions
and
0 deletions.
There are no files selected for viewing
6 changes: 6 additions & 0 deletions
6
contracts/intent-adapters/liquid-staking/Swell/Interfaces.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
136
contracts/intent-adapters/liquid-staking/Swell/SwellStakeEth.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import "./SwellStakeEth.deploy"; |
Oops, something went wrong.