OpenZeppelin / OpenZeppelin/openzeppelin-contracts
ERC20 Extension: "ERC20Deferred"
Nobody has claimed this yet.
- Dominant language
- Solidity
- Stars
- 27.2k
- Forks
- 12.4k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 33
Description
Description
Extension of ERC20.sol with an opt-in deferred mechanism for all received tokens. If a user chooses to set their manual claim status to ON, then all incoming tokens from transfers AND mints are re-directed to the _pendingBalance mapping. An accurate description of this mapping is the user's "inert balance until revived". Until the user calls either claimAll() or claimSpecificAmount(), the token's remain dead.
The default for all users manual claim status is 0 (UNINITIALIZED), which means users that do not enable their manual claim status receive tokens just like normal.
Code
- GitHub Gist which holds just the extension
ERC20Deferred.sol: https://gist.github.com/alexbabits/489f8ef1fa0a7d5fe5acb7dfe7549ae9 - GitHub Repo with the extension, a mock token example, and unit tests: https://github.com/alexbabits/erc20deferred
Details
Design Note
- Minting that happens within the context of the
claimAll()andclaimSpecificAmount()are considered the "real"_mint(). This is flagged as the sole special case where a user can revive their dead tokens through a "real"_mint()call. All other minting from ANY other source works as expected (if manual claim is not enabled, mints are normal. If manual claim is enabled, mints are forwarded to pending balance.)
Benefits
- Tokens found in the
_pendingBalancesmapping are inert and cannot be transferred or burned. Only upon calling a claim function are they revived from the dead. This may be advantageous for users in certain tax jurisdictions around the world, which might serve as a potential tax deferred instrument similar to traditional finance funds. - Some extra surface level privacy that makes a users overall status more opaque to frontends that display balances. Because the
_pendingBalancesmapping is separate from the_balancesmapping, many displays will not understand that a user has dead tokens that might one day be revived if the user is able to call a claim function. However, anyone who checks the blockchain and token contract in detail will be able to view the users "living" and "dead" balance. - Stable coins & meme coins can brag about this feature. This extension could attract the attention of mainstream users.
Drawbacks
- The total supply is temporarily decreased during any transfer to recipients with manual claim enabled. The total supply is increased back to par once the recipient claims the dead tokens. This may cause conflicts with other extensions like
ERC20Capped.sol. - This extension is probably not adaptable or applicable with Rebase/FoT tokens.
- Total Supply Griefing: Users that hold pending tokens can wait to "revive" them at any moment, which will change the total supply. This attack vector may be conquerable if a design change is made, where rather than burning tokens during a transfer, tokens are sent to an inert intermediary single global vault that holds all pending tokens, so the total supply stays constant. When a user wants to claim pending tokens, the vault burns the tokens and mints tokens to the user.
- Donation Griefing: Someone could frontrun a
claimAll()call and transfer some tokens to the user who is reviving all their dead tokens. This causes the user to revive more dead tokens than expected. Results in total loss for griefer but should be noted.
Options & Expansions
- A timelock mechanism could be implemented
ERC20DeferredTimelock.solwhere a user can choose a minimum locked time once they receive tokens to their pending balances, where they cannot claim the pending tokens to their real balance until the timelock has expired. This is advantageous because the timelock would be inherent to the token itself rather than any outside protocol. - It would be possible to change this contract so only transfers are deferred (and not mints). The default is set to deferring all transfers and mints to the users pending balance if the user has opted in to the manual claim status.
- It may be possible for this idea to be executed on ERC721 contracts, or any token-like smart contract.
Thought Experiment
Someone wants to give you $1,000,000 but you refuse to claim it. The person insists that this donation is something they must do. You once again remind the person that you are NOT currently the type of person to accept ANY donation of {insert fiat name} from ANYONE. In this universe, the person cannot force you to hold the cash in your physical hands, or personal savings account for that matter. Despite your refusal of the donation, the person does the next best thing they can imagine, and forcefully donates $1,000,000 in cash to your local banks vault on behalf of your name. The bank sends you a notice saying, "If you call our number, this cash will be instantly added to your personal savings account."
You go visit your friends working at a fine dining establishment and attempt to purchase a sandwich composed of three buns, 2 patties, and a delicious secret sauce. Because your personal savings account has $1.32 your card gets declined and your friends laugh at you to mask the stench of their own poverty. Walking out of the establishment with an empty stomach, you briefly consider giving the bank a call, but remain steadfast in your morals to pave your own path in life without any donations or help.
Time goes by and you forget about the donation. You lost the banks number and thus ability to call the bank and claim those funds. Even if you changed your mind and heart, you would have no way of retrieving the money. Unless someone reminded you about the donation fiasco and your consciousness and senses were coherent enough to understand the situation, the money remains indefinitely inert inside the vault.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ERC20.sol and compare the proposed ERC20Deferred.sol extension and mock token unit tests in the linked repository. Review the claimAll() and claimSpecificAmount() entry points and the stated transfer, mint, pending-balance, and total-supply behavior; done means the extension's intended semantics are resolved and covered by repository tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- solidity
- Domain
- blockchain
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100