Skip to content
Open
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
67 changes: 67 additions & 0 deletions contracts/utility/SpritzBridgeReceiver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: UNLICENSED

pragma solidity ^0.8.7;
Copy link
Collaborator

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


import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
Copy link
Collaborator

Choose a reason for hiding this comment

The 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;
Copy link
Collaborator

Choose a reason for hiding this comment

The 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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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,
Copy link
Collaborator

Choose a reason for hiding this comment

The 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);
Copy link
Collaborator

@ohitslaurence ohitslaurence Nov 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(bool success, ) = _target.call{ value: msg.value }(swapData);
if (!success) {
assembly {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}

IERC20(toToken).transfer(_circleReceiving, IERC20(toToken).balanceOf(address(this)));
Copy link
Collaborator

Choose a reason for hiding this comment

The 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)));
Copy link
Collaborator

Choose a reason for hiding this comment

The 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 }("");
}
}
19 changes: 19 additions & 0 deletions src/abi/SpritzBridgeReceiver.json
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)"
]
1 change: 1 addition & 0 deletions tasks/deploy/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "./protocol/contractFactory";
import "./smartPay";
import "./spritzBridge";
import "./spritzBridgeReceiver";
import "./spritzBridgeV2";
import "./spritzPay";
import "./spritzPayV2";
Expand Down
19 changes: 19 additions & 0 deletions tasks/deploy/spritzBridgeReceiver.ts
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,
});
});