-
Notifications
You must be signed in to change notification settings - Fork 21
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
Showing
1 changed file
with
117 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
import "OpenZeppelin/[email protected]/contracts/token/ERC20/IERC20.sol"; | ||
import "OpenZeppelin/[email protected]/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
import "OpenZeppelin/[email protected]/contracts/access/Ownable.sol"; | ||
|
||
import "./RequestManager.sol"; | ||
|
||
contract FeeSub is Ownable { | ||
using SafeERC20 for IERC20; | ||
|
||
RequestManager public requestManager; | ||
mapping(address token => uint256) public minimumAmounts; | ||
mapping(bytes32 requestId => address sender) public senders; | ||
|
||
constructor(address _requestManager) { | ||
requestManager = RequestManager(_requestManager); | ||
} | ||
|
||
function createRequest( | ||
uint256 targetChainId, | ||
address sourceTokenAddress, | ||
address targetTokenAddress, | ||
address targetAddress, | ||
uint256 amount, | ||
uint256 validityPeriod | ||
) external returns (bytes32) { | ||
require( | ||
minimumAmounts[sourceTokenAddress] > 0, | ||
"Token not to be subsidized" | ||
); | ||
require( | ||
amount >= minimumAmounts[sourceTokenAddress], | ||
"Transfer amount too small to be subsidized" | ||
); | ||
|
||
require( | ||
IERC20(sourceTokenAddress).allowance(msg.sender, address(this)) >= | ||
amount, | ||
"Insufficient allowance" | ||
); | ||
|
||
IERC20(sourceTokenAddress).safeTransferFrom( | ||
msg.sender, | ||
address(this), | ||
amount | ||
); | ||
|
||
bytes32 requestId = requestManager.createRequest( | ||
targetChainId, | ||
sourceTokenAddress, | ||
targetTokenAddress, | ||
targetAddress, | ||
amount, | ||
validityPeriod | ||
); | ||
senders[requestId] = msg.sender; | ||
|
||
return requestId; | ||
} | ||
|
||
function withdrawExpiredRequest(bytes32 requestId) external { | ||
( | ||
address sender, | ||
address sourceTokenAddress, | ||
, | ||
uint256 amount, | ||
, | ||
, | ||
, | ||
, | ||
uint96 withdrawClaimId, | ||
, | ||
|
||
) = requestManager.requests(requestId); | ||
require( | ||
sender == address(this), | ||
"Request was not created by this contract" | ||
); | ||
require( | ||
senders[requestId] != address(0), | ||
"Already refunded to the sender" | ||
); | ||
|
||
if (withdrawClaimId == 0) { | ||
// This will fail if the funds do not belong to the original sender (yet) | ||
requestManager.withdrawExpiredRequest(requestId); | ||
} else { | ||
// Make sure that funds were withdrawn by calling withdrawExpiredRequest() | ||
require( | ||
withdrawClaimId == type(uint96).max, | ||
"Request was withdrawn by another address" | ||
); | ||
} | ||
|
||
address recipient = senders[requestId]; | ||
senders[requestId] = address(0); | ||
|
||
IERC20 token = IERC20(sourceTokenAddress); | ||
token.safeTransfer(recipient, amount); | ||
} | ||
|
||
function setMinimumAmount( | ||
address tokenAddress, | ||
uint256 amount | ||
) external onlyOwner { | ||
if (amount > 0 && minimumAmounts[tokenAddress] == 0) { | ||
IERC20(tokenAddress).approve( | ||
address(requestManager), | ||
type(uint256).max | ||
); | ||
} else if (amount == 0 && minimumAmounts[tokenAddress] != 0) { | ||
IERC20(tokenAddress).approve(address(requestManager), 0); | ||
} | ||
minimumAmounts[tokenAddress] = amount; | ||
} | ||
} |