Simple question but I couldn’t find the answer anywhere.
How to know if the code of my contract is used in a CALLCODE or DELEGATECALL by third party sinceaddress(this)returns the address of the caller instead of the address of the contract if I’m not wrong ?

  • Of course, it’s possible that I’m wrong and address(this) returns always the same address even in a CALLCODE environment. – user2284570 Apr 11 at 12:51
  • I'm curious why you want to do this? – Tjaden Hess Apr 11 at 23:33
  • @TjadenHess for the sole purpose of preventing third parties doing it. – user2284570 Apr 12 at 2:32

Simple way

uint private constant MAGIC = ...; // Your birthday here
uint private magic = MAGIC;

function isDelegated () internal view return (bool) {
  return magic != MAGIC;

The idea is that MAGIC is compile-time constant, so it will be embedded into the byte code by Solidity, but magic is state variable. When contract is called normally, magic == MAGIC is true, but in case of CALLCODE or DELEGATECALL, your code will observe storage of the calling contract, thus magic will most probably contain something other than MAGIC. Though this approach may be easily cheated by calling contract, so it protects only from accidental, but not from malicious use.

Reliable approach

You need to save real deployment address of your contract, and then in method you need to compare address(this) with saved address. The problem is that you cannot save deployment address into storage, because storage will not be available when your contract is called via CALLCODE or DELEGATECALL, so you need to save deployment address into your smart contract's byte code. It is possible to modify byte code in constructor of smart contract, though this will require some assembly programming. Simpler way would be to modify byte code before publishing deploy transaction. You will just need to predict contract address, which is actually possible, because contract address is derived from address of whoever deployed the contract and transaction nonce. So, you need to do something like this:

function isDelegated () internal view returns (bool) {
  return address (this) != 0x0123456789012345678901234567890123456789;

And before deploying your contract you need to:

  1. Find out address the contract will be deployed at
  2. Replace 0123456789012345678901234567890123456789 in contract's byte code with this address
  3. Deploy contract as usual but with modified byte code

And after this isDelegated will return accurate result.

BTW, Solidity protects libraries form being called directly, and I believe that is uses byte code modification in constructor technique, as described above, to achieve this.

  • No this won’t work because calling contract can trick the values. I don’t only want to check but prevent. – user2284570 Apr 11 at 14:05
  • Usually, address(this) returns address of this contract, not calling one. But in case this contract was called via CALLCODE or DELEGATECALL it returns address of calling contract, or, more precisely, it returns whatever it returned for calling contract. – Mikhail Vladimirov Apr 11 at 14:05
  • Reliable approach is impossible to cheat – Mikhail Vladimirov Apr 11 at 14:05
  • How to ensure 0x0123456789012345678901234567890123456789 will be encoded in code and not as an ꜱꜱᴛᴏʀᴇ constent ? – user2284570 Apr 11 at 14:07
  • All literals are always in code. All store variables should be explicitly declared. Solidity never puts anything into store by its own. – Mikhail Vladimirov Apr 11 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.