ERC20Wrapper.sol 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "../ERC20.sol";
  4. import "../utils/SafeERC20.sol";
  5. /**
  6. * @dev Extension of the ERC20 token contract to support token wrapping.
  7. *
  8. * Users can deposit and withdraw "underlying tokens" and receive a matching number of "wrapped tokens". This is useful
  9. * in conjunction with other modules. For example, combining this wrapping mechanism with {ERC20Votes} will allow the
  10. * wrapping of an existing "basic" ERC20 into a governance token.
  11. *
  12. * _Available since v4.2._
  13. */
  14. abstract contract ERC20Wrapper is ERC20 {
  15. IERC20 public immutable underlying;
  16. constructor(IERC20 underlyingToken) {
  17. underlying = underlyingToken;
  18. }
  19. /**
  20. * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.
  21. */
  22. function depositFor(address account, uint256 amount) public virtual returns (bool) {
  23. SafeERC20.safeTransferFrom(underlying, _msgSender(), address(this), amount);
  24. _mint(account, amount);
  25. return true;
  26. }
  27. /**
  28. * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.
  29. */
  30. function withdrawTo(address account, uint256 amount) public virtual returns (bool) {
  31. _burn(_msgSender(), amount);
  32. SafeERC20.safeTransfer(underlying, account, amount);
  33. return true;
  34. }
  35. /**
  36. * @dev Mint wrapped token to cover any underlyingTokens that would have been transfered by mistake. Internal
  37. * function that can be exposed with access control if desired.
  38. */
  39. function _recover(address account) internal virtual returns (uint256) {
  40. uint256 value = underlying.balanceOf(address(this)) - totalSupply();
  41. _mint(account, value);
  42. return value;
  43. }
  44. }