Binance Smart Chain DeFi Project Hacked for $31M
cryptobriefing.com
cryptobriefing.com
Since everything has been scrubbed the only suggested that they've been hacked comes from a cropped screenshot of their telegram channel which I found in this article: https://obelisk.medium.com/meerkat-finance-and-the-0-that-wa...
The article also clearly shows in the smart contact that this was premeditated.
Edit: It's also important for context to note that 31 Million TVL (Total Value Locked) isn't low but isn't high for a DeFi project.
You can get a sense of the TVLs by looking at other projects on Ethereum ($39B total https://defipulse.com/) and the Binance Smart Chain ($9B total https://www.defistation.io/)
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
// this is the getter
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
// return the memory at slot
adm := sload(slot)
}
}
// notice the 0 and the different, off by 1 hash
bytes32 internal constant ADMIN_SL0T = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6102;
// this is the setter, this doesn't set the same value as the getter, in effect the admin cannot be changed
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SL0T;
assembly {
// set the memory at slot to the value of newAdmin
sstore(slot, newAdmin)
}
}
https://bscscan.com/address/0x7e0c621ea9f7afd5b86a50b0942eae...Then when you (indirectly) call _setAdmin you can pretend that you no longer have powers to upgrade the contract.
A casual glance through the code won't show anything amiss. The ADMIN_SLOT and ADMIN_SL0T are defined in very different places.
SL0T is also the closet fake character you could use, except maybe ADM1N_SLOT.
Then when you (indirectly) call _setAdmin you can pretend that you no longer have powers to upgrade the contract.
I know nothing about smart contracts, though, so, question: why is that a backdoor? What does it mean?
modifier ifAdmin() {
if (msg.sender == _admin()) {
_; // run the rest of the function being modified
} else {
// for our case this essentially does nothing
_fallback();
}
}
// imagine the code inside the function in place of the _ in ifAdmin
function upgradeTo(address newImplementation) external ifAdmin {
// actually upgrades the contract in place
_upgradeTo(newImplementation);
}
So this smart contract has the ability to upgrade itself in place if it is called by the administrator. This is widely accepted and normally a useful feature. As a gesture of goodwill a developer will relinquish control of the contract for a set amount of time via a timelock. During this time users can use the smart contract without worry that the developer will maliciously upgrade and steal their funds.This can be seen here: https://bscscan.com/tx/0xecd169b3a299d28495cbc9bd22b5690e263...
So here it looks like the administrator was changed but as we know it actually didn't. Now users begin to use the platform and deposit funds.
Since the admin hasn't changed the developer calls upgradeTo and deploys a malicious change, seen here: https://bscscan.com/tx/0xf19fa4bcff4adaebeddd28c851458ba0f01...
This contract (https://bscscan.com/address/0xb2603fc47331e3500eaf053bd7a971...) is compiled so we can't easily see the source. This doesn't matter as we can easily see the resulting transactions (https://bscscan.com/tx/0x1332fadcc5378b1cc90159e603b99e0b73a... and https://bscscan.com/tx/0xd8145dfe255a671428b9c082a006a145fe5...).
Whats especially clever about this rug pull scam is that it is self contained. Instead of selling your tokens at an exchange which risks low liquidity and front running, the developer is in control the whole time and could have done this whenever he thought the deposits were enough.
You can DM me on Twitter if you’re on.
Your best bet is probably a reddit pm (not their new chat feature), my username is the same. I should get twitter but it's one of those things I never really got into.
That's also a vulnerability which should have been exposed by tests (again, run by an independent 3rd party).
Audits aren't the be all end all either, a determined scammers could have added the backdoor after the audit.
It's almost as if having a readable contract that the signers can all understand and a judge who can rule on reasonable interpretations of the contract is a feature, not a bug.
Whatever component of the "smart contract" that allowed them to do this would have been negotiated out, but since it's a decentralized "the contract enforces itself" cryptosystem, people just trust that the contract does what it says on the tin.
What should be the procedure before using these? Pay a security researcher for an independent review, like you would have a lawyer go over a contract? If you have to do that, why not just use a regular contract and lawyers where you have recourse when something goes wrong?
Gotta say though, the choice of the term "smart contracts" was great marketing.
It's easier to think of them as the rules to a game, like chess. The smart contact defines the pieces and valid moves. The EVM enforces the rules.
A contract between two people is fundamentally an agreement that "If you do this, then I will do that", enforceable by law. It exists to allow trust: if you have no way of knowing what the other person is going to do in response, why would you ever do something like give them money or perform services for them? With smart contracts the legal system is replaced by a worldwide network of computers, and the actions that you can guarantee are restricted to quantities or properties represented on the blockchain. But the basic motivation and principal are the same: you want to provide guarantees about the future so that people can take mutually beneficial actions with them in mind.
If we took this take into your analogy this would be a scam artist solicitating funds and having a contact cause that has a loophole. Investors signed without reading and loose their money.
A judge could only rule after the fact and if the scammers left the country with the money the ruling wouldn't bring the investor's money back.
If I understand correctly, there can't be any actual secrets; you have to read carefully, then caveat emptor.
Yes, that is the normal practice, and any bigger project worth their salt pays for an external security auditor.
As explained in the blog post of the top comment here (https://obelisk.medium.com/meerkat-finance-and-the-0-that-wa...), this was clearly an exit scam by the Meerkat developers, which is exactly why users shouldn't put any significant amount of money into contracts that haven't been audited by a reputable external auditor.
Distressed users have reached out to Binance CEO Chanpeng Zhao, hoping that the CEO can track down the money. CZ has not replied to any comment on Twitter.
Know that feeling. Welcome to Mt. Gox in 201x.
Go stare at a lake and make peace that your money is gone.
(Then post loss porn so that you can get a few internet points out of it.)
By the way, as a registered member of Mt Gox, I was able to view every single claim posted by every other Mt Gox user, which was very surprising. It's essentially a giant table of confirmed claims, with 2,000 pages. You can hardly scroll more than a page before finding someone with a confirmed claim of ~1,200 BTC or so.
So, take comfort that there are always bigger losses. :)
Not your keys not your coins!
I don't think it's an argument against some kind of regulation/consumer protection. Pretty much everyone I know (in the UK) has banked safely for most of their life. Pretty much everyone I know that's touched crypto (me included!) has a story about losing something.
It was regarding the 'regulation' thing. Cryptocurrency is only ever going to work for John Everyman if the industry starts to mature a bit. Blaming the user when another exchange gets ripped off doesn't exactly scream 'legit', does it?
I'm not sure it's meaningful to say cryptocurrencies are decentralized. Decentralization is more of a social phenomenon than technical, e.g. cash is decentralized but socially we've found advantages to centralize.
As to the point of it, it's mostly about recycling the existing Ethereum ecosystem of dApps and allowing less wealthy people to play with it, even if the original motivation for it is lost. Kind of like a testnet network, except people put real money on it, and influencers mislead people about its real nature.
As far as I know BSC doesn't have any mixers, nor aomtic swaps exchanges.
Ethereum once rolled back their blockchain for the DAO hack. The price dropped 25% and ethereum was forked into ETC.
Then go on to say : Does Binance bear the losses if an on-chain contract is attacked during DeFi Staking? No. Binance only acts as a platform to showcase projects and provide users with related services, such as accessing funds on behalf of the user and distributing earnings, etc. Binance does not bear any liability for losses incurred as a result of on-chain contract security.
--- So if you don't have the keys, and there aren't liable, that's a bit messed up.
BSC is controlled by an oligopoly of validators that Binance decides on. I'm sure if things really got bad on their network they could do something similar to the Ethereum Classic fork during the DAO incident.
EDIT: My bad, I skipped a few words in parent.
function _setAdmin(address newAdmin) internal { bytes32 slot = ADMIN_SL0T;
assembly {
sstore(slot, newAdmin)
}
}
https://obelisk.medium.com/meerkat-finance-and-the-0-that-wa...This reminds me of Bruce Schneier's article "Unicode is too complex to ever be secure", except in this case ASCII too apparently ; )
Which makes me wonder: for such sensitive programming languages, shouldn't the specs be much more restrictive and for example only allow 'A' to 'Z' in variable names, no digits, no lowercases, etc.?
Not really considering it's usually the same people.
Who better knows the weird edge cases of the code than the devs themselves :) And after all, it's not theft because code is law :)
/s
Who the attacker is does not matter. This comment seems to describe the vulnerability (intentionally implemented, but again, it doesn't matter) as a homoglyph attack: https://news.ycombinator.com/item?id=26358767
Homoglyph attacks are not new. Even for Solidity, they are at least 4 years old: https://github.com/Arachnid/uscc/tree/master/submissions-201...
> // The e in the 'refunds' string is the unicode char U+0435, also known as Cyrillic small ie
> uint weiAmount = balances['rеfunds'][msg.sender];
(from the README)
> The actual hacks you'll see today are significantly different from those of last summer so there's been some measurable progress.
They might or might not be different, the fact remains that they have gained little in sophistication, which would be a more relevant measure of progress. As I mentioned in another comment, this is not the kind of flaw that would have passed a diligent 3rd party audit, and yet the thieves got $31M from it.
"OK, here"
"Oh oops someone stole it, that's too bad for you, oh well bye!"
The whole idea of contract in a legal sense is a human construct.
The age old bitcoin joke is that loans are gifts. I’ve used bitcoin for a decade and never touched binance. Mt. Gox creditor never bothered filing a claim either.
I could tell you stories about 10 other domains and sites that were trusted that did the same thing. Not your keys, not your coins; not in funny internet money land.
A good example of a real, everyday use case for smart contracts is NBA Top Shot. Unlike regular collectable the smart contact guarantees the company cannot decide to manufacture more of a rare item, it allows verification of the supply and traded value.
A lending contract like Aave simply formalises the economic contracts behind lending. By doing so it can provide stricter guarantees about enforcement. It's not so much of a contract but a strict set of bindings that the EVM will enforce.
If you've stayed away from binance perhaps you've used or hear of atomic swaps? They're especially smart contacts that aren't tied to any chain. A strict set of rules and moves to guarentee that the contract of swapping is withheld by both parties.
There are tons of ways trust assumptions about smart contracts can be misunderstood. The current general education level about crypto seems similar to when snake oil sellers where sprinkling "artifical intelligence" in their products to make them "smarter". A drip of "blockchain" and suddenly your product is "trustless".
[1]: https://defited.medium.com/my-centralized-experience-dapper-...
Am I right in understanding he's trying to withdraw USDC from Flow to Ethereum (https://support.meetdapper.com/hc/en-us/articles/36005912467...) and requires KYC and the process is actually centralised?
I'd have imagined that Cricle would have build a decentralised flowUSDC-ethUSDC bridge but perhaps there's a regulation reason which also explains the KYC requirements.
If this is the case, hopefully someone else can pick up the slack and create a Flow-Eth bridge/atomic swap.
We already have an escape hatch for generalized catastrophic events in the form of hard forks, but I expect in the future more fine-grained schemes to manually resolve local issues will become the norm.
It's only working for a small set of pools right now.
Really I'd say that project just isn't DeFI, but an on chain hedge fund. DeFI is usually non custodial meaning that the creator doesn't have the ability to touch your funds.
Will be interesting to see what really happened.
https://bscscan.com/address/0x7e0c621ea9f7afd5b86a50b0942eae...
Note line 304 the O is a 0:
bytes32 slot = ADMIN_SL0T;
This is like in Java, where you mean to override a method in a superclass but mis-spell the name of the method and therefore instead end up simply adding a new method with the mis-spelled name.
I guess either Solidity doesn't have something like Java 1.5+'s @Override, or else it just wasn't used.
In any case it's hard to believe this was accidental. Of all the places you could make this mistake, most of the others wouldn't result in a massive exploit like this.
But I agree, that's not what happened here.
In short:
* the smart contact is made in a way that allows upgrades by an administrator * the developers transfer their administrator privileges to another user as a show of good faith * the code to transfer the privileges actually doesn't do anything * the developers upgrade the contract giving themselves permission to take the funds
Then elsewhere on line 50, anybody who creates a Proxy object will automatically be made the admin with zero auth.
Note line 304 the O is a 0:
bytes32 slot = ADMIN_SL0T;
comment: @dev Storage slot with the admin of the contract. This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is validated in the constructor.
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
// this is the getter
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
// return the memory at slot
adm := sload(slot)
}
}
// this is the setter, notice the 0 and the different hash
bytes32 internal constant ADMIN_SL0T = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6102;
// this doesn't set the same value as the getter, in effect the admin cannot be changed
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SL0T;
assembly {
// set the memory at slot to the value of newAdmin
sstore(slot, newAdmin)
}
}
https://bscscan.com/address/0x7e0c621ea9f7afd5b86a50b0942eae...> The hackers implemented a change in the ownership of the smart contract address.
bytes32 slot = ADMIN_SL0T;
https://bscscan.com/address/0x7e0c621ea9f7afd5b86a50b0942eae...
These kind of rug pulls are more uncommon but not rare, they give the developers some level of plausible deniability. Even so their actions after speak volumes.
What's interesting is to see how it will be dealt with. Most "DeFi" and cryptocurrency aficionados are quick to claim that "code is law", so we'll see whether they change their minds when their own money is at stake.
code might not reflect
the intentions
So now we need human judges to judge what the intention of a smart contract is?Well, wouldn't it already be quite a win if for 99.9% of the smart contract out there no human judge was needed?
It's an honest question: ain't it unthinkable that most could be fully automated and yet real courts could be used in rare cases and that that'd be already be quite an improvement? Or is the system only working if 100% of the time no human ruling is needed?
I have no idea...
Most modern DeFi exploits take advantage of unintended interactions between multiple smart contracts.
yes, this totally sounds not made up