From 3dbf04582b1e62237544b76f528737ee76697f99 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sat, 30 Dec 2023 15:09:53 +0700 Subject: [PATCH 01/22] feat: add token transfer libs --- src/transfers/LibTokenTransfer.sol | 38 +++++++++++++++++++++ src/transfers/LibTokenTransferFrom.sol | 46 ++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/transfers/LibTokenTransfer.sol create mode 100644 src/transfers/LibTokenTransferFrom.sol diff --git a/src/transfers/LibTokenTransfer.sol b/src/transfers/LibTokenTransfer.sol new file mode 100644 index 0000000..3415e97 --- /dev/null +++ b/src/transfers/LibTokenTransfer.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/utils/Strings.sol"; + +/** + * @title LibTokenTransfer + * @dev Wraps transfer methods for ERC20 tokens that do not consistently return true/false or revert. + */ +library LibTokenTransfer { + /** + * @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( + abi.encodePacked( + "TransferHelper: could not transfer token ", + Strings.toHexString(uint160(token), 20), + " to ", + Strings.toHexString(uint160(to), 20), + " value ", + Strings.toHexString(value) + ) + ) + ); + } + } +} diff --git a/src/transfers/LibTokenTransferFrom.sol b/src/transfers/LibTokenTransferFrom.sol new file mode 100644 index 0000000..3ea7048 --- /dev/null +++ b/src/transfers/LibTokenTransferFrom.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/utils/Strings.sol"; + +/** + * @title LibTokenTransferFrom + * @dev Wraps transfer from methods for ERC20 tokens that do not consistently return true/false or revert. + */ +library LibTokenTransferFrom { + /** + * @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( + abi.encodePacked( + "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) + ) + ) + ); + } + } +} From 7e3786b4d4ff625c64cf13b1a8067fa3efe99fb3 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sat, 30 Dec 2023 15:17:53 +0700 Subject: [PATCH 02/22] feat: add ron transfer libs --- src/interfaces/IWRON.sol | 16 +++ src/interfaces/IWRONHelper.sol | 10 ++ src/transfers/LibRONTransfer.sol | 37 +++++++ src/transfers/LibRONTransferExtended.sol | 122 +++++++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 src/interfaces/IWRON.sol create mode 100644 src/interfaces/IWRONHelper.sol create mode 100644 src/transfers/LibRONTransfer.sol create mode 100644 src/transfers/LibRONTransferExtended.sol diff --git a/src/interfaces/IWRON.sol b/src/interfaces/IWRON.sol new file mode 100644 index 0000000..c1d4f18 --- /dev/null +++ b/src/interfaces/IWRON.sol @@ -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); +} diff --git a/src/interfaces/IWRONHelper.sol b/src/interfaces/IWRONHelper.sol new file mode 100644 index 0000000..370b47e --- /dev/null +++ b/src/interfaces/IWRONHelper.sol @@ -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; +} diff --git a/src/transfers/LibRONTransfer.sol b/src/transfers/LibRONTransfer.sol new file mode 100644 index 0000000..035a3f0 --- /dev/null +++ b/src/transfers/LibRONTransfer.sol @@ -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)); + } +} diff --git a/src/transfers/LibRONTransferExtended.sol b/src/transfers/LibRONTransferExtended.sol new file mode 100644 index 0000000..50b5ba7 --- /dev/null +++ b/src/transfers/LibRONTransferExtended.sol @@ -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); + } +} From 301210ea90d9e4fec2c7fd7ff9825b599b225637 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 2 Jan 2024 11:09:08 +0700 Subject: [PATCH 03/22] feat: add legacy transfer utils --- remappings.txt | 1 + .../transfers/RONTransferHelper.sol} | 4 +-- .../transfers/RONTransferHelperExtended.sol} | 36 +++++++++---------- .../transfers/TransferFromHelper.sol} | 28 +++++++-------- .../transfers/TransferHelper.sol} | 20 +++++------ 5 files changed, 45 insertions(+), 44 deletions(-) create mode 100644 remappings.txt rename src/{transfers/LibRONTransfer.sol => legacy/transfers/RONTransferHelper.sol} (91%) rename src/{transfers/LibRONTransferExtended.sol => legacy/transfers/RONTransferHelperExtended.sol} (77%) rename src/{transfers/LibTokenTransferFrom.sol => legacy/transfers/TransferFromHelper.sol} (63%) rename src/{transfers/LibTokenTransfer.sol => legacy/transfers/TransferHelper.sol} (55%) diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 0000000..add52da --- /dev/null +++ b/remappings.txt @@ -0,0 +1 @@ +@openzeppelin/=lib/openzeppelin-contracts/ \ No newline at end of file diff --git a/src/transfers/LibRONTransfer.sol b/src/legacy/transfers/RONTransferHelper.sol similarity index 91% rename from src/transfers/LibRONTransfer.sol rename to src/legacy/transfers/RONTransferHelper.sol index 035a3f0..02a2a7a 100644 --- a/src/transfers/LibRONTransfer.sol +++ b/src/legacy/transfers/RONTransferHelper.sol @@ -6,7 +6,7 @@ import "@openzeppelin/contracts/utils/Strings.sol"; /** * @title RONTransferHelper */ -library LibRONTransfer { +library RONTransferHelper { /** * @dev Transfers RON and wraps result for the method caller to a recipient. */ @@ -17,7 +17,7 @@ library LibRONTransfer { revert( string( abi.encodePacked( - "RONTransferHelper: could not transfer RON to ", + "TransferHelper: could not transfer RON to ", Strings.toHexString(uint160(address(_to)), 20), " value ", Strings.toHexString(_value) diff --git a/src/transfers/LibRONTransferExtended.sol b/src/legacy/transfers/RONTransferHelperExtended.sol similarity index 77% rename from src/transfers/LibRONTransferExtended.sol rename to src/legacy/transfers/RONTransferHelperExtended.sol index 50b5ba7..8a538c2 100644 --- a/src/transfers/LibRONTransferExtended.sol +++ b/src/legacy/transfers/RONTransferHelperExtended.sol @@ -1,13 +1,13 @@ // 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"; +import "../../interfaces/IWRON.sol"; +import "../../interfaces/IWRONHelper.sol"; +import "./RONTransferHelper.sol"; +import "./TransferFromHelper.sol"; +import "./TransferHelper.sol"; -library LibRONTransferExtended { +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. @@ -21,14 +21,14 @@ library LibRONTransferExtended { 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)) { + if (RONTransferHelper.send(_to, 0)) { _wron.withdraw(_amount); - LibRONTransfer.safeTransfer(_to, _amount); + RONTransferHelper.safeTransfer(_to, _amount); return; } } - LibTokenTransfer.safeTransfer(_token, _to, _amount); + TransferHelper.safeTransfer(_token, _to, _amount); } /** @@ -49,14 +49,14 @@ library LibRONTransferExtended { ) internal { if (_token == address(_wron)) { // Check whether the recipient receives RON - if (LibRONTransfer.send(_to, 0)) { + if (RONTransferHelper.send(_to, 0)) { _wron.approve(address(_wronHelper), _amount); _wronHelper.withdrawTo(_to, _amount); return; } } - LibTokenTransfer.safeTransfer(_token, _to, _amount); + TransferHelper.safeTransfer(_token, _to, _amount); } /** @@ -79,15 +79,15 @@ library LibRONTransferExtended { ) internal { if (_token == address(_wron)) { // Check whether the recipient receives RON - if (LibRONTransfer.send(_to, 0)) { - LibTokenTransferFrom.safeTransferFrom(_token, _from, address(this), _amount); + if (RONTransferHelper.send(_to, 0)) { + TransferFromHelper.safeTransferFrom(_token, _from, address(this), _amount); IWRON(_wron).withdraw(_amount); - LibRONTransfer.safeTransfer(_to, _amount); + RONTransferHelper.safeTransfer(_to, _amount); return; } } - LibTokenTransferFrom.safeTransferFrom(_token, _from, _to, _amount); + TransferFromHelper.safeTransferFrom(_token, _from, _to, _amount); } /** @@ -109,14 +109,14 @@ library LibRONTransferExtended { ) internal { if (_token == address(_wron)) { // Check whether the recipient receives RON - if (LibRONTransfer.send(_to, 0)) { - LibTokenTransferFrom.safeTransferFrom(_token, _from, address(this), _amount); + if (RONTransferHelper.send(_to, 0)) { + TransferFromHelper.safeTransferFrom(_token, _from, address(this), _amount); _wron.approve(address(_wronHelper), _amount); _wronHelper.withdrawTo(_to, _amount); return; } } - LibTokenTransferFrom.safeTransferFrom(_token, _from, _to, _amount); + TransferFromHelper.safeTransferFrom(_token, _from, _to, _amount); } } diff --git a/src/transfers/LibTokenTransferFrom.sol b/src/legacy/transfers/TransferFromHelper.sol similarity index 63% rename from src/transfers/LibTokenTransferFrom.sol rename to src/legacy/transfers/TransferFromHelper.sol index 3ea7048..d543eb4 100644 --- a/src/transfers/LibTokenTransferFrom.sol +++ b/src/legacy/transfers/TransferFromHelper.sol @@ -4,25 +4,25 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/Strings.sol"; /** - * @title LibTokenTransferFrom + * @title TransferFromHelper * @dev Wraps transfer from methods for ERC20 tokens that do not consistently return true/false or revert. */ -library LibTokenTransferFrom { +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 + address _token, + address _from, + address _to, + uint256 _value ) internal { - (bool success, bytes memory data) = token.call( + (bool success, bytes memory data) = _token.call( abi.encodeWithSelector( 0x23b872dd, // IERC20.transferFrom.selector - from, - to, - value + _from, + _to, + _value ) ); @@ -31,13 +31,13 @@ library LibTokenTransferFrom { string( abi.encodePacked( "TransferFromHelper: could not transfer token ", - Strings.toHexString(uint160(token), 20), + Strings.toHexString(uint160(_token), 20), " from ", - Strings.toHexString(uint160(from), 20), + Strings.toHexString(uint160(_from), 20), " to ", - Strings.toHexString(uint160(to), 20), + Strings.toHexString(uint160(_to), 20), " value ", - Strings.toHexString(value) + Strings.toHexString(_value) ) ) ); diff --git a/src/transfers/LibTokenTransfer.sol b/src/legacy/transfers/TransferHelper.sol similarity index 55% rename from src/transfers/LibTokenTransfer.sol rename to src/legacy/transfers/TransferHelper.sol index 3415e97..0d4e601 100644 --- a/src/transfers/LibTokenTransfer.sol +++ b/src/legacy/transfers/TransferHelper.sol @@ -4,19 +4,19 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/Strings.sol"; /** - * @title LibTokenTransfer - * @dev Wraps transfer methods for ERC20 tokens that do not consistently return true/false or revert. + * @title TransferHelper + * @dev Wraps transfer methods for ERC20/native tokens that do not consistently return true/false or revert. */ -library LibTokenTransfer { +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( + function safeTransfer(address _token, address _to, uint256 _value) internal { + (bool success, bytes memory data) = _token.call( abi.encodeWithSelector( 0xa9059cbb, // IERC20.transfer.selector - to, - value + _to, + _value ) ); @@ -25,11 +25,11 @@ library LibTokenTransfer { string( abi.encodePacked( "TransferHelper: could not transfer token ", - Strings.toHexString(uint160(token), 20), + Strings.toHexString(uint160(_token), 20), " to ", - Strings.toHexString(uint160(to), 20), + Strings.toHexString(uint160(_to), 20), " value ", - Strings.toHexString(value) + Strings.toHexString(_value) ) ) ); From 7768fd1b1b36eefc499e274cfe959a525753acc9 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 2 Jan 2024 11:14:33 +0700 Subject: [PATCH 04/22] chore: fix convention --- src/legacy/transfers/RONTransferHelper.sol | 16 +-- .../transfers/RONTransferHelperExtended.sol | 110 +++++++++--------- src/legacy/transfers/TransferFromHelper.sol | 25 ++-- src/legacy/transfers/TransferHelper.sol | 16 +-- 4 files changed, 79 insertions(+), 88 deletions(-) diff --git a/src/legacy/transfers/RONTransferHelper.sol b/src/legacy/transfers/RONTransferHelper.sol index 02a2a7a..152cecc 100644 --- a/src/legacy/transfers/RONTransferHelper.sol +++ b/src/legacy/transfers/RONTransferHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "@openzeppelin/contracts/utils/Strings.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; /** * @title RONTransferHelper @@ -10,17 +10,17 @@ 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); + function safeTransfer(address payable to, uint256 value) internal { + bool success = send(to, value); - if (!_success) { + if (!success) { revert( string( abi.encodePacked( "TransferHelper: could not transfer RON to ", - Strings.toHexString(uint160(address(_to)), 20), + Strings.toHexString(uint160(address(to)), 20), " value ", - Strings.toHexString(_value) + Strings.toHexString(value) ) ) ); @@ -31,7 +31,7 @@ library RONTransferHelper { * @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)); + function send(address payable to, uint256 value) internal returns (bool success) { + (success,) = to.call{ value: value }(new bytes(0)); } } diff --git a/src/legacy/transfers/RONTransferHelperExtended.sol b/src/legacy/transfers/RONTransferHelperExtended.sol index 8a538c2..08d31c3 100644 --- a/src/legacy/transfers/RONTransferHelperExtended.sol +++ b/src/legacy/transfers/RONTransferHelperExtended.sol @@ -1,122 +1,118 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "../../interfaces/IWRON.sol"; -import "../../interfaces/IWRONHelper.sol"; -import "./RONTransferHelper.sol"; -import "./TransferFromHelper.sol"; -import "./TransferHelper.sol"; +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. + * @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)) { + 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); + if (RONTransferHelper.send(to, 0)) { + wron.withdraw(amount); + RONTransferHelper.safeTransfer(to, amount); return; } } - TransferHelper.safeTransfer(_token, _to, _amount); + TransferHelper.safeTransfer(token, to, amount); } /** * @dev See `safeUnwrapTokenAndTransfer`. * * Requirements: - * - The consumer contract must approve the contract `_wronHelper`. + * - 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 + IWRON wron, + IWRONHelper wronHelper, + address token, + address payable to, + uint256 amount ) internal { - if (_token == address(_wron)) { + if (token == address(wron)) { // Check whether the recipient receives RON - if (RONTransferHelper.send(_to, 0)) { - _wron.approve(address(_wronHelper), _amount); - _wronHelper.withdrawTo(_to, _amount); + if (RONTransferHelper.send(to, 0)) { + wron.approve(address(wronHelper), amount); + wronHelper.withdrawTo(to, amount); return; } } - TransferHelper.safeTransfer(_token, _to, _amount); + 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. + * @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)) { + 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); + 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); + TransferFromHelper.safeTransferFrom(token, from, to, amount); } /** * @dev See `safeUnwrapTokenAndTransfer`. * * Requirements: - * - The consumer contract must approve the contract `_wronHelper`. + * - 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 + IWRON wron, + IWRONHelper wronHelper, + address token, + address from, + address payable to, + uint256 amount ) internal { - if (_token == address(_wron)) { + 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); + 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); + TransferFromHelper.safeTransferFrom(token, from, to, amount); } } diff --git a/src/legacy/transfers/TransferFromHelper.sol b/src/legacy/transfers/TransferFromHelper.sol index d543eb4..f52a054 100644 --- a/src/legacy/transfers/TransferFromHelper.sol +++ b/src/legacy/transfers/TransferFromHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "@openzeppelin/contracts/utils/Strings.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; /** * @title TransferFromHelper @@ -11,18 +11,13 @@ 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( + 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 + from, + to, + value ) ); @@ -31,13 +26,13 @@ library TransferFromHelper { string( abi.encodePacked( "TransferFromHelper: could not transfer token ", - Strings.toHexString(uint160(_token), 20), + Strings.toHexString(uint160(token), 20), " from ", - Strings.toHexString(uint160(_from), 20), + Strings.toHexString(uint160(from), 20), " to ", - Strings.toHexString(uint160(_to), 20), + Strings.toHexString(uint160(to), 20), " value ", - Strings.toHexString(_value) + Strings.toHexString(value) ) ) ); diff --git a/src/legacy/transfers/TransferHelper.sol b/src/legacy/transfers/TransferHelper.sol index 0d4e601..517464f 100644 --- a/src/legacy/transfers/TransferHelper.sol +++ b/src/legacy/transfers/TransferHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "@openzeppelin/contracts/utils/Strings.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; /** * @title TransferHelper @@ -11,12 +11,12 @@ 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( + function safeTransfer(address token, address to, uint256 value) internal { + (bool success, bytes memory data) = token.call( abi.encodeWithSelector( 0xa9059cbb, // IERC20.transfer.selector - _to, - _value + to, + value ) ); @@ -25,11 +25,11 @@ library TransferHelper { string( abi.encodePacked( "TransferHelper: could not transfer token ", - Strings.toHexString(uint160(_token), 20), + Strings.toHexString(uint160(token), 20), " to ", - Strings.toHexString(uint160(_to), 20), + Strings.toHexString(uint160(to), 20), " value ", - Strings.toHexString(_value) + Strings.toHexString(value) ) ) ); From 1af4175280e38336ce02119e6c2e7d744e15499b Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 2 Jan 2024 11:15:18 +0700 Subject: [PATCH 05/22] chore: fix convention --- src/interfaces/IWRONHelper.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interfaces/IWRONHelper.sol b/src/interfaces/IWRONHelper.sol index 370b47e..8f05ef1 100644 --- a/src/interfaces/IWRONHelper.sol +++ b/src/interfaces/IWRONHelper.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; interface IWRONHelper { function WRON() external view returns (address); - function withdraw(uint256 _amount) external; + function withdraw(uint256 amount) external; - function withdrawTo(address payable _to, uint256 _amount) external; + function withdrawTo(address payable to, uint256 amount) external; } From 0e00588fe1c7843deae91fc89b3b415bfaf1a664 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 2 Jan 2024 12:51:37 +0700 Subject: [PATCH 06/22] chore: use string.concat for string combination instead --- src/legacy/transfers/RONTransferHelper.sol | 12 +++++------- src/legacy/transfers/TransferFromHelper.sol | 20 +++++++++----------- src/legacy/transfers/TransferHelper.sol | 16 +++++++--------- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/legacy/transfers/RONTransferHelper.sol b/src/legacy/transfers/RONTransferHelper.sol index 152cecc..9c4ac2e 100644 --- a/src/legacy/transfers/RONTransferHelper.sol +++ b/src/legacy/transfers/RONTransferHelper.sol @@ -15,13 +15,11 @@ library RONTransferHelper { if (!success) { revert( - string( - abi.encodePacked( - "TransferHelper: could not transfer RON to ", - Strings.toHexString(uint160(address(to)), 20), - " value ", - Strings.toHexString(value) - ) + string.concat( + "TransferHelper: could not transfer RON to ", + Strings.toHexString(uint160(address(to)), 20), + " value ", + Strings.toHexString(value) ) ); } diff --git a/src/legacy/transfers/TransferFromHelper.sol b/src/legacy/transfers/TransferFromHelper.sol index f52a054..9d9a3e8 100644 --- a/src/legacy/transfers/TransferFromHelper.sol +++ b/src/legacy/transfers/TransferFromHelper.sol @@ -23,17 +23,15 @@ library TransferFromHelper { if (!success || !(data.length == 0 || abi.decode(data, (bool)))) { revert( - string( - abi.encodePacked( - "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) - ) + 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) ) ); } diff --git a/src/legacy/transfers/TransferHelper.sol b/src/legacy/transfers/TransferHelper.sol index 517464f..3426c0c 100644 --- a/src/legacy/transfers/TransferHelper.sol +++ b/src/legacy/transfers/TransferHelper.sol @@ -22,15 +22,13 @@ library TransferHelper { if (!success || !(data.length == 0 || abi.decode(data, (bool)))) { revert( - string( - abi.encodePacked( - "TransferHelper: could not transfer token ", - Strings.toHexString(uint160(token), 20), - " to ", - Strings.toHexString(uint160(to), 20), - " value ", - Strings.toHexString(value) - ) + string.concat( + "TransferHelper: could not transfer token ", + Strings.toHexString(uint160(token), 20), + " to ", + Strings.toHexString(uint160(to), 20), + " value ", + Strings.toHexString(value) ) ); } From adb78b043ae8c1a437dfd8ade94151ddbed5cfc6 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 2 Jan 2024 13:29:13 +0700 Subject: [PATCH 07/22] chore: use relative import and add docs --- remappings.txt | 1 - src/interfaces/IWRON.sol | 10 ++++++++++ src/interfaces/IWRONHelper.sol | 15 +++++++++++++++ src/legacy/transfers/RONTransferHelper.sol | 2 +- src/legacy/transfers/TransferFromHelper.sol | 2 +- src/legacy/transfers/TransferHelper.sol | 2 +- 6 files changed, 28 insertions(+), 4 deletions(-) delete mode 100644 remappings.txt diff --git a/remappings.txt b/remappings.txt deleted file mode 100644 index add52da..0000000 --- a/remappings.txt +++ /dev/null @@ -1 +0,0 @@ -@openzeppelin/=lib/openzeppelin-contracts/ \ No newline at end of file diff --git a/src/interfaces/IWRON.sol b/src/interfaces/IWRON.sol index c1d4f18..e468a78 100644 --- a/src/interfaces/IWRON.sol +++ b/src/interfaces/IWRON.sol @@ -2,15 +2,25 @@ 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); } diff --git a/src/interfaces/IWRONHelper.sol b/src/interfaces/IWRONHelper.sol index 8f05ef1..5ddbb10 100644 --- a/src/interfaces/IWRONHelper.sol +++ b/src/interfaces/IWRONHelper.sol @@ -2,9 +2,24 @@ 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; } diff --git a/src/legacy/transfers/RONTransferHelper.sol b/src/legacy/transfers/RONTransferHelper.sol index 9c4ac2e..93f16b0 100644 --- a/src/legacy/transfers/RONTransferHelper.sol +++ b/src/legacy/transfers/RONTransferHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; /** * @title RONTransferHelper diff --git a/src/legacy/transfers/TransferFromHelper.sol b/src/legacy/transfers/TransferFromHelper.sol index 9d9a3e8..19a98d6 100644 --- a/src/legacy/transfers/TransferFromHelper.sol +++ b/src/legacy/transfers/TransferFromHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; /** * @title TransferFromHelper diff --git a/src/legacy/transfers/TransferHelper.sol b/src/legacy/transfers/TransferHelper.sol index 3426c0c..9f9a4ec 100644 --- a/src/legacy/transfers/TransferHelper.sol +++ b/src/legacy/transfers/TransferHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; /** * @title TransferHelper From e49309598c8979e7dbe4fb5ac026ff0c60b6cb3a Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:14:07 +0700 Subject: [PATCH 08/22] chore: remove deep clone oz --- .gitmodules | 3 - lib/openzeppelin-contracts | 1 - src/legacy/transfers/RONTransferHelper.sol | 62 ++--- .../transfers/RONTransferHelperExtended.sol | 218 +++++++++--------- src/legacy/transfers/TransferFromHelper.sol | 72 +++--- src/legacy/transfers/TransferHelper.sol | 66 +++--- 6 files changed, 209 insertions(+), 213 deletions(-) delete mode 160000 lib/openzeppelin-contracts diff --git a/.gitmodules b/.gitmodules index 690924b..888d42d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std -[submodule "lib/openzeppelin-contracts"] - path = lib/openzeppelin-contracts - url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts deleted file mode 160000 index bd325d5..0000000 --- a/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bd325d56b4c62c9c5c1aff048c37c6bb18ac0290 diff --git a/src/legacy/transfers/RONTransferHelper.sol b/src/legacy/transfers/RONTransferHelper.sol index 93f16b0..1dc7645 100644 --- a/src/legacy/transfers/RONTransferHelper.sol +++ b/src/legacy/transfers/RONTransferHelper.sol @@ -1,35 +1,35 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +// // SPDX-License-Identifier: MIT +// pragma solidity ^0.8.0; -import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; +// 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); +// /** +// * @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) - ) - ); - } - } +// 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)); - } -} +// /** +// * @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)); +// } +// } diff --git a/src/legacy/transfers/RONTransferHelperExtended.sol b/src/legacy/transfers/RONTransferHelperExtended.sol index 08d31c3..bf4caaa 100644 --- a/src/legacy/transfers/RONTransferHelperExtended.sol +++ b/src/legacy/transfers/RONTransferHelperExtended.sol @@ -1,118 +1,118 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +// // 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"; +// 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; - } - } +// 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); - } +// 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; - } - } +// /** +// * @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); - } +// 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; - } - } +// /** +// * @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); - } +// 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; - } - } +// /** +// * @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); - } -} +// TransferFromHelper.safeTransferFrom(token, from, to, amount); +// } +// } diff --git a/src/legacy/transfers/TransferFromHelper.sol b/src/legacy/transfers/TransferFromHelper.sol index 19a98d6..fd1f3c7 100644 --- a/src/legacy/transfers/TransferFromHelper.sol +++ b/src/legacy/transfers/TransferFromHelper.sol @@ -1,39 +1,39 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +// // SPDX-License-Identifier: MIT +// pragma solidity ^0.8.0; -import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; +// 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 - ) - ); +// /** +// * @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) - ) - ); - } - } -} +// 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) +// ) +// ); +// } +// } +// } diff --git a/src/legacy/transfers/TransferHelper.sol b/src/legacy/transfers/TransferHelper.sol index 9f9a4ec..e6bee24 100644 --- a/src/legacy/transfers/TransferHelper.sol +++ b/src/legacy/transfers/TransferHelper.sol @@ -1,36 +1,36 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +// // SPDX-License-Identifier: MIT +// pragma solidity ^0.8.0; -import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; +// 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 - ) - ); +// /** +// * @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) - ) - ); - } - } -} +// 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) +// ) +// ); +// } +// } +// } From c482e1c3d46545b3dac28baef8bacc7d9fc9e299 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:20:21 +0700 Subject: [PATCH 09/22] chore: remove deep clone forge-std --- .gitmodules | 3 -- lib/forge-std | 1 - test/transfers/LibNativeTransfer.t.sol | 54 +++++++++++++------------- 3 files changed, 27 insertions(+), 31 deletions(-) delete mode 160000 lib/forge-std diff --git a/.gitmodules b/.gitmodules index 888d42d..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "lib/forge-std"] - path = lib/forge-std - url = https://github.com/foundry-rs/forge-std diff --git a/lib/forge-std b/lib/forge-std deleted file mode 160000 index 2f11269..0000000 --- a/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2f112697506eab12d433a65fdc31a639548fe365 diff --git a/test/transfers/LibNativeTransfer.t.sol b/test/transfers/LibNativeTransfer.t.sol index 5eddad0..17442ca 100644 --- a/test/transfers/LibNativeTransfer.t.sol +++ b/test/transfers/LibNativeTransfer.t.sol @@ -1,33 +1,33 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; +// // SPDX-License-Identifier: MIT +// pragma solidity ^0.8.23; -import { Test } from "forge-std/Test.sol"; -import { LibNativeTransfer } from "src/transfers/LibNativeTransfer.sol"; +// import { Test } from "forge-std/Test.sol"; +// import { LibNativeTransfer } from "src/transfers/LibNativeTransfer.sol"; -contract LibNativeTransferTest is Test { - function testFork_RevertWhen_TransferNativeToContractWithoutFallback_safeTransfer( - address any, - uint256 amount, - uint256 gas - ) external { - vm.deal(any, amount); - vm.expectRevert(); - vm.prank(any); - LibNativeTransfer.transfer(address(this), amount, gas); - } +// contract LibNativeTransferTest is Test { +// function testFork_RevertWhen_TransferNativeToContractWithoutFallback_safeTransfer( +// address any, +// uint256 amount, +// uint256 gas +// ) external { +// vm.deal(any, amount); +// vm.expectRevert(); +// vm.prank(any); +// LibNativeTransfer.transfer(address(this), amount, gas); +// } - function testConcrete_TransferNative(uint256 gas) external { - LibNativeTransfer.transfer(address(0xBEEF), 1e18, gas); - assertEq(address(0xBEEF).balance, 1e18); - } +// function testConcrete_TransferNative(uint256 gas) external { +// LibNativeTransfer.transfer(address(0xBEEF), 1e18, gas); +// assertEq(address(0xBEEF).balance, 1e18); +// } - function testFork_TransferNativeToRecipient(address recipient, uint256 amount, uint256 gas) external { - // Transferring to msg.sender can fail because it's possible to overflow their ETH balance as it begins non-zero. - if (recipient.code.length > 0 || uint256(uint160(recipient)) <= 18 || recipient == msg.sender) return; +// function testFork_TransferNativeToRecipient(address recipient, uint256 amount, uint256 gas) external { +// // Transferring to msg.sender can fail because it's possible to overflow their ETH balance as it begins non-zero. +// if (recipient.code.length > 0 || uint256(uint160(recipient)) <= 18 || recipient == msg.sender) return; - amount = _bound(amount, 0, address(this).balance); - LibNativeTransfer.transfer(recipient, amount, gas); +// amount = _bound(amount, 0, address(this).balance); +// LibNativeTransfer.transfer(recipient, amount, gas); - assertEq(recipient.balance, amount); - } -} +// assertEq(recipient.balance, amount); +// } +// } From 03cca4d4c16e383dfbce78ee1f484d2e83c06374 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:21:02 +0700 Subject: [PATCH 10/22] forge install: forge-std --- .gitmodules | 3 +++ lib/forge-std | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/forge-std diff --git a/.gitmodules b/.gitmodules index e69de29..888d42d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 0000000..b6a506d --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit b6a506db2262cad5ff982a87789ee6d1558ec861 From ffcc91e91ab72d5edba7f3478b44b5df1cf93e0a Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:31:05 +0700 Subject: [PATCH 11/22] forge install: openzeppelin-contracts --- .gitmodules | 3 +++ lib/openzeppelin-contracts | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/openzeppelin-contracts diff --git a/.gitmodules b/.gitmodules index 888d42d..690924b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "lib/openzeppelin-contracts"] + path = lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts new file mode 160000 index 0000000..6b4ec6c --- /dev/null +++ b/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit 6b4ec6c6c6b67d7350f5b449c0a2fd2dab1af3c7 From 2404114f35f88b566bd4093a79e9bcabf7091e58 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:32:36 +0700 Subject: [PATCH 12/22] submodule: add shallow config --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index 690924b..b618289 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,9 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std + shallow = true [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "lib/lib/openzeppelin-contracts"] + shallow = true From 463a0820be1f8198286be6d5137436cca2d1c3e4 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:33:37 +0700 Subject: [PATCH 13/22] chore: uncomment sol files --- src/legacy/transfers/RONTransferHelper.sol | 62 ++--- .../transfers/RONTransferHelperExtended.sol | 218 +++++++++--------- src/legacy/transfers/TransferFromHelper.sol | 72 +++--- src/legacy/transfers/TransferHelper.sol | 66 +++--- test/transfers/LibNativeTransfer.t.sol | 54 ++--- 5 files changed, 236 insertions(+), 236 deletions(-) diff --git a/src/legacy/transfers/RONTransferHelper.sol b/src/legacy/transfers/RONTransferHelper.sol index 1dc7645..93f16b0 100644 --- a/src/legacy/transfers/RONTransferHelper.sol +++ b/src/legacy/transfers/RONTransferHelper.sol @@ -1,35 +1,35 @@ -// // SPDX-License-Identifier: MIT -// pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; -// import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; +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); +/** + * @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) -// ) -// ); -// } -// } + 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)); -// } -// } + /** + * @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)); + } +} diff --git a/src/legacy/transfers/RONTransferHelperExtended.sol b/src/legacy/transfers/RONTransferHelperExtended.sol index bf4caaa..08d31c3 100644 --- a/src/legacy/transfers/RONTransferHelperExtended.sol +++ b/src/legacy/transfers/RONTransferHelperExtended.sol @@ -1,118 +1,118 @@ -// // SPDX-License-Identifier: MIT -// pragma solidity ^0.8.0; +// 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"; +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; -// } -// } +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); -// } + 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; -// } -// } + /** + * @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); -// } + 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; -// } -// } + /** + * @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); -// } + 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; -// } -// } + /** + * @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); -// } -// } + TransferFromHelper.safeTransferFrom(token, from, to, amount); + } +} diff --git a/src/legacy/transfers/TransferFromHelper.sol b/src/legacy/transfers/TransferFromHelper.sol index fd1f3c7..19a98d6 100644 --- a/src/legacy/transfers/TransferFromHelper.sol +++ b/src/legacy/transfers/TransferFromHelper.sol @@ -1,39 +1,39 @@ -// // SPDX-License-Identifier: MIT -// pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; -// import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; +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 -// ) -// ); +/** + * @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) -// ) -// ); -// } -// } -// } + 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) + ) + ); + } + } +} diff --git a/src/legacy/transfers/TransferHelper.sol b/src/legacy/transfers/TransferHelper.sol index e6bee24..9f9a4ec 100644 --- a/src/legacy/transfers/TransferHelper.sol +++ b/src/legacy/transfers/TransferHelper.sol @@ -1,36 +1,36 @@ -// // SPDX-License-Identifier: MIT -// pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; -// import { Strings } from "../../../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; +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 -// ) -// ); +/** + * @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) -// ) -// ); -// } -// } -// } + 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) + ) + ); + } + } +} diff --git a/test/transfers/LibNativeTransfer.t.sol b/test/transfers/LibNativeTransfer.t.sol index 17442ca..5eddad0 100644 --- a/test/transfers/LibNativeTransfer.t.sol +++ b/test/transfers/LibNativeTransfer.t.sol @@ -1,33 +1,33 @@ -// // SPDX-License-Identifier: MIT -// pragma solidity ^0.8.23; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; -// import { Test } from "forge-std/Test.sol"; -// import { LibNativeTransfer } from "src/transfers/LibNativeTransfer.sol"; +import { Test } from "forge-std/Test.sol"; +import { LibNativeTransfer } from "src/transfers/LibNativeTransfer.sol"; -// contract LibNativeTransferTest is Test { -// function testFork_RevertWhen_TransferNativeToContractWithoutFallback_safeTransfer( -// address any, -// uint256 amount, -// uint256 gas -// ) external { -// vm.deal(any, amount); -// vm.expectRevert(); -// vm.prank(any); -// LibNativeTransfer.transfer(address(this), amount, gas); -// } +contract LibNativeTransferTest is Test { + function testFork_RevertWhen_TransferNativeToContractWithoutFallback_safeTransfer( + address any, + uint256 amount, + uint256 gas + ) external { + vm.deal(any, amount); + vm.expectRevert(); + vm.prank(any); + LibNativeTransfer.transfer(address(this), amount, gas); + } -// function testConcrete_TransferNative(uint256 gas) external { -// LibNativeTransfer.transfer(address(0xBEEF), 1e18, gas); -// assertEq(address(0xBEEF).balance, 1e18); -// } + function testConcrete_TransferNative(uint256 gas) external { + LibNativeTransfer.transfer(address(0xBEEF), 1e18, gas); + assertEq(address(0xBEEF).balance, 1e18); + } -// function testFork_TransferNativeToRecipient(address recipient, uint256 amount, uint256 gas) external { -// // Transferring to msg.sender can fail because it's possible to overflow their ETH balance as it begins non-zero. -// if (recipient.code.length > 0 || uint256(uint160(recipient)) <= 18 || recipient == msg.sender) return; + function testFork_TransferNativeToRecipient(address recipient, uint256 amount, uint256 gas) external { + // Transferring to msg.sender can fail because it's possible to overflow their ETH balance as it begins non-zero. + if (recipient.code.length > 0 || uint256(uint160(recipient)) <= 18 || recipient == msg.sender) return; -// amount = _bound(amount, 0, address(this).balance); -// LibNativeTransfer.transfer(recipient, amount, gas); + amount = _bound(amount, 0, address(this).balance); + LibNativeTransfer.transfer(recipient, amount, gas); -// assertEq(recipient.balance, amount); -// } -// } + assertEq(recipient.balance, amount); + } +} From a297690618802d8321d92c51d903815f4d7a32ec Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:34:33 +0700 Subject: [PATCH 14/22] chore: add permisison for husky files --- .husky/generate-layout.sh | 0 .husky/pre-push | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .husky/generate-layout.sh mode change 100644 => 100755 .husky/pre-push diff --git a/.husky/generate-layout.sh b/.husky/generate-layout.sh old mode 100644 new mode 100755 diff --git a/.husky/pre-push b/.husky/pre-push old mode 100644 new mode 100755 From 02804a1e65ec4dacb0c851644119956088a3f811 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:34:54 +0700 Subject: [PATCH 15/22] chore: storage layout --- logs/contract-code-sizes.log | 27 +++++++++++++++++++ logs/storage/Base.sol:CommonBase.log | 1 + logs/storage/Base.sol:ScriptBase.log | 1 + logs/storage/Base.sol:TestBase.log | 1 + logs/storage/Counter.sol:Counter.log | 1 + logs/storage/MockERC20.sol:MockERC20.log | 10 +++++++ logs/storage/MockERC721.sol:MockERC721.log | 7 +++++ logs/storage/Script.sol:Script.log | 8 ++++++ .../StdAssertions.sol:StdAssertions.log | 1 + logs/storage/StdChains.sol:StdChains.log | 5 ++++ logs/storage/StdCheats.sol:StdCheats.log | 2 ++ logs/storage/StdCheats.sol:StdCheatsSafe.log | 1 + .../storage/StdInvariant.sol:StdInvariant.log | 9 +++++++ logs/storage/test.sol:DSTest.log | 2 ++ logs/storage/test.sol:Test.log | 18 +++++++++++++ 15 files changed, 94 insertions(+) create mode 100644 logs/contract-code-sizes.log create mode 100644 logs/storage/Base.sol:CommonBase.log create mode 100644 logs/storage/Base.sol:ScriptBase.log create mode 100644 logs/storage/Base.sol:TestBase.log create mode 100644 logs/storage/Counter.sol:Counter.log create mode 100644 logs/storage/MockERC20.sol:MockERC20.log create mode 100644 logs/storage/MockERC721.sol:MockERC721.log create mode 100644 logs/storage/Script.sol:Script.log create mode 100644 logs/storage/StdAssertions.sol:StdAssertions.log create mode 100644 logs/storage/StdChains.sol:StdChains.log create mode 100644 logs/storage/StdCheats.sol:StdCheats.log create mode 100644 logs/storage/StdCheats.sol:StdCheatsSafe.log create mode 100644 logs/storage/StdInvariant.sol:StdInvariant.log create mode 100644 logs/storage/test.sol:DSTest.log create mode 100644 logs/storage/test.sol:Test.log diff --git a/logs/contract-code-sizes.log b/logs/contract-code-sizes.log new file mode 100644 index 0000000..f906e69 --- /dev/null +++ b/logs/contract-code-sizes.log @@ -0,0 +1,27 @@ +| Contract | Size (kB) | Margin (kB) | +|---------------------------|-----------|-------------| +| LibErrorHandler | 0.086 | 24.49 | +| LibNativeTransfer | 0.086 | 24.49 | +| LibSafeRange | 0.086 | 24.49 | +| Math | 0.086 | 24.49 | +| MockERC20 | 3.704 | 20.872 | +| MockERC721 | 3.964 | 20.612 | +| Panic | 0.086 | 24.49 | +| RONTransferHelper | 0.086 | 24.49 | +| RONTransferHelperExtended | 0.086 | 24.49 | +| SafeCast | 0.086 | 24.49 | +| SignedMath | 0.086 | 24.49 | +| StdStyle | 0.086 | 24.49 | +| Strings | 0.086 | 24.49 | +| TransferFromHelper | 0.086 | 24.49 | +| TransferHelper | 0.086 | 24.49 | +| console | 0.086 | 24.49 | +| console2 | 0.086 | 24.49 | +| safeconsole | 0.086 | 24.49 | +| stdError | 0.592 | 23.984 | +| stdJson | 0.086 | 24.49 | +| stdMath | 0.086 | 24.49 | +| stdStorage | 0.086 | 24.49 | +| stdStorageSafe | 0.086 | 24.49 | +| stdToml | 0.086 | 24.49 | + diff --git a/logs/storage/Base.sol:CommonBase.log b/logs/storage/Base.sol:CommonBase.log new file mode 100644 index 0000000..0060c1c --- /dev/null +++ b/logs/storage/Base.sol:CommonBase.log @@ -0,0 +1 @@ +lib/forge-std/src/Base.sol:CommonBase:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) \ No newline at end of file diff --git a/logs/storage/Base.sol:ScriptBase.log b/logs/storage/Base.sol:ScriptBase.log new file mode 100644 index 0000000..7884c93 --- /dev/null +++ b/logs/storage/Base.sol:ScriptBase.log @@ -0,0 +1 @@ +lib/forge-std/src/Base.sol:ScriptBase:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) \ No newline at end of file diff --git a/logs/storage/Base.sol:TestBase.log b/logs/storage/Base.sol:TestBase.log new file mode 100644 index 0000000..2a0f2c1 --- /dev/null +++ b/logs/storage/Base.sol:TestBase.log @@ -0,0 +1 @@ +lib/forge-std/src/Base.sol:TestBase:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) \ No newline at end of file diff --git a/logs/storage/Counter.sol:Counter.log b/logs/storage/Counter.sol:Counter.log new file mode 100644 index 0000000..36a12ad --- /dev/null +++ b/logs/storage/Counter.sol:Counter.log @@ -0,0 +1 @@ +src/Counter.sol:Counter:number (storage_slot: 0) (offset: 0) (type: uint256) (numberOfBytes: 32) \ No newline at end of file diff --git a/logs/storage/MockERC20.sol:MockERC20.log b/logs/storage/MockERC20.sol:MockERC20.log new file mode 100644 index 0000000..b5e16f5 --- /dev/null +++ b/logs/storage/MockERC20.sol:MockERC20.log @@ -0,0 +1,10 @@ +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_name (storage_slot: 0) (offset: 0) (type: string) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_symbol (storage_slot: 1) (offset: 0) (type: string) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_decimals (storage_slot: 2) (offset: 0) (type: uint8) (numberOfBytes: 1) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_totalSupply (storage_slot: 3) (offset: 0) (type: uint256) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_balanceOf (storage_slot: 4) (offset: 0) (type: mapping(address => uint256)) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_allowance (storage_slot: 5) (offset: 0) (type: mapping(address => mapping(address => uint256))) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:INITIAL_CHAIN_ID (storage_slot: 6) (offset: 0) (type: uint256) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:INITIAL_DOMAIN_SEPARATOR (storage_slot: 7) (offset: 0) (type: bytes32) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:nonces (storage_slot: 8) (offset: 0) (type: mapping(address => uint256)) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC20.sol:MockERC20:initialized (storage_slot: 9) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/MockERC721.sol:MockERC721.log b/logs/storage/MockERC721.sol:MockERC721.log new file mode 100644 index 0000000..9dfd98d --- /dev/null +++ b/logs/storage/MockERC721.sol:MockERC721.log @@ -0,0 +1,7 @@ +lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_name (storage_slot: 0) (offset: 0) (type: string) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_symbol (storage_slot: 1) (offset: 0) (type: string) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_ownerOf (storage_slot: 2) (offset: 0) (type: mapping(uint256 => address)) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_balanceOf (storage_slot: 3) (offset: 0) (type: mapping(address => uint256)) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_getApproved (storage_slot: 4) (offset: 0) (type: mapping(uint256 => address)) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_isApprovedForAll (storage_slot: 5) (offset: 0) (type: mapping(address => mapping(address => bool))) (numberOfBytes: 32) +lib/forge-std/src/mocks/MockERC721.sol:MockERC721:initialized (storage_slot: 6) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/Script.sol:Script.log b/logs/storage/Script.sol:Script.log new file mode 100644 index 0000000..2ec2cf0 --- /dev/null +++ b/logs/storage/Script.sol:Script.log @@ -0,0 +1,8 @@ +lib/forge-std/src/Script.sol:Script:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 224) +lib/forge-std/src/Script.sol:Script:stdChainsInitialized (storage_slot: 7) (offset: 0) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/Script.sol:Script:chains (storage_slot: 8) (offset: 0) (type: mapping(string => struct StdChains.Chain)) (numberOfBytes: 32) +lib/forge-std/src/Script.sol:Script:defaultRpcUrls (storage_slot: 9) (offset: 0) (type: mapping(string => string)) (numberOfBytes: 32) +lib/forge-std/src/Script.sol:Script:idToAlias (storage_slot: 10) (offset: 0) (type: mapping(uint256 => string)) (numberOfBytes: 32) +lib/forge-std/src/Script.sol:Script:fallbackToDefaultRpcUrls (storage_slot: 11) (offset: 0) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/Script.sol:Script:gasMeteringOff (storage_slot: 11) (offset: 1) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/Script.sol:Script:IS_SCRIPT (storage_slot: 11) (offset: 2) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/StdAssertions.sol:StdAssertions.log b/logs/storage/StdAssertions.sol:StdAssertions.log new file mode 100644 index 0000000..4ee60ec --- /dev/null +++ b/logs/storage/StdAssertions.sol:StdAssertions.log @@ -0,0 +1 @@ +lib/forge-std/src/StdAssertions.sol:StdAssertions:_failed (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/StdChains.sol:StdChains.log b/logs/storage/StdChains.sol:StdChains.log new file mode 100644 index 0000000..e38d8f5 --- /dev/null +++ b/logs/storage/StdChains.sol:StdChains.log @@ -0,0 +1,5 @@ +lib/forge-std/src/StdChains.sol:StdChains:stdChainsInitialized (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/StdChains.sol:StdChains:chains (storage_slot: 1) (offset: 0) (type: mapping(string => struct StdChains.Chain)) (numberOfBytes: 32) +lib/forge-std/src/StdChains.sol:StdChains:defaultRpcUrls (storage_slot: 2) (offset: 0) (type: mapping(string => string)) (numberOfBytes: 32) +lib/forge-std/src/StdChains.sol:StdChains:idToAlias (storage_slot: 3) (offset: 0) (type: mapping(uint256 => string)) (numberOfBytes: 32) +lib/forge-std/src/StdChains.sol:StdChains:fallbackToDefaultRpcUrls (storage_slot: 4) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/StdCheats.sol:StdCheats.log b/logs/storage/StdCheats.sol:StdCheats.log new file mode 100644 index 0000000..fcbd9e8 --- /dev/null +++ b/logs/storage/StdCheats.sol:StdCheats.log @@ -0,0 +1,2 @@ +lib/forge-std/src/StdCheats.sol:StdCheats:gasMeteringOff (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/StdCheats.sol:StdCheats:stdstore (storage_slot: 1) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) \ No newline at end of file diff --git a/logs/storage/StdCheats.sol:StdCheatsSafe.log b/logs/storage/StdCheats.sol:StdCheatsSafe.log new file mode 100644 index 0000000..372cbe1 --- /dev/null +++ b/logs/storage/StdCheats.sol:StdCheatsSafe.log @@ -0,0 +1 @@ +lib/forge-std/src/StdCheats.sol:StdCheatsSafe:gasMeteringOff (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/StdInvariant.sol:StdInvariant.log b/logs/storage/StdInvariant.sol:StdInvariant.log new file mode 100644 index 0000000..68417b1 --- /dev/null +++ b/logs/storage/StdInvariant.sol:StdInvariant.log @@ -0,0 +1,9 @@ +lib/forge-std/src/StdInvariant.sol:StdInvariant:_excludedContracts (storage_slot: 0) (offset: 0) (type: address[]) (numberOfBytes: 32) +lib/forge-std/src/StdInvariant.sol:StdInvariant:_excludedSenders (storage_slot: 1) (offset: 0) (type: address[]) (numberOfBytes: 32) +lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedContracts (storage_slot: 2) (offset: 0) (type: address[]) (numberOfBytes: 32) +lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedSenders (storage_slot: 3) (offset: 0) (type: address[]) (numberOfBytes: 32) +lib/forge-std/src/StdInvariant.sol:StdInvariant:_excludedArtifacts (storage_slot: 4) (offset: 0) (type: string[]) (numberOfBytes: 32) +lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedArtifacts (storage_slot: 5) (offset: 0) (type: string[]) (numberOfBytes: 32) +lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedArtifactSelectors (storage_slot: 6) (offset: 0) (type: struct StdInvariant.FuzzSelector[]) (numberOfBytes: 32) +lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedSelectors (storage_slot: 7) (offset: 0) (type: struct StdInvariant.FuzzSelector[]) (numberOfBytes: 32) +lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedInterfaces (storage_slot: 8) (offset: 0) (type: struct StdInvariant.FuzzInterface[]) (numberOfBytes: 32) \ No newline at end of file diff --git a/logs/storage/test.sol:DSTest.log b/logs/storage/test.sol:DSTest.log new file mode 100644 index 0000000..2f26342 --- /dev/null +++ b/logs/storage/test.sol:DSTest.log @@ -0,0 +1,2 @@ +lib/forge-std/lib/ds-test/src/test.sol:DSTest:IS_TEST (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) +lib/forge-std/lib/ds-test/src/test.sol:DSTest:_failed (storage_slot: 0) (offset: 1) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/test.sol:Test.log b/logs/storage/test.sol:Test.log new file mode 100644 index 0000000..5f8eb82 --- /dev/null +++ b/logs/storage/test.sol:Test.log @@ -0,0 +1,18 @@ +lib/forge-std/src/Test.sol:Test:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) +lib/forge-std/src/Test.sol:Test:_failed (storage_slot: 8) (offset: 0) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/Test.sol:Test:stdChainsInitialized (storage_slot: 8) (offset: 1) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/Test.sol:Test:chains (storage_slot: 9) (offset: 0) (type: mapping(string => struct StdChains.Chain)) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:defaultRpcUrls (storage_slot: 10) (offset: 0) (type: mapping(string => string)) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:idToAlias (storage_slot: 11) (offset: 0) (type: mapping(uint256 => string)) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:fallbackToDefaultRpcUrls (storage_slot: 12) (offset: 0) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/Test.sol:Test:gasMeteringOff (storage_slot: 12) (offset: 1) (type: bool) (numberOfBytes: 1) +lib/forge-std/src/Test.sol:Test:stdstore (storage_slot: 13) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) +lib/forge-std/src/Test.sol:Test:_excludedContracts (storage_slot: 21) (offset: 0) (type: address[]) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:_excludedSenders (storage_slot: 22) (offset: 0) (type: address[]) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:_targetedContracts (storage_slot: 23) (offset: 0) (type: address[]) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:_targetedSenders (storage_slot: 24) (offset: 0) (type: address[]) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:_excludedArtifacts (storage_slot: 25) (offset: 0) (type: string[]) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:_targetedArtifacts (storage_slot: 26) (offset: 0) (type: string[]) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:_targetedArtifactSelectors (storage_slot: 27) (offset: 0) (type: struct StdInvariant.FuzzSelector[]) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:_targetedSelectors (storage_slot: 28) (offset: 0) (type: struct StdInvariant.FuzzSelector[]) (numberOfBytes: 32) +lib/forge-std/src/Test.sol:Test:_targetedInterfaces (storage_slot: 29) (offset: 0) (type: struct StdInvariant.FuzzInterface[]) (numberOfBytes: 32) \ No newline at end of file From e5a96dd8205d1e072fd5e6783a22957111779490 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:37:55 +0700 Subject: [PATCH 16/22] chore: update husky files --- .husky/generate-layout.sh | 8 ++--- .husky/pre-push | 4 +-- .husky/storage-logger.js | 67 +++++++++++++++++++++------------------ 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/.husky/generate-layout.sh b/.husky/generate-layout.sh index 8fc74d4..0e66916 100755 --- a/.husky/generate-layout.sh +++ b/.husky/generate-layout.sh @@ -3,12 +3,12 @@ rm -rf logs/storage/* dirOutputs=$(ls out | grep '^[^.]*\.sol$') # assuming the out dir is at 'out' while IFS= read -r contractDir; do - innerdirOutputs=$(ls out/$contractDir) + innerdirOutputs=$(ls out/"$contractDir") while IFS= read -r jsonFile; do - fileIn=out/$contractDir/$jsonFile - fileOut=logs/storage/$contractDir:${jsonFile%.json}.log - node .husky/storage-logger.js $fileIn $fileOut & + fileIn=out/"$contractDir"/$jsonFile + fileOut=logs/storage/"$contractDir":${jsonFile%.json}.log + node .husky/storage-logger.js "$fileIn" "$fileOut" & done <<< "$innerdirOutputs" done <<< "$dirOutputs" diff --git a/.husky/pre-push b/.husky/pre-push index 6397927..4a821d8 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -16,8 +16,8 @@ forge build --sizes 2>&1 | sed -n '/Contract/,$p' > logs/contract-code-sizes.log git add logs output=$(git status -s) -line_count=$(echo "$output" | wc -l) -if [ "$line_count" -gt 1 ]; then +word_count=$(echo "$output" | wc -w) +if [ "$word_count" -gt 0 ]; then git commit -m "chore: storage layout" fi diff --git a/.husky/storage-logger.js b/.husky/storage-logger.js index ec74913..d5a13df 100644 --- a/.husky/storage-logger.js +++ b/.husky/storage-logger.js @@ -3,44 +3,49 @@ const fileIn = process.argv[2]; const fileOut = process.argv[3]; if (!fileIn) { - console.error('Invalid input'); + console.error('Invalid input'); } fs.readFile(fileIn, 'utf8', (err, data) => { - if (err) { - console.error('Error reading file:', err); - return; + if (err) { + console.error('Error reading file:', err); + return; + } + + try { + const jsonData = JSON.parse(data); + if (typeof jsonData.storageLayout == 'undefined' || jsonData.ast.absolutePath == 'undefined') { + return; } - try { - const jsonData = JSON.parse(data); - if (typeof jsonData.storageLayout == 'undefined') { - return; - } + if (jsonData.storageLayout.storage.length == 0) { + return; + } - if (jsonData.storageLayout.storage.length == 0) { - return; - } + // Skip generating storage layout for files locate in the directory "src" + if (!jsonData.ast.absolutePath.startsWith('src')) { + return; + } - const outputData = jsonData.storageLayout.storage - .map(({ contract, label, offset, slot, type: typeId }) => { - const typeObj = jsonData.storageLayout.types[typeId]; - const typeLabel = typeObj.label; - const numberOfBytes = typeObj.numberOfBytes; - return `${contract}:${label} (storage_slot: ${slot}) (offset: ${offset}) (type: ${typeLabel}) (numberOfBytes: ${numberOfBytes})`; - }) - .join('\n'); - if (!fileOut) { - console.log(outputData); - } else { - fs.writeFile(fileOut, outputData, 'utf-8', err => { - if (err) { - console.error('Error writing file:', err); - return; - } - }); + const outputData = jsonData.storageLayout.storage + .map(({ contract, label, offset, slot, type: typeId }) => { + const typeObj = jsonData.storageLayout.types[typeId]; + const typeLabel = typeObj.label; + const numberOfBytes = typeObj.numberOfBytes; + return `${contract}:${label} (storage_slot: ${slot}) (offset: ${offset}) (type: ${typeLabel}) (numberOfBytes: ${numberOfBytes})`; + }) + .join('\n'); + if (!fileOut) { + console.log(outputData); + } else { + fs.writeFile(fileOut, outputData, 'utf-8', err => { + if (err) { + console.error('Error writing file:', err); + return; } - } catch (err) { - console.error('Error parsing JSON:', err); + }); } + } catch (err) { + console.error('Error parsing JSON:', err); + } }); \ No newline at end of file From 2e19e0e82805e923c68980aa245937f525c8600c Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:38:01 +0700 Subject: [PATCH 17/22] chore: storage layout --- logs/storage/Base.sol:CommonBase.log | 1 - logs/storage/Base.sol:ScriptBase.log | 1 - logs/storage/Base.sol:TestBase.log | 1 - logs/storage/MockERC20.sol:MockERC20.log | 10 ---------- logs/storage/MockERC721.sol:MockERC721.log | 7 ------- logs/storage/Script.sol:Script.log | 8 -------- .../StdAssertions.sol:StdAssertions.log | 1 - logs/storage/StdChains.sol:StdChains.log | 5 ----- logs/storage/StdCheats.sol:StdCheats.log | 2 -- logs/storage/StdCheats.sol:StdCheatsSafe.log | 1 - logs/storage/StdInvariant.sol:StdInvariant.log | 9 --------- logs/storage/test.sol:DSTest.log | 2 -- logs/storage/test.sol:Test.log | 18 ------------------ 13 files changed, 66 deletions(-) delete mode 100644 logs/storage/Base.sol:CommonBase.log delete mode 100644 logs/storage/Base.sol:ScriptBase.log delete mode 100644 logs/storage/Base.sol:TestBase.log delete mode 100644 logs/storage/MockERC20.sol:MockERC20.log delete mode 100644 logs/storage/MockERC721.sol:MockERC721.log delete mode 100644 logs/storage/Script.sol:Script.log delete mode 100644 logs/storage/StdAssertions.sol:StdAssertions.log delete mode 100644 logs/storage/StdChains.sol:StdChains.log delete mode 100644 logs/storage/StdCheats.sol:StdCheats.log delete mode 100644 logs/storage/StdCheats.sol:StdCheatsSafe.log delete mode 100644 logs/storage/StdInvariant.sol:StdInvariant.log delete mode 100644 logs/storage/test.sol:DSTest.log delete mode 100644 logs/storage/test.sol:Test.log diff --git a/logs/storage/Base.sol:CommonBase.log b/logs/storage/Base.sol:CommonBase.log deleted file mode 100644 index 0060c1c..0000000 --- a/logs/storage/Base.sol:CommonBase.log +++ /dev/null @@ -1 +0,0 @@ -lib/forge-std/src/Base.sol:CommonBase:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) \ No newline at end of file diff --git a/logs/storage/Base.sol:ScriptBase.log b/logs/storage/Base.sol:ScriptBase.log deleted file mode 100644 index 7884c93..0000000 --- a/logs/storage/Base.sol:ScriptBase.log +++ /dev/null @@ -1 +0,0 @@ -lib/forge-std/src/Base.sol:ScriptBase:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) \ No newline at end of file diff --git a/logs/storage/Base.sol:TestBase.log b/logs/storage/Base.sol:TestBase.log deleted file mode 100644 index 2a0f2c1..0000000 --- a/logs/storage/Base.sol:TestBase.log +++ /dev/null @@ -1 +0,0 @@ -lib/forge-std/src/Base.sol:TestBase:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) \ No newline at end of file diff --git a/logs/storage/MockERC20.sol:MockERC20.log b/logs/storage/MockERC20.sol:MockERC20.log deleted file mode 100644 index b5e16f5..0000000 --- a/logs/storage/MockERC20.sol:MockERC20.log +++ /dev/null @@ -1,10 +0,0 @@ -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_name (storage_slot: 0) (offset: 0) (type: string) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_symbol (storage_slot: 1) (offset: 0) (type: string) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_decimals (storage_slot: 2) (offset: 0) (type: uint8) (numberOfBytes: 1) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_totalSupply (storage_slot: 3) (offset: 0) (type: uint256) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_balanceOf (storage_slot: 4) (offset: 0) (type: mapping(address => uint256)) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:_allowance (storage_slot: 5) (offset: 0) (type: mapping(address => mapping(address => uint256))) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:INITIAL_CHAIN_ID (storage_slot: 6) (offset: 0) (type: uint256) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:INITIAL_DOMAIN_SEPARATOR (storage_slot: 7) (offset: 0) (type: bytes32) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:nonces (storage_slot: 8) (offset: 0) (type: mapping(address => uint256)) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC20.sol:MockERC20:initialized (storage_slot: 9) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/MockERC721.sol:MockERC721.log b/logs/storage/MockERC721.sol:MockERC721.log deleted file mode 100644 index 9dfd98d..0000000 --- a/logs/storage/MockERC721.sol:MockERC721.log +++ /dev/null @@ -1,7 +0,0 @@ -lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_name (storage_slot: 0) (offset: 0) (type: string) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_symbol (storage_slot: 1) (offset: 0) (type: string) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_ownerOf (storage_slot: 2) (offset: 0) (type: mapping(uint256 => address)) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_balanceOf (storage_slot: 3) (offset: 0) (type: mapping(address => uint256)) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_getApproved (storage_slot: 4) (offset: 0) (type: mapping(uint256 => address)) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC721.sol:MockERC721:_isApprovedForAll (storage_slot: 5) (offset: 0) (type: mapping(address => mapping(address => bool))) (numberOfBytes: 32) -lib/forge-std/src/mocks/MockERC721.sol:MockERC721:initialized (storage_slot: 6) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/Script.sol:Script.log b/logs/storage/Script.sol:Script.log deleted file mode 100644 index 2ec2cf0..0000000 --- a/logs/storage/Script.sol:Script.log +++ /dev/null @@ -1,8 +0,0 @@ -lib/forge-std/src/Script.sol:Script:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 224) -lib/forge-std/src/Script.sol:Script:stdChainsInitialized (storage_slot: 7) (offset: 0) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/Script.sol:Script:chains (storage_slot: 8) (offset: 0) (type: mapping(string => struct StdChains.Chain)) (numberOfBytes: 32) -lib/forge-std/src/Script.sol:Script:defaultRpcUrls (storage_slot: 9) (offset: 0) (type: mapping(string => string)) (numberOfBytes: 32) -lib/forge-std/src/Script.sol:Script:idToAlias (storage_slot: 10) (offset: 0) (type: mapping(uint256 => string)) (numberOfBytes: 32) -lib/forge-std/src/Script.sol:Script:fallbackToDefaultRpcUrls (storage_slot: 11) (offset: 0) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/Script.sol:Script:gasMeteringOff (storage_slot: 11) (offset: 1) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/Script.sol:Script:IS_SCRIPT (storage_slot: 11) (offset: 2) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/StdAssertions.sol:StdAssertions.log b/logs/storage/StdAssertions.sol:StdAssertions.log deleted file mode 100644 index 4ee60ec..0000000 --- a/logs/storage/StdAssertions.sol:StdAssertions.log +++ /dev/null @@ -1 +0,0 @@ -lib/forge-std/src/StdAssertions.sol:StdAssertions:_failed (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/StdChains.sol:StdChains.log b/logs/storage/StdChains.sol:StdChains.log deleted file mode 100644 index e38d8f5..0000000 --- a/logs/storage/StdChains.sol:StdChains.log +++ /dev/null @@ -1,5 +0,0 @@ -lib/forge-std/src/StdChains.sol:StdChains:stdChainsInitialized (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/StdChains.sol:StdChains:chains (storage_slot: 1) (offset: 0) (type: mapping(string => struct StdChains.Chain)) (numberOfBytes: 32) -lib/forge-std/src/StdChains.sol:StdChains:defaultRpcUrls (storage_slot: 2) (offset: 0) (type: mapping(string => string)) (numberOfBytes: 32) -lib/forge-std/src/StdChains.sol:StdChains:idToAlias (storage_slot: 3) (offset: 0) (type: mapping(uint256 => string)) (numberOfBytes: 32) -lib/forge-std/src/StdChains.sol:StdChains:fallbackToDefaultRpcUrls (storage_slot: 4) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/StdCheats.sol:StdCheats.log b/logs/storage/StdCheats.sol:StdCheats.log deleted file mode 100644 index fcbd9e8..0000000 --- a/logs/storage/StdCheats.sol:StdCheats.log +++ /dev/null @@ -1,2 +0,0 @@ -lib/forge-std/src/StdCheats.sol:StdCheats:gasMeteringOff (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/StdCheats.sol:StdCheats:stdstore (storage_slot: 1) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) \ No newline at end of file diff --git a/logs/storage/StdCheats.sol:StdCheatsSafe.log b/logs/storage/StdCheats.sol:StdCheatsSafe.log deleted file mode 100644 index 372cbe1..0000000 --- a/logs/storage/StdCheats.sol:StdCheatsSafe.log +++ /dev/null @@ -1 +0,0 @@ -lib/forge-std/src/StdCheats.sol:StdCheatsSafe:gasMeteringOff (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/StdInvariant.sol:StdInvariant.log b/logs/storage/StdInvariant.sol:StdInvariant.log deleted file mode 100644 index 68417b1..0000000 --- a/logs/storage/StdInvariant.sol:StdInvariant.log +++ /dev/null @@ -1,9 +0,0 @@ -lib/forge-std/src/StdInvariant.sol:StdInvariant:_excludedContracts (storage_slot: 0) (offset: 0) (type: address[]) (numberOfBytes: 32) -lib/forge-std/src/StdInvariant.sol:StdInvariant:_excludedSenders (storage_slot: 1) (offset: 0) (type: address[]) (numberOfBytes: 32) -lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedContracts (storage_slot: 2) (offset: 0) (type: address[]) (numberOfBytes: 32) -lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedSenders (storage_slot: 3) (offset: 0) (type: address[]) (numberOfBytes: 32) -lib/forge-std/src/StdInvariant.sol:StdInvariant:_excludedArtifacts (storage_slot: 4) (offset: 0) (type: string[]) (numberOfBytes: 32) -lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedArtifacts (storage_slot: 5) (offset: 0) (type: string[]) (numberOfBytes: 32) -lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedArtifactSelectors (storage_slot: 6) (offset: 0) (type: struct StdInvariant.FuzzSelector[]) (numberOfBytes: 32) -lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedSelectors (storage_slot: 7) (offset: 0) (type: struct StdInvariant.FuzzSelector[]) (numberOfBytes: 32) -lib/forge-std/src/StdInvariant.sol:StdInvariant:_targetedInterfaces (storage_slot: 8) (offset: 0) (type: struct StdInvariant.FuzzInterface[]) (numberOfBytes: 32) \ No newline at end of file diff --git a/logs/storage/test.sol:DSTest.log b/logs/storage/test.sol:DSTest.log deleted file mode 100644 index 2f26342..0000000 --- a/logs/storage/test.sol:DSTest.log +++ /dev/null @@ -1,2 +0,0 @@ -lib/forge-std/lib/ds-test/src/test.sol:DSTest:IS_TEST (storage_slot: 0) (offset: 0) (type: bool) (numberOfBytes: 1) -lib/forge-std/lib/ds-test/src/test.sol:DSTest:_failed (storage_slot: 0) (offset: 1) (type: bool) (numberOfBytes: 1) \ No newline at end of file diff --git a/logs/storage/test.sol:Test.log b/logs/storage/test.sol:Test.log deleted file mode 100644 index 5f8eb82..0000000 --- a/logs/storage/test.sol:Test.log +++ /dev/null @@ -1,18 +0,0 @@ -lib/forge-std/src/Test.sol:Test:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) -lib/forge-std/src/Test.sol:Test:_failed (storage_slot: 8) (offset: 0) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/Test.sol:Test:stdChainsInitialized (storage_slot: 8) (offset: 1) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/Test.sol:Test:chains (storage_slot: 9) (offset: 0) (type: mapping(string => struct StdChains.Chain)) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:defaultRpcUrls (storage_slot: 10) (offset: 0) (type: mapping(string => string)) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:idToAlias (storage_slot: 11) (offset: 0) (type: mapping(uint256 => string)) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:fallbackToDefaultRpcUrls (storage_slot: 12) (offset: 0) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/Test.sol:Test:gasMeteringOff (storage_slot: 12) (offset: 1) (type: bool) (numberOfBytes: 1) -lib/forge-std/src/Test.sol:Test:stdstore (storage_slot: 13) (offset: 0) (type: struct StdStorage) (numberOfBytes: 256) -lib/forge-std/src/Test.sol:Test:_excludedContracts (storage_slot: 21) (offset: 0) (type: address[]) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:_excludedSenders (storage_slot: 22) (offset: 0) (type: address[]) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:_targetedContracts (storage_slot: 23) (offset: 0) (type: address[]) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:_targetedSenders (storage_slot: 24) (offset: 0) (type: address[]) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:_excludedArtifacts (storage_slot: 25) (offset: 0) (type: string[]) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:_targetedArtifacts (storage_slot: 26) (offset: 0) (type: string[]) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:_targetedArtifactSelectors (storage_slot: 27) (offset: 0) (type: struct StdInvariant.FuzzSelector[]) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:_targetedSelectors (storage_slot: 28) (offset: 0) (type: struct StdInvariant.FuzzSelector[]) (numberOfBytes: 32) -lib/forge-std/src/Test.sol:Test:_targetedInterfaces (storage_slot: 29) (offset: 0) (type: struct StdInvariant.FuzzInterface[]) (numberOfBytes: 32) \ No newline at end of file From ba93be9dba701795ebdb329d5b6dfca4b5cdaac8 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:39:48 +0700 Subject: [PATCH 18/22] ci: bump create pull request package version --- .github/workflows/create-PR-implement.yml | 2 +- .github/workflows/create-PR-release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-PR-implement.yml b/.github/workflows/create-PR-implement.yml index 33d00a5..85cbbd6 100644 --- a/.github/workflows/create-PR-implement.yml +++ b/.github/workflows/create-PR-implement.yml @@ -41,7 +41,7 @@ jobs: toBranch: ${{ env.FEATURE_BRANCH }} - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6.0.1 with: branch: ${{ env.HEAD_BRANCH }} base: ${{env.FEATURE_BRANCH}} diff --git a/.github/workflows/create-PR-release.yml b/.github/workflows/create-PR-release.yml index 87944c6..b9dec20 100644 --- a/.github/workflows/create-PR-release.yml +++ b/.github/workflows/create-PR-release.yml @@ -75,7 +75,7 @@ jobs: toBranch: ${{matrix.branch_name}} - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6.0.1 with: labels: automated PR delete-branch: true From 68388fc2ab8a79ddeb58e4128df941b183084912 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 14 Mar 2024 11:42:36 +0700 Subject: [PATCH 19/22] ci: bump create pull request package version --- .../workflows/create-PR-deploy-to-release.yml | 62 ++++++++++++++++++ ...yml => create-PR-implement-to-feature.yml} | 0 ...e.yml => create-PR-release-to-feature.yml} | 0 .../create-PR-release-to-network.yml | 47 ++++++++++++++ .github/workflows/create-release-tag.yml | 64 +++++++++++++++++++ 5 files changed, 173 insertions(+) create mode 100644 .github/workflows/create-PR-deploy-to-release.yml rename .github/workflows/{create-PR-implement.yml => create-PR-implement-to-feature.yml} (100%) rename .github/workflows/{create-PR-release.yml => create-PR-release-to-feature.yml} (100%) create mode 100644 .github/workflows/create-PR-release-to-network.yml create mode 100644 .github/workflows/create-release-tag.yml diff --git a/.github/workflows/create-PR-deploy-to-release.yml b/.github/workflows/create-PR-deploy-to-release.yml new file mode 100644 index 0000000..23eccf8 --- /dev/null +++ b/.github/workflows/create-PR-deploy-to-release.yml @@ -0,0 +1,62 @@ +name: Create PR Deploy to Release + +on: + push: + branches: + - deploy/* + pull_request: + branches: + - deploy/* + +env: + HEAD_BRANCH: ${{ github.head_ref || github.ref_name }} + +permissions: + contents: write + pull-requests: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Set Env + run: | + echo "PR_BRANCH=merge/${HEAD_BRANCH}" >> $GITHUB_ENV + echo "VERSION=$(echo -n ${{ env.HEAD_BRANCH }} | sed 's/.*deploy\///' | cut -d'-' -f1)" >> $GITHUB_ENV + echo "NETWORK=$(echo -n ${{ env.HEAD_BRANCH }} | sed 's/.*deploy\/v[0-9\.]*-\(.*\)/\1/')" >> $GITHUB_ENV + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: 'release/${{ env.VERSION }}' + fetch-depth: 0 + fetch-tags: 'true' + + - name: Get Testnet Latest Tag + if: ${{ env.NETWORK == 'testnet' }} + run: | + echo "LATESTTAG=$(git describe --tags --match "*testnet*" --abbrev=0)" >> $GITHUB_ENV + + - name: Get Mainnet Latest Tag + if: ${{ env.NETWORK == 'mainnet' }} + run: | + echo "LATESTTAG=$(git describe --tags --match "*mainnet*" --abbrev=0)" >> $GITHUB_ENV + + - name: Reset promotion branch + run: | + git fetch origin ${HEAD_BRANCH}:${HEAD_BRANCH} + git reset --hard ${HEAD_BRANCH} + + - name: Generate Release note + id: template + run: | + echo "VERSION=${{ env.VERSION }} - SHA: ${{ github.sha }}" > CHANGELOG.md + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v6.0.1 + with: + labels: automated PR + delete-branch: true + title: 'chore(`release/${{ env.VERSION }}`): merge from `${{ env.HEAD_BRANCH}}`' + body: ${{ steps.template.outputs.result }} + branch: ${{ env.PR_BRANCH }} diff --git a/.github/workflows/create-PR-implement.yml b/.github/workflows/create-PR-implement-to-feature.yml similarity index 100% rename from .github/workflows/create-PR-implement.yml rename to .github/workflows/create-PR-implement-to-feature.yml diff --git a/.github/workflows/create-PR-release.yml b/.github/workflows/create-PR-release-to-feature.yml similarity index 100% rename from .github/workflows/create-PR-release.yml rename to .github/workflows/create-PR-release-to-feature.yml diff --git a/.github/workflows/create-PR-release-to-network.yml b/.github/workflows/create-PR-release-to-network.yml new file mode 100644 index 0000000..7484518 --- /dev/null +++ b/.github/workflows/create-PR-release-to-network.yml @@ -0,0 +1,47 @@ +name: Create PR from release to network + +on: + pull_request: + branches: + - release/* + types: + - closed + +permissions: + contents: write + pull-requests: write + +env: + HEAD_BRANCH: ${{ github.head_ref || github.ref_name }} + RELEASE_BRANCH: ${{ github.event.pull_request.base.ref}} + +jobs: + merge-release-to-network: + runs-on: ubuntu-latest + if: ${{ (github.event.pull_request.merged == true) && (contains(github.head_ref, 'deploy') || contains(github.ref_name, 'deploy')) }} + steps: + - name: Set Env + run: | + echo "PR_BRANCH=merge/${HEAD_BRANCH}" >> $GITHUB_ENV + echo "VERSION=$(echo -n ${{ env.HEAD_BRANCH }} | sed 's/.*deploy\///' | cut -d'-' -f1)" >> $GITHUB_ENV + echo "NETWORK=$(echo -n ${{ env.HEAD_BRANCH }} | sed 's/.*deploy\/v[0-9\.]*-\(.*\)/\1/')" >> $GITHUB_ENV + + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ env.NETWORK }} + + - name: Reset promotion branch + run: | + git fetch origin ${RELEASE_BRANCH}:${RELEASE_BRANCH} + git reset --hard ${RELEASE_BRANCH} + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v6.0.1 + with: + labels: automated PR + delete-branch: true + title: 'chore(`${{ env.NETWORK }}`): merge from `${{ env.HEAD_BRANCH}}`' + body: ${{ steps.template.outputs.result }} + branch: ${{env.PR_BRANCH}} diff --git a/.github/workflows/create-release-tag.yml b/.github/workflows/create-release-tag.yml new file mode 100644 index 0000000..f8ede5b --- /dev/null +++ b/.github/workflows/create-release-tag.yml @@ -0,0 +1,64 @@ +name: Create Release Tag + +on: + pull_request: + types: [closed] + branches: + - mainnet + - testnet + +env: + HEAD_BRANCH: ${{ github.head_ref || github.ref_name }} + +permissions: + contents: write + pull-requests: write + +jobs: + create-release-tag: + runs-on: ubuntu-latest + if: github.event.pull_request.merged == true + steps: + - name: Set Env + run: | + echo "VERSION=$(echo -n ${{ env.HEAD_BRANCH }} | sed 's/.*deploy\///' | cut -d'-' -f1)" >> $GITHUB_ENV + echo "NETWORK=$(echo -n ${{ env.HEAD_BRANCH }} | sed 's/.*deploy\/v[0-9\.]*-\(.*\)/\1/')" >> $GITHUB_ENV + + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ env.NETWORK }} + fetch-depth: 0 + fetch-tags: 'true' + + - name: Set Mainnet Tag + if: ${{ env.NETWORK == 'mainnet' }} + run: | + echo "TAG=${{ env.VERSION }}" >> $GITHUB_ENV + + - name: Set Testnet Tag + if: ${{ env.NETWORK == 'testnet' }} + run: | + echo "TAG=${{ env.VERSION }}-testnet" >> $GITHUB_ENV + + - name: Get Testnet Latest Tag + if: ${{ env.NETWORK == 'testnet' }} + run: | + echo "LATESTTAG=$(git describe --tags --match "*testnet*" --abbrev=0)" >> $GITHUB_ENV + + - name: Get Mainnet Latest Tag + if: ${{ env.NETWORK == 'mainnet' }} + run: | + echo "LATESTTAG=$(git describe --tags --match "*mainnet*" --abbrev=0)" >> $GITHUB_ENV + + - name: Create release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ env.TAG }} + run: | + gh release create "$tag" \ + --repo "$GITHUB_REPOSITORY" \ + --title "${{ env.NETWORK }} release ${{ env.VERSION }}" \ + --target "${{ env.NETWORK }}" \ + --notes-start-tag "${{ env.LATESTTAG }}" \ + --generate-notes From b7f66edfb8eaf17be378f168e58487f44ab6aa04 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 19 Mar 2024 11:20:28 +0700 Subject: [PATCH 20/22] feat: remove send zero checks --- .../transfers/RONTransferHelperExtended.sol | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/src/legacy/transfers/RONTransferHelperExtended.sol b/src/legacy/transfers/RONTransferHelperExtended.sol index 08d31c3..51ef344 100644 --- a/src/legacy/transfers/RONTransferHelperExtended.sol +++ b/src/legacy/transfers/RONTransferHelperExtended.sol @@ -20,12 +20,9 @@ library RONTransferHelperExtended { */ 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; - } + wron.withdraw(amount); + RONTransferHelper.safeTransfer(to, amount); + return; } TransferHelper.safeTransfer(token, to, amount); @@ -48,12 +45,9 @@ library RONTransferHelperExtended { 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; - } + wron.approve(address(wronHelper), amount); + wronHelper.withdrawTo(to, amount); + return; } TransferHelper.safeTransfer(token, to, amount); @@ -74,13 +68,10 @@ library RONTransferHelperExtended { 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, address(this), amount); + IWRON(wron).withdraw(amount); + RONTransferHelper.safeTransfer(to, amount); + return; } TransferFromHelper.safeTransferFrom(token, from, to, amount); @@ -104,13 +95,10 @@ library RONTransferHelperExtended { 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, address(this), amount); + wron.approve(address(wronHelper), amount); + wronHelper.withdrawTo(to, amount); + return; } TransferFromHelper.safeTransferFrom(token, from, to, amount); From 27aee4a4813bf546fb1e71153285923ce6b97b24 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Tue, 21 May 2024 14:58:45 +0700 Subject: [PATCH 21/22] feat(LibEventRange): add LibEventRange --- src/LibEventRange.sol | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/LibEventRange.sol diff --git a/src/LibEventRange.sol b/src/LibEventRange.sol new file mode 100644 index 0000000..08decea --- /dev/null +++ b/src/LibEventRange.sol @@ -0,0 +1,42 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +struct EventRange { + // uint40 is enough to represent the timestamp until year 36812 + uint40 startedAt; + uint40 endedAt; + /// @dev Reserved space for future upgrades + uint176 __reserved; +} + +using LibEventRange for EventRange global; + +library LibEventRange { + /** + * @dev Checks whether the event range is valid. + */ + function valid(EventRange memory range) internal pure returns (bool) { + return range.startedAt <= range.endedAt; + } + + /** + * @dev Returns whether the current range is not yet started. + */ + function isNotYetStarted(EventRange memory range) internal view returns (bool) { + return block.timestamp < range.startedAt; + } + + /** + * @dev Returns whether the current range is ended or not. + */ + function isEnded(EventRange memory range) internal view returns (bool) { + return range.endedAt <= block.timestamp; + } + + /** + * @dev Returns whether the current block is in period. + */ + function isInPeriod(EventRange memory range) internal view returns (bool) { + return range.startedAt <= block.timestamp && block.timestamp < range.endedAt; + } +} From d9d7ddbc1c39ac1f71424e66b13003225ae6bf5e Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Tue, 21 May 2024 14:58:54 +0700 Subject: [PATCH 22/22] chore: storage layout --- logs/contract-code-sizes.log | 41 +++++++++++++----------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/logs/contract-code-sizes.log b/logs/contract-code-sizes.log index f906e69..8225747 100644 --- a/logs/contract-code-sizes.log +++ b/logs/contract-code-sizes.log @@ -1,27 +1,16 @@ -| Contract | Size (kB) | Margin (kB) | -|---------------------------|-----------|-------------| -| LibErrorHandler | 0.086 | 24.49 | -| LibNativeTransfer | 0.086 | 24.49 | -| LibSafeRange | 0.086 | 24.49 | -| Math | 0.086 | 24.49 | -| MockERC20 | 3.704 | 20.872 | -| MockERC721 | 3.964 | 20.612 | -| Panic | 0.086 | 24.49 | -| RONTransferHelper | 0.086 | 24.49 | -| RONTransferHelperExtended | 0.086 | 24.49 | -| SafeCast | 0.086 | 24.49 | -| SignedMath | 0.086 | 24.49 | -| StdStyle | 0.086 | 24.49 | -| Strings | 0.086 | 24.49 | -| TransferFromHelper | 0.086 | 24.49 | -| TransferHelper | 0.086 | 24.49 | -| console | 0.086 | 24.49 | -| console2 | 0.086 | 24.49 | -| safeconsole | 0.086 | 24.49 | -| stdError | 0.592 | 23.984 | -| stdJson | 0.086 | 24.49 | -| stdMath | 0.086 | 24.49 | -| stdStorage | 0.086 | 24.49 | -| stdStorageSafe | 0.086 | 24.49 | -| stdToml | 0.086 | 24.49 | +| Contract | Size (B) | Margin (B) | +|---------------------------|----------|------------| +| LibErrorHandler | 86 | 24,490 | +| LibEventRange | 86 | 24,490 | +| LibNativeTransfer | 86 | 24,490 | +| LibSafeRange | 86 | 24,490 | +| Math | 86 | 24,490 | +| Panic | 86 | 24,490 | +| RONTransferHelper | 86 | 24,490 | +| RONTransferHelperExtended | 86 | 24,490 | +| SafeCast | 86 | 24,490 | +| SignedMath | 86 | 24,490 | +| Strings | 86 | 24,490 | +| TransferFromHelper | 86 | 24,490 | +| TransferHelper | 86 | 24,490 |