Skip to content

Commit

Permalink
feat: add ron transfer libs
Browse files Browse the repository at this point in the history
  • Loading branch information
huyhuynh3103 committed Dec 30, 2023
1 parent 3dbf045 commit 7e3786b
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/interfaces/IWRON.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IWRON {
function deposit() external payable;

function transfer(address to, uint256 value) external returns (bool);

function transferFrom(address src, address dst, uint256 wad) external returns (bool);

function withdraw(uint256) external;

function balanceOf(address) external view returns (uint256);

function approve(address guy, uint256 wad) external returns (bool);
}
10 changes: 10 additions & 0 deletions src/interfaces/IWRONHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IWRONHelper {
function WRON() external view returns (address);

function withdraw(uint256 _amount) external;

function withdrawTo(address payable _to, uint256 _amount) external;
}
37 changes: 37 additions & 0 deletions src/transfers/LibRONTransfer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Strings.sol";

/**
* @title RONTransferHelper
*/
library LibRONTransfer {
/**
* @dev Transfers RON and wraps result for the method caller to a recipient.
*/
function safeTransfer(address payable _to, uint256 _value) internal {
bool _success = send(_to, _value);

if (!_success) {
revert(
string(
abi.encodePacked(
"RONTransferHelper: could not transfer RON to ",
Strings.toHexString(uint160(address(_to)), 20),
" value ",
Strings.toHexString(_value)
)
)
);
}
}

/**
* @dev Returns whether the call was success.
* Note: this function should use with the `ReentrancyGuard`.
*/
function send(address payable _to, uint256 _value) internal returns (bool _success) {
(_success,) = _to.call{ value: _value }(new bytes(0));
}
}
122 changes: 122 additions & 0 deletions src/transfers/LibRONTransferExtended.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "../interfaces/IWRON.sol";
import "../interfaces/IWRONHelper.sol";
import "./LibRONTransfer.sol";
import "./LibTokenTransferFrom.sol";
import "./LibTokenTransfer.sol";

library LibRONTransferExtended {
/**
* @dev Safely unwraps tokens if it is WRON token and transfers them to a specified recipient.
* @param _wron Address of the WRON contract.
* @param _token Address of the ERC20 token to unwrap and transfer.
* @param _to Address of the recipient to transfer the tokens to.
* @param _amount Amount of tokens to transfer.
*
* Note: This function may cause a revert if the consumer contract is a proxy, consider using the method
* `safeUnwrapTokenAndTransferWithHelper` instead.
*/
function safeUnwrapTokenAndTransfer(IWRON _wron, address _token, address payable _to, uint256 _amount) internal {
if (_token == address(_wron)) {
// Check whether the recipient receives RON
if (LibRONTransfer.send(_to, 0)) {
_wron.withdraw(_amount);
LibRONTransfer.safeTransfer(_to, _amount);
return;
}
}

LibTokenTransfer.safeTransfer(_token, _to, _amount);
}

/**
* @dev See `safeUnwrapTokenAndTransfer`.
*
* Requirements:
* - The consumer contract must approve the contract `_wronHelper`.
*
* Note: This function supports the use of a proxy contract by using the WRONHelper contract to unwrap WRON and
* transfer RON.
*/
function safeUnwrapTokenAndTransferWithHelper(
IWRON _wron,
IWRONHelper _wronHelper,
address _token,
address payable _to,
uint256 _amount
) internal {
if (_token == address(_wron)) {
// Check whether the recipient receives RON
if (LibRONTransfer.send(_to, 0)) {
_wron.approve(address(_wronHelper), _amount);
_wronHelper.withdrawTo(_to, _amount);
return;
}
}

LibTokenTransfer.safeTransfer(_token, _to, _amount);
}

/**
* @dev Safely unwraps tokens if it is WRON token from specified sender, and transfers them to a specified recipient.
* @param _wron Address of the WRON contract.
* @param _token Address of the ERC20 token to unwrap and transfer.
* @param _from Address of the sender on whose behalf the tokens will be unwrapped and transferred.
* @param _to Address of the recipient to transfer the tokens to.
* @param _amount Amount of tokens to transfer.
*
* Note: This function may cause a revert if the consumer contract is a proxy, consider using the method
* `safeUnwrapTokenAndTransferFromWithHelper` instead.
*/
function safeUnwrapTokenAndTransferFrom(
IWRON _wron,
address _token,
address _from,
address payable _to,
uint256 _amount
) internal {
if (_token == address(_wron)) {
// Check whether the recipient receives RON
if (LibRONTransfer.send(_to, 0)) {
LibTokenTransferFrom.safeTransferFrom(_token, _from, address(this), _amount);
IWRON(_wron).withdraw(_amount);
LibRONTransfer.safeTransfer(_to, _amount);
return;
}
}

LibTokenTransferFrom.safeTransferFrom(_token, _from, _to, _amount);
}

/**
* @dev See `safeUnwrapTokenAndTransfer`.
*
* Requirements:
* - The consumer contract must approve the contract `_wronHelper`.
*
* Note: This function supports the use of a proxy contract by using the WRONHelper contract to unwrap WRON and
* transfer RON.
*/
function safeUnwrapTokenAndTransferFromWithHelper(
IWRON _wron,
IWRONHelper _wronHelper,
address _token,
address _from,
address payable _to,
uint256 _amount
) internal {
if (_token == address(_wron)) {
// Check whether the recipient receives RON
if (LibRONTransfer.send(_to, 0)) {
LibTokenTransferFrom.safeTransferFrom(_token, _from, address(this), _amount);
_wron.approve(address(_wronHelper), _amount);
_wronHelper.withdrawTo(_to, _amount);
return;
}
}

LibTokenTransferFrom.safeTransferFrom(_token, _from, _to, _amount);
}
}

0 comments on commit 7e3786b

Please sign in to comment.