DEVELOPER PERSPECTIVE | Rekt 2.0 – Your PhD in Next-Level Crypto Scams for The Overconfident Crypto Bro

Picture this, "Ocean's Eleven," but instead of George Clooney, we've got a bunch of nerds with keyboards trying to steal your digital lunch money.

The “I’m Too Smart to Fall for That” Syndrome

So, you think you’re the Sherlock Holmes of the blockchain world, eh? You scoff at those peasants who fall for “send ETH here, paste your private key, sign this very obscure transaction and connect your wallet here” scams. Well, prepare to have your digital ego bruised faster than you can say “gas fees.”

While true,

  • Never paste your wallet seed phrase anywhere regardless of the urgency. Yes, that email that takes you to a website that prompts you to connect your wallet and paste your seed phrase to continue, yeah, it’s probably a scam.
  • Never run code that you don’t fully understand what it does. “Earn passive yield using this bot. It’s been making me 1 ETH every week”. There is no free lunch my bro! That Solidity code that you got from the replies of a X(formerly Twitter) account advertising a yield generating bot, it’s 100% a scam.
  • Always triple check the wallet address before sending any coins. If dealing with a large transaction, send a small amount of test coins first.

…etc. You know the drill. Do everything that you were taught in that security 101 class when you first learnt about cryptocurrencies and blockchains.

 

Today, we’re gonna look at more sophisticated scams rather than common ones of send coins here, paste your seed phrase, click this link etc. The kind of scams we’ll be looking at target tech-savvy folks who are very familiar with blockchain concepts. Why do they get scammed then?

Well, it all boils down to greed my friend, greed.

 

 

The Impossible Dream Contract

You’re going through EtherScan, the block explorer, and notice a very peculiar verified smart contract,

 

 

Looking at the contract balance, you see 2 ether. Every single ounce in your body tells you that the above contract is exploitable. Just send 2 ether or more and get double the amount, seems like a sweet deal right?

WRONG.

Surprised? I told you scams are getting more sophisticated and you didn’t believe me. See now.

From the surface, it’s clear that given the contract’s balance of 2 ether, you just need to send 2 ether + 1 wei and you get 4 ether + 1 wei, double the profit isn’t it?

Now let me tell you why that thinking of yours is very wrong my good friend.

You see line 3, the ‘if’ statement, that ‘if’ statement creates an impossible conditional branch and you will never, I repeat, never land in that ‘if’ statement regardless of what you do. Even Vitalik Buterin and Gavin Wood can’t help you here.

But why is that so?

The value of msg.value flows directly into this.balance . What do I mean?

As long as msg.value has a value, the amount of this.balance will increase!

this.balance is just the contract’s balance. This means that there will be no single day, given the above contract, that msg.value will be greater than this.balance! It is literally impossible.

So you end up losing more than 2 ether in your attempts to exploit the contract 🙂

Don’t be surprised that the contract deployer, i.e scammer, has another contract deployed that links to this allowing him/her to withdraw your >2 ether trapped funds!

 

The Shadow Owner Switcheroo

You end up crying yourself to sleep and try again tomorrow.

The next day, you come across the below verified smart contract on EtherScan. This time, you do your research to not fall for another trick again because once bitten, twice shy!

 

 

You see two contracts here, Ownable and Throne

Contract Throne inherits from Ownable. You easily figure out that calling the function stake in contract Throne and sending more than 0 ether, you become the owner of the contract and the ether you sent while calling this function stake, becomes the largest stake.

With you being the owner, you can now call the function withdraw in contract Throne and you get sent the contract’s balance. You can’t call function withdraw unless you’re the contract owner as seen in the modifier onlyOwner in contract Ownable that Throne inherits from.

So, send > 0 ether, become owner, call withdraw and profit. Looking at the contract balance on Etherscan, you see that it’s 5 ether. The adrenaline rush kicks in and you think to yourself, every second that passes, the chances of someone else finding this contract increases tenfold.

So after double and triple checking, you give it a shot. You send 1 ether and check to see if you are the owner. Guess what, you’re not the owner! Lol, get rekt 😂😂😂

WTH is happening here?

Well, let me school you a bit. You see the variable owner, it has been defined twice. In contract Ownable and also in contract Throne

This is called variable shadowing. This ensures that the value of the variable is NEVER reassigned from the base contract Ownable, and guess where who the owner is, the scammer — as he sets his address as the owner in contract Ownable constructor.

Scammer 2, you 0.

 

The Mempool Mischief

You are a degen and a few losses here and there won’t deter you. As upset as you are, you go hunting the same day and come across the below contract.

 

 

This time the contract balance is 10 ether and guess what again, you don’t get anything. Why so and you had a very clear and genius plan?

  • passHasBeenSet is set to true when you checked so the require statement in line 9 passes smoothly
  • Call function setPass with your name but in hex, say 0xca7c8bf73e97c26e2dca88cfcfe972e4c09a9c0e0351e77125011c78454dcc65 as the parameter and sending more than 1 ether while calling this function. That long hex string you see, 0xca7c8bf73e97c26e2dca88cfcfe972e4c09a9c0e0351e77125011c78454dcc65 is just the SHA3 or fancily called keccack256 in Ethereum of the string Bill.
  • Next, call function getGift with Bill as the parameter. The require statement in line 17 will pass as hashPass, 0xca7c8bf73e97c26e2dca88cfcfe972e4c09a9c0e0351e77125011c78454dcc65, will be equal to keccack256(Bill)
  • After that, you are supposed to see 11 ether in your wallet. What went wrong here?  You ask yourself.

Well, nothing went wrong at all here. Your plan is very solid but you failed to account for one thing.

On Ethereum, the mempool, where transactions await to be put in a block, is public for anyone to see. This means that the scammer will see your transaction, front-run it by submitting a similar transaction but paying a higher gas fee (thanks to EIP 1559), making sure that a validator includes the scammer’s transaction first then yours second in the block. This means that the scammer will be the one getting the 11 ether, a 1 ether profit for the scammer!

All this can be automated by a bot which constantly views the mempool prying on innocent victim transactions who have the ambition of getting free money like yourself.

And just when you thought you cracked the code with your SHA3 wizardry? Welcome to the world of front-running, where your brilliant plan gets sniped faster than you can say ‘blockchain.’

 

The Linguistic Bamboozle

There is this fun one which also threw me off before figuring out what exactly is happening. Think you can figure it out now that you have experience being scammed?

 

 

Did you catch it? No, lemme show you a video on the same:

 

Remember when you thought learning “Hello, World!” in different programming languages was impressive? Well, how about a smart contract that reads differently based on which way you read it? It’s like a blockchain version of those Magic Eye pictures, except instead of seeing a hidden 3D image, you see your ETH disappearing!

The thing is that English isn’t the only language on the planet. There are languages like Hebrew which is typed right to left contrary to English which is typed left to right.

This means that the benign checkAndTransferPrize function is not as benign as you think. The function above is actually comparing n and p completely reversing the logic of the contract. This means that no matter how many times you guess, you will not be successful.

Pretty cool huh…

 

The Blind Trust Blunder

Then there’s this one for those who blindly trust websites initiating fund transfers. You just connect your MetaMask to the website and blindly approve transactions. I mean come on, haven’t you heard of ‘Do not trust, verify!’

Be extra careful when connecting to new websites you haven’t connected to before. Check the YouTube short below from Patrick Collins showing you how you can easily get rekt for this reckless behaviour.

 

 

 

The Short Address Long Con

There is also this one. A bit more technical but a really cool one, trust me. Bear with me as we deep dive.

Just when you thought you had it all figured out, along comes the short address attack. Suddenly, your 100 token withdrawal turns into 25,600 and you’re left wondering if you accidentally stumbled into a digital multiplication course.

When passing parameters to a smart contract, the parameters are encoded according to the Application Binary Interface(ABI) specification. It is possible to send parameters that are shorter than the expected parameter length (for example, sending an address that is only 38 hex characters (19 bytes) instead of the standard 40 hex characters (20 bytes)).

In such a scenario, the Ethereum Virtual Machine (EVM) will pad 0’s to the end of the parameters to make up for the expected length.

This becomes an issue when third-party applications do not validate inputs. The clearest example of this is an exchange that doesn’t verify the address of an ERC-20 token when a user requests a withdrawal.

Consider the standard ERC-20 transfer function interface:

function transfer(address to, uint tokens) public returns (bool success);

 

Now consider an exchange holding a large amount of a token (let’s say INC) and a user wishes to withdraw their share of 100 tokens.

The user would submit their address, 0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead and the number of tokens, 100.

The exchange would encode these parameters in the order specified by the transfer() function, i.e., address then tokens.

The encoded result would be:

a9059cbb000000000000000000000000deaddeaddeaddeaddeaddeaddeaddeaddeaddead000000000000000000000000000000000000000000000000056bc75e2d63100000

The first four bytes, a9059cbb are the transfer() function signature, the second 32 bytes are the addressto followed by the final 32 bytes which represent the number of tokens.

Notice that the hex 56bc75e2d63100000 at the end corresponds to 100 tokens (with 18 decimal places, as specified by the INC token contract).

 

Okay, so what?

 

Let’s look at what happens if we were to send an address that was missing 1 byte (2 hex digits). Specifically, let’s say an attacker sends 0xdeaddeaddeaddeaddeaddeaddeaddeaddeadde, as his address (missing the last two digits) and the same 100 tokens to withdraw. If the exchange doesn’t validate this input, it would get encoded as:

a9059cbb000000000000000000000000deaddeaddeaddeaddeaddeaddeaddeaddeadde00000000000000000000000000000000000000000000000056bc75e2d6310000000

The difference is very subtle.

Note that 00 has been padded to the end of the encoding, to make up for the short address that was sent. When this gets sent to the smart contract, the address parameter will read as 0xdeaddeaddeaddeaddeaddeaddeaddeaddeadde00 and the value will be read as 56bc75e2d6310000000 (notice the two extra 0’s).

This value is now 25,600 tokens (the value has been multiplied by 256). In this example, if the exchange held this many tokens, the user would withdraw 25,600 tokens (whilst the exchange thinks the user is only withdrawing 100) to the modified address.

Obviously, the attacker won’t possess the modified address in this example, but remember addresses in Ethereum are deterministic, meaning that they can be calculated prior to actually creating the address. This is the case for addresses creating contracts and also for contracts spawning other contracts. In fact, a created contract’s address is determined by:

keccak256(rlp.encode([<account_address>, <transaction_nonce>]))

 

An example function from pyethereum :

 

def mk_contract_address(sender, nonce):

    return sha3(rlp.encode([normalize_address(sender), nonce]))[12:]

 

Essentially, a contract’s address is just the keccak256 hash of the account that created it concatenated with the account’s transaction nonce. The same is true for contracts, except contracts’ nonces start at 1 whereas addresses’ transaction nonces start at 0.

This means that given an Ethereum address, we can calculate all the possible contract addresses that this address can spawn. For example, if the address 0x123000...000 were to create a contract on its 100th transaction, it would create the contract address

keccak256(rlp.encode[0x123...000, 100]), which would give the contract address 0xed4cafc88a13f5d58a163e61591b9385b6fe6d1a

This means that the attacker can easily bruteforce the desired address!

 


Think you could have evaded any of the discussed scams above? Which one?

Scams are getting more complex. In a land where money is poured into projects like how you pour water down a sink drain, scams will be everywhere.

 

So, my friend, if you thought you were the sharpest tool in the blockchain shed, think again. While you’re busy double-checking wallet addresses and inspecting smart contracts like a detective in a noir film, remember: the scammers are already three steps ahead, probably laughing at your attempts.

Stay sharp, stay safe, and for heaven’s sake, don’t fall for the old ;send ETH to this address’ trick. Until next time, may your wallets be full and your transactions secure. And remember, if it’s too good to be true, it probably is.

Cheers!

 

 

 

Follow us on X  for the latest posts and updates

Join and interact with our Telegram community

___________________________________________

___________________________________________