# ERC20 Wrapper tutorial

**URL:** <https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536>\
**Category:** Guides and Tutorials\
**Tags:** erc20, tutorial, wrappedtoken\
**Created:** [January 27, 2022, 8:50pm UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536 "2022-01-27T20:50:53Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![JulissaDantes](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/julissadantes/32/15410_2.png) [@JulissaDantes](https://forum.openzeppelin.com/u/JulissaDantes)\
**Post date:** [January 27, 2022, 8:50pm UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/1 "2022-01-27T20:50:54Z")

</div>

In this tutorial we are going learn how to create a wrapped token using the [ERC20Wrapper](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Wrapper.sol) contract provided by OpenZeppelin, but first let's get familiar with what a wrapped token is.

**Introduction to wrapped tokens**

A wrapped token is a token whose value is tied to an underlying cryptocurrency. An amount of the original token is locked in a digital vault, and in return this allows an equivalent amount of wrapped tokens to be minted.

This is useful for several reasons, to mention a few:

- To extend the functionalities of an existing token in conjunction with other ERC20 modules.
- Allow a native cryptocurrency to behave like an ERC20, e.g. Wrapped ether (WETH).
- Allow the use of currencies outside its native blockchain, e.g. Wrapped bitcoin (WBTC).

This OpenZeppelin contract covers the first case: underlying ERC20 tokens on the same chain can be wrapped and thus virtually extended with new functionality. For this tutorial we are implementing a wrapped token that enables voting in a governance protocol with a token that was not originally designed for this purpose.

**Let’s start!**  
We’ll assume a project X was launched with its own token, a non upgradable ERC20 contract, but some time after the launch they found themselves in need of on chain governance. For said purpose they would need to deploy a governance system through a `Governor` contract that will look something like this:

```auto
contract MyGovernor is Governor, GovernorSettings, GovernorCountingSimple, GovernorVotes, GovernorVotesQuorumFraction, GovernorTimelockControl {
    constructor(ERC20Votes _token, TimelockController _timelock)
        Governor("MyGovernor")
        GovernorSettings(1 /* 1 block */, 45818 /* 1 week */, 0)
        GovernorVotes(_token)
        GovernorVotesQuorumFraction(4)
        GovernorTimelockControl(_timelock)
    {}
 
    // ...
}

```

For more information on how to set an on chain governance please take a look at [this guide](https://docs.openzeppelin.com/contracts/4.x/governance).

As you might have noticed it uses an `ERC20Votes` type of token to perform all its operations, and the launched token was just a non upgradeable ERC20, therefore not compatible with the governance needs. The solution to their predicament is fairly simple, let's wrap the existing token adding the ERC20Votes module.

First we will inherit from the contracts `ERC20Wrapper` and `ERC20Votes`:

```auto
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Wrapper.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
 
contract VotesWrapper is ERC20, ERC20Wrapper, ERC20Votes {

```

ERC20Wrapper takes a parameter for the original token that we want to wrap. We would use the previously launched token address as this parameter. And we’ll setvalues for all the other required parameters, notice that we have to include `ERC20Permit` constructor call because it is a parent for our wrapped token parent `ERC20Votes`:

```
constructor(IERC20 wrappedToken)
   ERC20("Wrapped Token", "wTKN")
   ERC20Permit("Wrapped Token")
   ERC20Wrapper(wrappedToken)
{}

```

Note that the compiler requires writing some overrides.

> **Click here to see the full code**
>
> ```auto
> 
> import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Wrapper.sol";
> import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
>  
> contract VotesWrapper is ERC20, ERC20Wrapper, ERC20Votes{
> constructor(IERC20 wrappedToken)
> ERC20("Wrapped Token", "wTKN")
> ERC20Permit("Wrapped Token")
> ERC20Wrapper(wrappedToken)
> {}
>     
> function _afterTokenTransfer(address from, address to, uint256 amount)
> internal
> override(ERC20, ERC20Votes)
> {
> super._afterTokenTransfer(from, to, amount);
> }
>  
> function _mint(address to, uint256 amount)
> internal
> override(ERC20, ERC20Votes)
> {
> super._mint(to, amount);
> }
>  
> function _burn(address account, uint256 amount)
> internal
> override(ERC20, ERC20Votes)
> {
> super._burn(account, amount);
> }
> 
> ```

Now you can use your wrapped token to execute any voting operations, by deploying the wrapped token first, and then deploying the Governor contract configured with the wrapped token as its voting token.

In order to vote for governance proposals, token holders must first use the wrapped token’s method `depositFor` to get voting tokens 1-to-1 for the tokens they already hold.

After there are some locked tokens on the wrapped token’s contract, or in other words after there are some wrapped tokens minted, you can start using the `Governor` contract as if you were using your token as a voting token.

---

<div class="post-metadata">

**Author:** ![DeFiSon](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/defison/32/15198_2.png) [@DeFiSon](https://forum.openzeppelin.com/u/DeFiSon)\
**Post date:** [June 3, 2022, 6:19pm UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/2 "2022-06-03T18:19:04Z")

</div>

Hi there. Complete beginner here.

Can somebody shed light on the following, please: In Remix I copy/past [ERC20Wrapper.sol](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Wrapper.sol) because I only need to wrap an existing token (on Moonbeam). I don't type anything. Only choose compiler 0.8.2, and get the green checkmark. Then I'd like to deploy, but get the message "This contract may be abstract, it may not implement an abstract parent's methods completely or it may not invoke an inherited contract's constructor correctly.".  
What do I have to do, so it deploys? Is this linked to "only" 1 token, and it must be defined in the contract?? (if yes, what do I have to type?)  
Thanks in advance for some helpful inputs.  
Cheers

or I use a simple fixed rate swap smart contract. if there is any.. should be, shouldn't it??

---

<div class="post-metadata">

**Author:** ![CryptoWorld](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/cryptoworld/32/16709_2.png) [@CryptoWorld](https://forum.openzeppelin.com/u/CryptoWorld)\
**Post date:** [June 6, 2022, 11:22am UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/3 "2022-06-06T11:22:20Z")

</div>

The ERCwrapper contract is an abstract class, which means you will have to create an new contract and inherit from it

Please check the above guide and look at the VotesWrapper contract for an example on how to create your own contract.

---

<div class="post-metadata">

**Author:** ![10xc0ffee](https://avatars.discourse-cdn.com/v4/letter/1/e480ec/32.png) [@10xc0ffee](https://forum.openzeppelin.com/u/10xc0ffee)\
**Post date:** [July 21, 2023, 7:32am UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/4 "2023-07-21T07:32:49Z")

</div>

Could any one help on this:

```auto
constructor(IERC20 wrappedToken)
   ERC20("Wrapped Token", "wTKN")
   ERC20Permit("Wrapped Token")
   ERC20Wrapper(wrappedToken)
{}

```

ERC20Permit has a parent of ERC20. Why the constructor also has to initialize the ERC20? Why ERC20Permit don't need to initialize ERC20 in its constructor?

---

<div class="post-metadata">

**Author:** ![barakman](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/barakman/32/855_2.png) [@barakman](https://forum.openzeppelin.com/u/barakman)\
**Post date:** [July 21, 2023, 8:03am UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/5 "2023-07-21T08:03:54Z")

</div>

Since you haven't provided your contract declaration here, I'll answer with "probably"...

The "extra" initialization is required probably because **your contract itself** inherits from `ERC20`.

Since your contract inherits from `ERC20Permit` and `ERC20Permit` inherits from `ERC20`, you may as well get rid of your contract's inheritance from `ERC20`, which will allow you to get rid of this "extra" initialization that you're complaining about.

---

<div class="post-metadata">

**Author:** ![Amxx](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/amxx/32/668_2.png) [@Amxx](https://forum.openzeppelin.com/u/Amxx)\
**Post date:** [July 27, 2023, 8:37am UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/6 "2023-07-27T08:37:23Z")

</div>

> [@10xc0ffee](#):
>
> ERC20Permit has a parent of ERC20. Why the constructor also has to initialize the ERC20? Why ERC20Permit don't need to initialize ERC20 in its constructor?

- ERC20's constructor ask for a name and a symbol that will be used for the token itself
- ERC20Permit inherit from EIP712. That requires you to provide is a name to setup the domain separator (for EIP712 domains).

Since EIP712 and ER20 are independant, they don't share any common name structure, so you have to provide the 2 separatelly ... and technically the 2 could be different is you wanted.

---

<div class="post-metadata">

**Author:** ![Shmaplex](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/shmaplex/32/20399_2.png) [@Shmaplex](https://forum.openzeppelin.com/u/Shmaplex)\
**Post date:** [February 5, 2024, 4:21pm UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/7 "2024-02-05T16:21:28Z")

</div>

I deployed this to the mainnet and it didn't work. Can you elaborate on what might be updated now in 2024, so people don't make the same mistake?

---

<div class="post-metadata">

**Author:** ![barakman](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/barakman/32/855_2.png) [@barakman](https://forum.openzeppelin.com/u/barakman)\
**Post date:** [February 5, 2024, 4:36pm UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/8 "2024-02-05T16:36:58Z")

</div>

> [@Shmaplex](#):
>
> it didn't work

Not before you elaborate on that (obviously).

---

<div class="post-metadata">

**Author:** ![Shmaplex](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/shmaplex/32/20399_2.png) [@Shmaplex](https://forum.openzeppelin.com/u/Shmaplex)\
**Post date:** [February 5, 2024, 4:41pm UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/9 "2024-02-05T16:41:32Z")

</div>

@barakman Here's an open question that shows the contracts deployed. It would be great to figure out where I went wrong because right now I'm at a total loss. [Wrapped ERC-20 Token Issue](https://forum.openzeppelin.com/t/wrapped-erc-20-token-issue/39456)

---

<div class="post-metadata">

**Author:** ![Ali\_Ercan\_Ozgokce](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/ali_ercan_ozgokce/32/21441_2.png) [@Ali\_Ercan\_Ozgokce](https://forum.openzeppelin.com/u/Ali_Ercan_Ozgokce)\
**Post date:** [September 4, 2024, 4:03pm UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/10 "2024-09-04T16:03:37Z")

</div>

Getting this error, on Openzeppelin 5.0.2 version  
"  
DeclarationError: Identifier not found or not unique.  
--\> contracts/wxBTC.sol:10:8:  
|  
10 | ERC20Permit("Wrapped xBTC")  
| ^^^^^^^^^^^  
"

---

<div class="post-metadata">

**Author:** ![Serhat\_Hazar](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/serhat_hazar/32/21961_2.png) [@Serhat\_Hazar](https://forum.openzeppelin.com/u/Serhat_Hazar)\
**Post date:** [December 10, 2024, 12:50am UTC](https://forum.openzeppelin.com/t/erc20-wrapper-tutorial/23536/11 "2024-12-10T00:50:08Z")

</div>

Erc20 token yapıp adını btc token olarak olusturduktan sonra bunun btc ile eşdeğer fiyatta aynı olması ve fantom ağında fantom BTC olarak kullanmak için ne yapmalıyım nereden baslamalıyım
