I want to create a token that represent the other token, the peg is not 1:1 but e.g. 10:1, so if a person deposit 1 of TokenX will get 10 of my tokens. The person should also be able to withdraw his tokens and I must not be able to control the deposits.

More accurate example if someone deposits 1 USDC will get 10 Tokens and this is always fixed

I don't know if this is possible, I thought cloning the WETH contract and change it a bit but I feel the deposit feature works only with ETH not with tokens

  • of course it is possible, you just have to track all deposits to USDC and immediately issue your own transaction after each block to mint/burn your own tokens accordingly and assign them to addresses. The users obviously won't control anything and couldn't withdraw your tokens or deposit, because your tokens are pegged to USDC. Users would increase/decrease their holding in your token by managing USDC tokens.
    – Nulik
    Aug 16, 2021 at 19:47

2 Answers 2


You should use the approve + transferFrom combination. So it would work something like this:

  1. User adds your contract allowance to withdraw 10 of his tokenA (with the approve function)

  2. User calls your contract's exchange function (or whatever it's called). This function: a) withdraws the 10 tokenA from user's wallet (transferFrom) and b) sends 1 tokenB to the same user's wallet.

And vice versa, for the reverse.

  • this is not what allowance feature was designed to. What if he wants to give infinite allowance to the contract? this way of working would fail
    – Nulik
    Aug 16, 2021 at 19:40
  • Thanks for the feedback. I'm not sure if I understand your comment correctly. I thought this is exactly what allowance was designed for - a two-phase transfer. And if one wants to allow more, nothing stops you from allowing the maximum uint can store. For security purposes you should never allow more than you want for the other to take - but in reality most services add way too much services for convenience reasons Aug 17, 2021 at 4:37

Untested quick example to show you how the concept works:

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

interface IUSDC {
  transferFrom(address, address, uint)

contract peggedToken is ERC20 {
  address usdcContract = 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48;
  constructor ERC20("PeggedToken", "PT") {

  function getPeggedToken(uint usdcIn) {
    IUSDC(usdcContract).transferFrom(msg.sender, address(this), usdcIn);
    _mint(msg.sender, usdcIn*10);

This is the basic idea. User will need to make an approve call to the USDC contract directly, first, with the amount of usdcIn, and the address of this contract.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.