-
Notifications
You must be signed in to change notification settings - Fork 411
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use of BTCRelay without paying fees #44
Comments
I think that it is a good case if something that is already possible especially if messy and complicated becomes easier to do, because future smart contracts get safer because the developer and potential auditors are more likely to realize that something is flawed when their is an easy (or in this case at least easier way) to exploit it. |
If by INJECTED_STATIC_CALL you mean |
No I meant ethereum/EIPs#199 (which is only an issue but I used it as an illustration of what would make such flaws the most obvious) |
Please note that this is an issue even today, without |
Thanks for the discussion. It's looking like the design for such oracles should use 2 transactions. tx1: is for some payer address to be recorded. tx2: when oracle is asked for information, it checks the payer has prepaid (tx1). Implementation wise, one way to ensure 2 txs is to also record the blocknumber in tx1, which tx2 checks that its blocknumber is different. |
I think that won't help ether, as long as the information is on the chain their is a way to access it. One approach that always works is, that I read it outside the chain and then generate a proof, that in a specified block at the storage key inside the oracle contract a specific value was stored. Because smart contracts have access to the block hashes, they can verify that proof. That way not a single call to the oracle is necessary. The only way I see to make a oracle work, is to not charge for reading the information but for generating the information as oraclize.it does it. So the information is not send to the blockchain until it is requested and payed for. |
The proof/s would be stored on-chain and would thus have costs. Exact economic costs aside, the "altruistic" party that wants to make BTC Relay free for use, may as well use those costs to submit Bitcoin blockheaders instead (and set no fee). EDIT: Or for a "malicious" party, the cost of storing the proof might be higher than just paying the fee. There's potentially 2 types of "on-chain oracles": for-profit and non-profit. Business models for on-chain for-profit oracles may be tenuous or infeasible since the data is public (as @tawaren and others suggest). The fundamental reason for fees in BTC Relay is to strive for sustainable, decentralized infrastructure. BTC Relay needs data regularly and apart from "altruistic benefactor/s" which may not exist, it needs to incentivize the community to provide the data, and the obvious way to do it is to charge a fee (at least for first use of the data). My understanding is that Oraclize isn't 100% trustless; maybe increasing its trustlessness is more feasible than a sustainable, decentralized infrastructure. If a decentralized one works, it may have lower cost than a centralized oracle infrastructure (and also the advantage of availability guarantees of the blockchain). |
Oracles on Ethereum aren't valuable because of the information itself. They are valuable because they make that information immutably available to contracts via a well defined trust scheme. When one pays for an Oracle, they are paying for the mechanism of getting real-world information into a contract with some well defined level of trust (depends on the oracle). This opcode will undermine any system that charges for on-chain access to that data to more than one user. It will make it so that once someone has paid to put the data on-chain, any contract can access that data on-chain for free. While in some cases "pay to put on chain" can work, this doesn't allow distribution of the cost across many users. If you have some kind of data that is expensive to put on the chain you run into a problem where the user that puts the data on-chain has to pay 100% of the cost and the next 1000 users get it for free. At the moment, I don't believe there is a live exploit because throw burns all gas, so there is no way for the contract to take the result and store it on-chain. As an example:
Currently, step 3 would be a throw which would prevent step 4 from completing. This allows an oracle to distribute its costs across all users of the data rather than having to front-load the costs on the first request. This change, as I understand it, will effectively allow for a contract to be able to copy the result of any other contract without paying the contract for that result. I would consider this a pretty major change in the model and it violates expectations of historic contract authors. My recommendation would be to make it so if you call revert, your stack is wiped rather than allowing the contract to retain its stack on a call to revert. Of course, one can argue that the first person can pay the low-cost for the data and then publish it for free to everyone else but this can be mitigated by a semi-ponzi scheme where the first person who wants the data pays full price, then the next person pays full-price minus delta to the first person, the third person pays full price minus 2*delta to the second person, etc. This ensures that the contract always gets enough to cover its costs, while making it so if the data is highly sought after everyone will end up paying The point of the above two examples are just to show that it is possible to setup an oracle that distributes costs to users of the data without risking itself being underpaid for the service. |
With Metropolis, there will be a new opcode,
REVERT
(ethereum/EIPs#206) andRETURNDATA
(ethereum/EIPs#211).The
REVERT
opcode will function as athrow
, reverting state-changes, but will not burn the remaining gas. Additionally, it can return some data, in order to provide the callee with information about the error.Unfortunately, this EVM-change undermines the model for synchronous oracles which accept payment; it's possible to
BTCFreelay
InternalCall
3. Perform call to
BTCRelay
for verification, along with payment4. Perform
revert
along with the response from BTCRelayThis would revert the payment(s), but still grant access to the return value.
Note: Even without
RETURNDATA
, it would still be possible to perform this attack, albeit with less data being extracted. Example gist showing how to 'freeload' on btcrelay usingrevert
withoutreturndata
: https://gist.github.com/holiman/51f9b02b64f864b896129d329757460c .Note 2, this can also be performed already today, using a regular
throw
, but the attack is quite 'messy' since it needs to handle several intricate cases ofOOG
due to remaining gas being discarded at everythrow
.I'm filing this as an issue, even if it's not yet implemented, so there can be a discussion about possible future modifications that can be made. Also, posting it as a 'known issue' here makes in not eligible for a reward in the bug bounty.
The text was updated successfully, but these errors were encountered: