Live data from Hacker News

Understanding Ethereum Smart Contracts

gjermundbjaanes.com

131–140 of 162 posts

Re: Understanding Ethereum Smart Contracts

#131

Earlier quoted context omitted.

That happens today: when I pump gas into my car, the price on the display goes up. When it hits the limit, the gas flow stops. No blockchain is required.

The difference is there is no counterparty risk. Not with the gas station, not with Visa. Admittedly that’s not a big problem with gas pumps (at least where I live, though card skimming is definitely a thing) but you can easily imagine other use-cases. For example your computer could automatically pay an untrusted WiFi hotspot per MB (and automatically pay the VPN you use to secure said untrusted WiFi hotspot) Zero c…

There's still counterparty risk: I could start paying the wifi hotspot but there is no guarantee that it will let me use what I've paid for. At any point, the next microtransaction could fail because the counterparty decides to steal my cash.

Re: Understanding Ethereum Smart Contracts

#132
post #130

Earlier quoted context omitted.

Honest question - why is that something to avoid? What does the floating point representation buy you that say an int64 doesn't, with the same choice of units ie. 1 = 10^-6 dollars?

What if you need to calculate the percentage difference between two monetary values? Ints wont cut it there.

Sure they will. To truncated whole percents, (N2-N1)×100÷N1, using integer ops, gets you that, to whole percents rounded half up, ((N2-N1)×100+50)÷N1 does it. For additional decimal places, increase the fixed multiplier (and added factor for round-half-up) by the appropriate power of 10.

Even if you are dealing in units of hundreds of billions of dollars tracked to mils, this gets you up to, I think, a hundred-thousandth of a percent with int64.

Re: Understanding Ethereum Smart Contracts

#133
post #101
post #98

Earlier quoted context omitted.

But you are working in HF trading. Speed is paramount there. The common programmer has no clue about the numerical instabilities that floating point numbers are causing. Your examples are exactly what I would expect from a capable engineer that is pondering the different pros and cons when you have to optimize your code. Calling BigDecimals entirely unneeded tells me you are in a luxury position where you can draw fr…

Not every single aspect of HFT is insanely speed critical and even in non-critical areas we still don't use fixed decimal point arithmetic on principle. For example we do a lot of profit/loss reporting and analytics which are not speed critical, we write user interfaces and web apps in Javascript that work with money, so on so forth. I will agree BigDecimal is fine to use if speed really doesn't matter, it's at least…

To clarify for myself and maybe others: are you arguing against using a single integer scaled to the smallest precision someone thought they'd need N year(s) ago?

If so: totally agreed. Inflexible single-scaled-ints have been a plague in nearly every piece of production code I've seen them in. I'll take floats (well, doubles) any day over this.

Flexible scale tho (arbitrary precision / bigdecimal equivalents (I'd prefer bigdecimal over home-grown two-int variants, obv)) usually works out. And tends to avoid semi-frequent-though-usually-unimportant/unnoticed[1] issues with imprecise floats (~16 million for exact int representation[2] is awfully small, though doubles are generally Good Enough™).

[1]: usually. adding doubles/fractions often produces garbage-looking output unless you remember to round. but in my lines of work, nobody cares[1.1] if it's a couple cents off in analytics.

[2]: https://stackoverflow.com/questions/3793838/which-is-the-fir...

[1.1]: yet

Re: Understanding Ethereum Smart Contracts

#134

Earlier quoted context omitted.

Likely you don't need a generic implementation of Decimal. What money do you want to represent, they all have a "atomic value". For instance, when working with dollars store cents. When working with Eth, store wei. etc. I can't think of a use case of money that needs decimals except maybe computing ownerships percentage. but that should never be stored, but rather computed. Anything that needs to be converted is a "f…

You might need to work with fractions of "atomic values" to get the desired level of accuracy. So you have to store not logical cents, but 1/100th of cents or something like that. Much easier and straightforward just use decimal-like type.

That's what happens in e.g. the Maker stablecoin project. Decimal fixed point to give sub-wei precision when prorating per-second compounding fees. Other than the normal simple arithmetic operations, we use "exponentiation by squaring" to take a decimal fixed point raised to an integer power.

Re: Understanding Ethereum Smart Contracts

#135
post #133
post #101

Earlier quoted context omitted.

Not every single aspect of HFT is insanely speed critical and even in non-critical areas we still don't use fixed decimal point arithmetic on principle. For example we do a lot of profit/loss reporting and analytics which are not speed critical, we write user interfaces and web apps in Javascript that work with money, so on so forth. I will agree BigDecimal is fine to use if speed really doesn't matter, it's at least…

To clarify for myself and maybe others: are you arguing against using a single integer scaled to the smallest precision someone thought they'd need N year(s) ago? If so: totally agreed. Inflexible single-scaled-ints have been a plague in nearly every piece of production code I've seen them in. I'll take floats (well, doubles) any day over this. Flexible scale tho (arbitrary precision / bigdecimal equivalents (I'd pre…

Yes, we are on the same page. BigDecimal is appropriate for representing money, fixed point arithmetic is not. I simply argue that in situations where you care about performance, you can actually drop BigDecimal and use floating point decimal or even floating point binary and get perfectly good results that have exact precision so long as you model your domain.

Re: Understanding Ethereum Smart Contracts

#136

Earlier quoted context omitted.

True, but the extra code around those solutions cost gas, of which your looking at around 500 lines worth. How long is BigDecimal.class?

Likely you don't need a generic implementation of Decimal. What money do you want to represent, they all have a "atomic value". For instance, when working with dollars store cents. When working with Eth, store wei. etc. I can't think of a use case of money that needs decimals except maybe computing ownerships percentage. but that should never be stored, but rather computed. Anything that needs to be converted is a "f…

> What money do you want to represent, they all have a "atomic value".

This is mostly not true.

> For instance, when working with dollars store cents.

While external transactions often must occur in cents, internal accounts and unit prices often have smaller amounts. If you don't believe me, visit any US gas station and the prices will be in mils, not cents (and will usually be one mil less than some full-cent value per gallon.) Atomic units for financial applications are application-specific if there is an appropriate value at all, they aren't trivially determinable by looking at the base currency.

In some cases you really want an arbitrary precision decimal (or even rational) representation.

Re: Understanding Ethereum Smart Contracts

#137
post #130

Earlier quoted context omitted.

What if you need to calculate the percentage difference between two monetary values? Ints wont cut it there.

Sure they will. To truncated whole percents, (N2-N1)×100÷N1, using integer ops, gets you that, to whole percents rounded half up, ((N2-N1)×100+50)÷N1 does it. For additional decimal places, increase the fixed multiplier (and added factor for round-half-up) by the appropriate power of 10. Even if you are dealing in units of hundreds of billions of dollars tracked to mils, this gets you up to, I think, a hundred-thousa…

But with floats you just use a divide operation.

Re: Understanding Ethereum Smart Contracts

#138
post #89

Earlier quoted context omitted.

>That is actually a feature when it comes to working with money. You don't ever want to use floating-point arithmetic with monetary values due to its inability to represent all possible decimal fractions of your base unit. This is just as true for over-hyped blockchain stuff as it is for any imaginable application in the "classic" financial sector. I feel like this is constantly repeated but is simply untrue and work…

> [...] only to eventually encounter all the issues that floating point was invented to solve. When they encounter those issues they then end up having to adapt their code only to basically re-invent a broken, unstable quasi-floating point system when they would have been much better off using the IEEE floating point system [...] Would you care to elaborate on some of these issues? I'm genuinely curious.

Sure, I'll embarrass myself here and use myself as an example since this is how I actually came to even learn about this to begin with.

When I started working in finance straight out of school (not in HFT at the time), I naively accepted the dogma that money should never be represented using floating points. I mean everywhere I went I would read in bold letters don't use floating point! Don't use floating point! So I just accepted it to be true and didn't question it. When I wrote my first financial application I used an int64 to represent currencies with a resolution of up to 10^-6 because that was what everyone said to do.

And well... all was good in life. Then one day I extended my system to work with currencies other than U.S. dollars, like Mexican Peso's, Japanese Yen, and currencies X where 1 X is either much less than 1 USD or much greater than 1 USD.

Then things started to fail, rounding errors became noticeable, especially when doing currency conversions, things started to fall apart real bad.

So I took the next logical step and used a BigDecimal. Now my rounding issues were solved but the performance of my applications suffered immensely across the board. Instead of storing a 64 bit int in a database I'm now storing a BigDecimal in Postgresql, and that slowed my queries immensely. Instead of just serializing raw 64-bits of data across a network in network byte order, I now have to convert my BigDecimal to a string, send it across the wire, and then parse back the string. Every operation I perform now requires potentially allocating memory on the heap whereas before everything was minimal and blazingly fast. I feel like there is a general attitude that performance doesn't matter, premature optimization is evil, programmer time is more expensive than hardware, so on so forth... but honestly nothing feels more demoralizing to me as a programmer then having an application run really really fast one day, and then the next day it's really really slow. Performance is one of those things that when you have it and know what it feels like, you don't want to give it up.

So not knowing any better I decided to come up with a scheme to regain the lost performance... I realized that for U.S. dollars, 10^-6 was perfectly fine. For currencies that are small compared to the U.S. dollar, I needed fewer decimal places, so for Yen, 1 unit would represent 10^-4 Yen. For currencies bigger than U.S. dollar, 1 unit would represent 10^-8...

So my "genius" younger self decided that my Money class would store both an integer value and a 'scale' factor. When doing operations, if the scale factor was the same, then I could perform operations as is. When the scale factor was different, I would have to rescale the value with lower precision to the value with higher precision and then perform the operation.

This actually worked to a degree, I regained a lot of my speed and didn't have any precision issues, but all I did was reinvent a crappy floating point system in software without knowing it.

Eventually I ended up reading about actual floating points and I could see clearly the relationship between what I was doing and what actual experts had realized was the proper way to handle working with values whose scales could vary wildly.

And once I realized that I could then sympathize with why people were against using binary floating point values for money, but the solution wasn't to abandon them, it was to actually take the time to understand how floating point works and then use floating points properly for my domain.

So my Money class does use a 64-bit floating point value, but instead of (double)(1.0) representing 1 unit, it represents 10^-6 units. And it doesn't matter what currency I need to represent, I can represent currencies as small as Russian rubles to as large as Bitcoin, and it all just works and works very fast.

64-bit doubles give me 15 digits of guaranteed precision, so as long as my values are within the range 0.000001 up to 999999999.999999 I am guaranteed to get exact results.

For values outside of that range, I still get my 15 digits of precision but I will have a very small margin of error. But here's the thing... that margin of error would have been unavoidable if I used fixed decimal arithmetic.

Now I say this as a personal anecdote but I know for a fact I'm not the only one who has done this. I just did a Google search that led to this:

https://stackoverflow.com/questions/224462/storing-money-in-...

The second top answer with 77 points yells in bold letters about not using floating points as a currency and suggests using a scheme almost identical to the one I described, where you store a raw number and a scaling factor, basically implementing a poor-man's version of floating point numbers.

Re: Understanding Ethereum Smart Contracts

#139
post #137

Earlier quoted context omitted.

Sure they will. To truncated whole percents, (N2-N1)×100÷N1, using integer ops, gets you that, to whole percents rounded half up, ((N2-N1)×100+50)÷N1 does it. For additional decimal places, increase the fixed multiplier (and added factor for round-half-up) by the appropriate power of 10. Even if you are dealing in units of hundreds of billions of dollars tracked to mils, this gets you up to, I think, a hundred-thousa…

But with floats you just use a divide operation.

“Won’t cut it” and “will require 1-2 more operations” are very much not the same thing.

Re: Understanding Ethereum Smart Contracts

#140

Earlier quoted context omitted.

The only thing seckimjohn showed is that contracts, paper or "smart", are only as good as they're written. Since contracts such as _red gave, "we are friends, this is our company, we share the EBT equally", exist right now, it's a perfectly realistic use case for a smart contract. Hell, I'd even do that for a small project. Smart contracts being fixed and errors being exploitable is a valid criticism but it's not the…

""smart", are only as good as they're written" There are so many things that go into contracts that cannot be articulated in 'code' that this all hardly makes sense. Employment contracts are long. Comp packages can be complex. And we all live in countries with employment laws etc. that require these things anyhow. I don't see any actual real-world cases for Eth contracts just yet.

> There are so many things that go into contracts that cannot be articulated in 'code' that this all hardly makes sense.

I think this is actually something I've been trying to articulate for a while now anytime smart contracts come up.

Legal contracts only specify the criteria and conditions surrounding a contract. Smart contracts must describe that PLUS all the very specific instructions on how to validate those criteria/conditions which adds a massive amount of complexity into the contract (and more potential for loopholes).

Post reply on HN