-
Notifications
You must be signed in to change notification settings - Fork 0
SpritzBridgeReceiver #20
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
|
||
pragma solidity ^0.8.7; | ||
|
||
import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. try openzeppelin-5, its aliased to the latest openzeppelin contracts which are better |
||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
|
||
/** | ||
* @title SpritzBridgeReceiver | ||
* @author Spritz Finance | ||
* @notice A utility contract for handling bridged funds | ||
*/ | ||
contract SpritzBridgeReceiver is AccessControlEnumerable { | ||
using SafeERC20 for IERC20; | ||
|
||
// @dev Bot which has permission to call the bridge function | ||
bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); | ||
|
||
// @dev Address of paraswap | ||
address internal _target = 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make these all contstants |
||
// @dev Address of paraswap allowance target | ||
address internal _allowanceTarget = 0x216B4B4Ba9F3e719726886d34a177484278Bfcae; | ||
// @dev Circle receiving address | ||
address internal _circleReceiving = 0xb0E2D41a14494717f42Ffc6327F9D250b0ad32a8; | ||
|
||
constructor(address bridgeRole) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can make the constructor payable to save some gas |
||
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender); | ||
_setupRole(BRIDGE_ROLE, msg.sender); | ||
_setupRole(BRIDGE_ROLE, bridgeRole); | ||
} | ||
|
||
/** | ||
* @dev Bridge deposited tokens via Jumper | ||
* @param fromToken Token to swap | ||
* @param amount How much to swap | ||
* @param toToken Target token | ||
* @param swapData Data for paraswap call | ||
*/ | ||
function swapToken( | ||
address fromToken, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can cast this to IERC20 then you wont need to do it everywhere else |
||
uint amount, | ||
address toToken, | ||
bytes calldata swapData | ||
) external payable onlyRole(BRIDGE_ROLE) { | ||
require(amount <= IERC20(fromToken).balanceOf(address(this)), "Amount exceeds balance"); | ||
IERC20(fromToken).safeApprove(_allowanceTarget, amount); | ||
_target.call{ value: msg.value }(swapData); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (bool success, ) = _target.call{ value: msg.value }(swapData); |
||
IERC20(toToken).transfer(_circleReceiving, IERC20(toToken).balanceOf(address(this))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. safeTransfer |
||
} | ||
|
||
/** | ||
* @dev Withdraw deposited tokens to the given address | ||
* @param token Token to withdraw | ||
* @param to Target address | ||
*/ | ||
function sweep(IERC20 token, address to) external onlyRole(BRIDGE_ROLE) { | ||
token.transfer(to, token.balanceOf(address(this))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. safeTransfer, just because it can cause issues in some cases where the token doesn't conform properly |
||
} | ||
|
||
/** | ||
* @dev Withdraw ETH to the given address | ||
* @param to Target address | ||
*/ | ||
function nativeSweep(address to) external onlyRole(BRIDGE_ROLE) { | ||
to.call{ value: address(this).balance }(""); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[ | ||
"constructor(address)", | ||
"event RoleAdminChanged(bytes32 indexed,bytes32 indexed,bytes32 indexed)", | ||
"event RoleGranted(bytes32 indexed,address indexed,address indexed)", | ||
"event RoleRevoked(bytes32 indexed,address indexed,address indexed)", | ||
"function BRIDGE_ROLE() view returns (bytes32)", | ||
"function DEFAULT_ADMIN_ROLE() view returns (bytes32)", | ||
"function getRoleAdmin(bytes32) view returns (bytes32)", | ||
"function getRoleMember(bytes32,uint256) view returns (address)", | ||
"function getRoleMemberCount(bytes32) view returns (uint256)", | ||
"function grantRole(bytes32,address)", | ||
"function hasRole(bytes32,address) view returns (bool)", | ||
"function nativeSweep(address)", | ||
"function renounceRole(bytes32,address)", | ||
"function revokeRole(bytes32,address)", | ||
"function supportsInterface(bytes4) view returns (bool)", | ||
"function swapToken(address,uint256,address,bytes) payable", | ||
"function sweep(address,address)" | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { task } from "hardhat/config"; | ||
import type { TaskArguments } from "hardhat/types"; | ||
|
||
const BRIDGE_BOT = "0xAAAF0666A916bdf97710A8E44e42BA250490e5b8"; | ||
|
||
task("deploy:SpritzBridgeReceiver").setAction(async function (_taskArguments: TaskArguments, hre) { | ||
const bridgeFactory = await hre.ethers.getContractFactory("SpritzBridgeReceiver"); | ||
console.log("Deploying"); | ||
const args: [string] = [BRIDGE_BOT]; | ||
const bridge = await bridgeFactory.deploy(...args); | ||
await bridge.deployTransaction.wait(10); | ||
console.log(`Deployed to ${bridge.address} with tx: ${bridge.deployTransaction.hash}`); | ||
await hre.run(`verify:verify`, { | ||
address: bridge.address, | ||
contract: "contracts/utility/SpritzBridgeReceiver.sol:SpritzBridgeReceiver", | ||
constructorArguments: args, | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use 0.8.21 now