-
Notifications
You must be signed in to change notification settings - Fork 4
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
1 parent
e489ea3
commit 2cb93b3
Showing
8 changed files
with
169 additions
and
1 deletion.
There are no files selected for viewing
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
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
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,29 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
pragma solidity 0.8.14; | ||
|
||
import "forge-std/Script.sol"; | ||
import { DeploySetting } from "./libraries/DeploySetting.sol"; | ||
import { LibDeploy } from "./libraries/LibDeploy.sol"; | ||
|
||
contract DeployCyberRelayer is Script, DeploySetting { | ||
function run() external { | ||
_setDeployParams(); | ||
vm.startBroadcast(); | ||
|
||
if ( | ||
block.chainid == DeploySetting.CYBER_TESTNET || | ||
block.chainid == DeploySetting.CYBER | ||
) { | ||
LibDeploy.deployCyberRelayer( | ||
vm, | ||
deployParams.deployerContract, | ||
deployParams.protocolOwner, | ||
deployParams.backendSigner | ||
); | ||
} else { | ||
revert("UNSUPPORTED_CHAIN"); | ||
} | ||
vm.stopBroadcast(); | ||
} | ||
} |
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
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,106 @@ | ||
pragma solidity ^0.8.0; | ||
|
||
import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; | ||
import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/AccessControlEnumerable.sol"; | ||
|
||
contract CyberRelayer is AccessControlEnumerable { | ||
using SafeERC20 for IERC20; | ||
|
||
/*////////////////////////////////////////////////////////////// | ||
EVENT | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
event Relayed(bytes32 relayId); | ||
|
||
/*////////////////////////////////////////////////////////////// | ||
STORAGE | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE"); | ||
mapping(bytes32 => bool) public relayed; | ||
|
||
/*////////////////////////////////////////////////////////////// | ||
CONSTRUCTOR | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
constructor(address owner) { | ||
_grantRole(DEFAULT_ADMIN_ROLE, owner); | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////// | ||
ONLY RELAYER | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
function relay( | ||
bytes32 relayId, | ||
address to, | ||
uint256 value, | ||
bytes calldata data | ||
) external payable onlyRole(RELAYER_ROLE) { | ||
require(msg.value == value, "INVALID_VALUE"); | ||
require(!relayed[relayId], "ALREADY_RELAYED"); | ||
relayed[relayId] = true; | ||
bool success; | ||
bytes memory ret; | ||
|
||
if (data.length == 0) { | ||
// explicitly call transfer to limit gas to 2300 | ||
payable(to).transfer(value); | ||
} else { | ||
(success, ret) = _call(to, value, data); | ||
if (!success) { | ||
assembly { | ||
revert(add(ret, 32), mload(ret)) | ||
} | ||
} | ||
} | ||
|
||
emit Relayed(relayId); | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////// | ||
ONLY ADMIN | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
function withdraw( | ||
address to, | ||
address token, | ||
uint256 amount | ||
) external onlyRole(DEFAULT_ADMIN_ROLE) { | ||
if (token == address(0)) { | ||
(bool success, ) = to.call{ value: amount }(""); | ||
require(success, "WITHDRAW_FAILED"); | ||
} else { | ||
IERC20(token).safeTransfer(to, amount); | ||
} | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////// | ||
PRIVATE | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
function _call( | ||
address to, | ||
uint256 value, | ||
bytes memory data | ||
) private returns (bool success, bytes memory returnData) { | ||
assembly { | ||
success := call( | ||
gas(), | ||
to, | ||
value, | ||
add(data, 0x20), | ||
mload(data), | ||
0, | ||
0 | ||
) | ||
let len := returndatasize() | ||
let ptr := mload(0x40) | ||
mstore(0x40, add(ptr, add(len, 0x20))) | ||
mstore(ptr, len) | ||
returndatacopy(add(ptr, 0x20), 0, len) | ||
returnData := ptr | ||
} | ||
} | ||
} |