Last active
March 27, 2022 18:18
-
-
Save irzhywau/b1257353a2dabbf3504043d2cb52038f to your computer and use it in GitHub Desktop.
wrap/unwrap token inside of a contract
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity >=0.6.12; | |
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "./IERC20Wrappable.sol"; | |
contract ERC20WrappableSupport { | |
modifier withWrap(address payable wToken) { | |
require(_bundleWrap(wToken), "failed to wrap"); | |
_; | |
} | |
modifier withUnwrap(address payable wToken, uint256 amount) { | |
_; | |
_unwrap(wToken, amount); | |
} | |
modifier _underlyingTokenRequired(address payable wToken) { | |
require(wToken != address(0), "underlying token not set"); | |
_; | |
} | |
/// @dev execute wrap transaction along the process and transfer wETH into original msg.sender account | |
function _bundleWrap(address payable wToken) | |
internal | |
_underlyingTokenRequired(wToken) | |
returns (bool) | |
{ | |
// Note: | |
// There exists a special variant of a message `call`, | |
// named `delegatecall` which is identical to a message call | |
// apart from the fact that the code at the target address | |
// is executed in the context of the calling contract | |
// and msg.sender and msg.value do not change their values. | |
(bool deposited, ) = wToken.call{value: msg.value}( | |
abi.encodeWithSignature("deposit()") | |
); | |
require(deposited, "failed to deposit"); | |
IERC20(wToken).transferFrom(address(this), msg.sender, msg.value); | |
// @todo: figure out how to bundle this in this method | |
// (bool approved, ) = wToken.delegatecall( | |
// abi.encodeWithSignature("approve(address,uint256)", this, amount) | |
// ); | |
// require(approved, "failed to approve"); | |
return true; | |
} | |
function _unwrap(address payable wToken, uint256 wad) | |
internal | |
_underlyingTokenRequired(wToken) | |
returns (bool) | |
{ | |
// this statement needs an approval in prior | |
// transfer fund from user account to the current contract | |
require( | |
IERC20(wToken).transferFrom(msg.sender, address(this), wad), | |
"wERC20: failed to transfer to calling contract" | |
); | |
// here we will withdraw transfered wETH in the contract to ETH | |
// then transfer it again to the recipient (msg.sender) | |
// execution operated by this contract | |
IERC20Wrappable(wToken).withdraw(wad); | |
(bool withdrawn, ) = msg.sender.call{value: wad}(""); | |
return withdrawn; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity >=0.6.12; | |
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
interface IERC20Wrappable is IERC20 { | |
function deposit() external payable; | |
function withdraw(uint256 wad) external; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity >=0.6.12; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "../library/ERC20WrappableSupport.sol"; | |
contract TestWrap is Ownable, ERC20WrappableSupport { | |
address payable public wToken; | |
function pay() external payable { | |
require(_bundleWrap(wToken), "failed to bundle actions"); | |
} | |
function refundMe(uint256 amount) external { | |
require(_unwrap(wToken, amount), "failed to withdraw"); | |
} | |
function setWToken(address _wToken) public onlyOwner { | |
wToken = payable(_wToken); | |
} | |
} |
receive() external payable {
_fallback();
}
This function means that the contract can recieve ether from ourside contract or account.
If there is no such function, we can't recieve ether from outside.
got it.
thank you @alexlu0917 your help just unlocked me from a week of struggle
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you so much for your help,
finally the issue was rather about the contract that implement
ERC20WrappableSupport
it needed afallback
andreceive
functionsby adding both, everything seemed ok
but still, I'm not really sure to understand what will be the effect of that
I just added below in
TestWrap