usmfum / usm Goto Github PK
View Code? Open in Web Editor NEWMinimalist USD - A minimalist, collateralized stablecoin built on Ethereum.
License: GNU General Public License v3.0
Minimalist USD - A minimalist, collateralized stablecoin built on Ethereum.
License: GNU General Public License v3.0
This is an idea I've had in the back of my mind, to fix some unpleasant cases where the system charges both buyers and sellers an excessive fee. I dove in this week and looks like it's working - it's a significant change (different formulas in usmFromMint()
and co), but a worthwhile one I believe. Doesn't change the public API at all. I'm putting some time into revamping the tests before I submit a PR - aiming for sometime tomorrow. Then I can get back to oracle work!
For better UX, the UI should make use of off-chain signatures and use them to interact with ERC20Permit.
Let's check what our options are
This is total nitpicking but just for my understanding - we have the enum Side {Buy, Sell}
in IUSM, but the constants like WAD
and MAX_DEBT_RATIO
, and the struct TimedValue
definition, in USM. Any rhyme or reason to that or does it just not matter much...
Implement in Proxy
by calling:
function fundWithUSM(...) {
proxy.burn(...);
proxy.fund(...);
}
function defundToUSM(...) {
proxy.defund(...);
proxy.mint(...);
}
Note that we are calling the Proxy
functions, meaning that limit orders are included.
USMView
needs to call usm.totalSupply()
, but its usm
is of type IUSM
, and I couldn't figure out how make IUSM
include a totalSupply()
fn; because then USM
would be inheriting it from both IUSM
and ERC20Permit
, and I couldn't get that to work. So I gave the IUSM
interface a usmTotalSupply()
fn, where USM.usmTotalSupply()
just returns totalSupply()
.
This works fine! But the redundant usmTotalSupply()
is ugly. Ideally USMView
would just call usm.totalSupply()
.
Maybe we could make IUSM
inherit from IERC20
, so that IUSM
users like USMView
can count on it implementing totalSupply()
?
Otherwise this may just be one of those "It ain't beautiful but it's fine stop worrying about it" things.
fund limit buy orders (aka: specify a max FUM price when doing a fund op, so that the ETH/USM is stored for later execution if the current FUM price is too high)
Eg storedPriceA
/storedPriceB
in OurUniwapV2TWAPOracle
. I made those private to try to save gas but I don't even think it does? Anyway not worth it, better to expose this stuff for debugging etc
These should never happen after the first FUM is minted after launch. But they might produce some exploitable cases if they do (eg, infinite debt ratio), so let's make sure that if the oracle returns a price <= 0 we reject it, etc.
Can USM be deployed on ETH compatible chains? Is the project team open to working on commercial collaboration?
In the current fumPrice function,
price = (buffer <= 0 ? 0 : uint(buffer).wadDiv(fumSupply, roundUp));
if the fumSupply is very low and buffer is very high the price returned is so high that it can be considered impractical. Moreover, at such high price both fund and defund functions throw error when calculating fumOut or ethOut in fund/defund respectively.
fumOut = ethIn.wadDivDown(fumBuyPrice0);
See ABDK issue #56, and Telegram discussion with @albertocuestacanada.
One possible convention is:
USMView
, USMWETHProxy
)_burnUsm()
, onlyHolderOrDelegateOrFum
)This will help incentivize anyone using the TWAP to call refreshPrice()
(rather than latestPrice()
) in order to get a fresh price, which is beneficial for the other users of the TWAP (like us!). Even better for us would be to remove latestPrice()
from the TWAP oracle entirely, but having no view
function to get a price seems a little harsh. I think "You can call our view
function (latestPrice()
) rather than our transactional fn (refreshPrice()
), but it won't give you as fresh a price" is a reasonable compromise.
(This is based on a suggestion from @albertocuestacanada last month. I already incorporated it into USM
/USMView
, but I realized tonight I didn't incorporate it into OurUniswapV2TWAPOracle
.)
Note that this issue has no direct impact on USM
, which only ever calls refreshPrice()
anyway. But it does indirectly affect USM
in that the more often other users of our oracle call refreshPrice()
, the more up-to-date the numbers it gives us will be.
Would be nice for eg @alexroan's dashboard, so when there's a significant spread between buy and sell price, users can see which is actually expensive right now (far from mid).
The result should be simpler, let's check.
burn
/fund
) pushes up the price (the "sliding price" effect), the price drops back towards the raw oracle price faster. This saves the next buyer fees, but means that when the oracle price is slow/off, traders get more chances to exploit it.mint
/burn
, another for fund
/defund
. So if, eg, there have been more mints
than burns
recently, that will push down the sell price used for mints
and defunds
; and if there have been more funds
than defunds
, that will push up the buy price used for burns
and funds
. If both of these have happened recently (more mints
than burns
and more funds
than defunds
), then fees will effectively be high for all operations.mint
against a long-ETH fund
. If 10 ETH has been passed to mint
and 5 ETH to fund
, that could add up to net long ETH in total or net short, since fund
is effectively a leveraged buy - it depends on the current debt ratio, etc...burn
/fund
) will be more expensive if either more burns
than mints
have been done recently, or more funds
than defunds
.As discussed on Telegram - this is a predictable (serious) future UX problem we should think through now, since the most natural fix is to make (eg) USMv1._transfer()
reject sends if the recipient is USMv2
, and making that work requires figuring out how USMv1
will be able to know USMv2
's address once we release the latter.
Related to #61, as discussed on Telegram - a generic "autoexecutor" smart contract that you can call addTask(task)
on, with task.isExecutable()
and task.execute()
callbacks, where each addTask()
call also executes up to two previously-scheduled-and-currently-executable tasks. Might be workable might not
Create a basic UI so users can interact with testnet USM using their preferred web3 provider.
I'm noticing, though, that all the buy
functions are missing from the system. We can use a precise amount of ETH to fund
for an unknown amount of FUM. What if the user wants to mint exactly 1 FUM?
Same with all others. Would we just reverse the logic in the frontend? Code it in the smart contracts? Not implement it?
Working on the fees math made me realize we don't actually need to store the minFumBuyPrice
when debt ratio > max (eg 80%): there's a clean way to infer it from other stored values. This has been bugging me for a long time - it's actually what I spent most of my first week on USM in July banging my head against!
In brief: the way it works now is, if the system's debt ratio goes above 80%, it records the FUM price in ETH terms as of the moment it crossed 80%, and charges at least that much (in ETH terms) until debt ratio goes back below 80%.
fund
callers will always be charged ≥ 0.005 ETH per FUM, until debt ratio gets back below 80%.The new way is, when debt ratio > 80%, instead of using the actual USM quantity in the FUM price calculation, we use a lower "effective USM" quantity equating to an 80% debt ratio. Basically, we pretend any USM that pushes us above 80% doesn't exist.
I found this because the storage-based method doesn't work for the new fumFromFund()
math - I needed to back it out this way instead. Then I realized then we don't need to store it at all.
I believe the new way always gives the same number as before, except it avoids the ugliest part of the old way: the fact that in some cases the FUM buy price would discontinuously drop once debt ratio got back below 80%. (FUM price plunging after people buy FUM = bad incentives.) Now it instead declines smoothly as debt ratio approaches 80%, which seems strictly more correct to me.
Note we do still want to store a value related to mfbp, because of the separate feature (Elliot's) where we make mfbp decline over time. But now we can just store the time to start declining from, rather than a price value.
ABDK think this is more conventional, I see some mixed evidence but on balance I agree.
0-fee upgrade op, to save users money if/when we need to push a fresh contract
Using ETH is a pain, let's consider using Weth instead.
"Don't annoy @danrobinson" is a good rule of thumb for any project https://twitter.com/danrobinson/status/1338566170140581889
I've been doing some dreaming about this... It's not a trivial undertaking, but the code might actually be quite short and I really think it's the feature that would most effectively prevent the system from going underwater. Anyway not top of our plate quite yet...
Just scrapping all the MINT_FEE/BURN_FEE stuff if it makes life simpler (probably), because I think the const-product fees are likely to be all we use in the end.
There are arguments for and against this, but it's a reasonable option to consider. (Suggested by ABDK audit)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.