Skip to content

Commit

Permalink
Merge pull request #39 from axieinfinity/merge/release/v0.1.0-feature…
Browse files Browse the repository at this point in the history
…/math

chore(`math`): merge from `release/v0.1.0`
  • Loading branch information
TuDo1403 authored Jan 2, 2024
2 parents d9ee098 + 2141612 commit e08fdca
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/interfaces/IWRON.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IWRON {
/**
* @dev Deposit RON and increase balance WRON tokens of sender.
*/
function deposit() external payable;

/// @dev See {IERC20-transfer}.
function transfer(address to, uint256 value) external returns (bool);

/// @dev See {IERC20-transferFrom}.
function transferFrom(address src, address dst, uint256 wad) external returns (bool);

/**
* @dev Withdraw RON and decrease balance WRON tokens of sender.
*/
function withdraw(uint256) external;

/// @dev See {IERC20-balanceOf}.
function balanceOf(address) external view returns (uint256);

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

interface IWRONHelper {
/**
* @dev Returns WRON address.
*/
function WRON() external view returns (address);

/**
* @dev Deposit WRON and withdraw RON token.
*
* Requirements:
* - This contract must be approved `amount` WRON tokens by sender.
*/
function withdraw(uint256 amount) external;

/**
* @dev Deposit WRON and withdraw RON token to address `to`.
*
* Requirements:
* - This contract must be approved `amount` WRON tokens by sender.
*/
function withdrawTo(address payable to, uint256 amount) external;
}
35 changes: 35 additions & 0 deletions src/legacy/transfers/RONTransferHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol";

/**
* @title RONTransferHelper
*/
library RONTransferHelper {
/**
* @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.concat(
"TransferHelper: 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));
}
}
118 changes: 118 additions & 0 deletions src/legacy/transfers/RONTransferHelperExtended.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { IWRON } from "../../interfaces/IWRON.sol";
import { IWRONHelper } from "../../interfaces/IWRONHelper.sol";
import { RONTransferHelper } from "./RONTransferHelper.sol";
import { TransferFromHelper } from "./TransferFromHelper.sol";
import { TransferHelper } from "./TransferHelper.sol";

library RONTransferHelperExtended {
/**
* @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 (RONTransferHelper.send(to, 0)) {
wron.withdraw(amount);
RONTransferHelper.safeTransfer(to, amount);
return;
}
}

TransferHelper.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 (RONTransferHelper.send(to, 0)) {
wron.approve(address(wronHelper), amount);
wronHelper.withdrawTo(to, amount);
return;
}
}

TransferHelper.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 (RONTransferHelper.send(to, 0)) {
TransferFromHelper.safeTransferFrom(token, from, address(this), amount);
IWRON(wron).withdraw(amount);
RONTransferHelper.safeTransfer(to, amount);
return;
}
}

TransferFromHelper.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 (RONTransferHelper.send(to, 0)) {
TransferFromHelper.safeTransferFrom(token, from, address(this), amount);
wron.approve(address(wronHelper), amount);
wronHelper.withdrawTo(to, amount);
return;
}
}

TransferFromHelper.safeTransferFrom(token, from, to, amount);
}
}
39 changes: 39 additions & 0 deletions src/legacy/transfers/TransferFromHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol";

/**
* @title TransferFromHelper
* @dev Wraps transfer from methods for ERC20 tokens that do not consistently return true/false or revert.
*/
library TransferFromHelper {
/**
* @dev Transfers token and wraps result for the input address to a recipient.
*/
function safeTransferFrom(address token, address from, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(
0x23b872dd, // IERC20.transferFrom.selector
from,
to,
value
)
);

if (!success || !(data.length == 0 || abi.decode(data, (bool)))) {
revert(
string.concat(
"TransferFromHelper: could not transfer token ",
Strings.toHexString(uint160(token), 20),
" from ",
Strings.toHexString(uint160(from), 20),
" to ",
Strings.toHexString(uint160(to), 20),
" value ",
Strings.toHexString(value)
)
);
}
}
}
36 changes: 36 additions & 0 deletions src/legacy/transfers/TransferHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol";

/**
* @title TransferHelper
* @dev Wraps transfer methods for ERC20/native tokens that do not consistently return true/false or revert.
*/
library TransferHelper {
/**
* @dev Transfers token and wraps result for the method caller to a recipient.
*/
function safeTransfer(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(
0xa9059cbb, // IERC20.transfer.selector
to,
value
)
);

if (!success || !(data.length == 0 || abi.decode(data, (bool)))) {
revert(
string.concat(
"TransferHelper: could not transfer token ",
Strings.toHexString(uint160(token), 20),
" to ",
Strings.toHexString(uint160(to), 20),
" value ",
Strings.toHexString(value)
)
);
}
}
}

0 comments on commit e08fdca

Please sign in to comment.