- To obfuscate the input so that etherscan cannot decode it : YES.
- To hide your contract's activity (ERC20 transfer): NO.
Although you can obfuscate and hide your input data, people can see your contract interacting with ERC20 address and use transfer & approve on that contract address. They can simply look at the Internal transactions
or Log
tab on etherscan to view it easily.
To obfuscate the input, it's actually quite simple, change your function name to some random string and change your function signature to use some encoded bytes. The simplest method for encode and decode is to use XOR operator. using the code below and do not submit ABI or source code to Etherscan, it would help you to avoid etherscan decoding your input.
uint256 constant not_secret = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;
function random_obfuscated_string_0x1234567890(uint256 a, uint256 b) public{
address real_addr_a = address(uint160(a ^ not_secret));
address real_addr_b = address(uint160(b ^ not_secret));
}
To encode data you do the same thing , XORing with not_secret
. As the name suggest, it's not a secret and its only purpose is to prevent etherscan. It also doesn't protect your contract from being revert engineered or disassembled by other users if they want to do it.
I would not recommend doing it though, because it doesn't help anything other than preventing the Input Data
field from being decoded. People still can see "Token Transfered", "Internal Transactions", and "Logs". All these things clearly expose what your contract buy and sell.
Related question : How to obfuscate solidity smart contract
Update: OP asks for the step-by-step guide. So here it is (you have to understand these concepts (XOR cipher - symmetric encryption and the above description about what your contract can hide) before using it, otherwise it's very dangerous to copy and use online answers for solidity without understanding it fully:
Step 1. Choose a cipher key, it's the not_secret
constant here. You can change it to any random number.
Step 2. Use the key to encrypt your input: Example:
Token_1: 0x55d398326f99059ff775485246999027b3197955
Encrypt Token_1 using the key not_secret
:
Encrypted_token_1 = uint256(uint160(token2)) ^ not_secret = 50801780122331352337026042894364481186943364210072012998642427539196337619350
Token 2: 0x2170Ed0880ac9A755fd29B2688956BD959F933F8
Encrypted_token_2 = uint256(uint160(token2)) ^ not_secret =
50801780122331352337026042894659144872731148500323806259612097858952170752827
Step 3. Use Encrypted_token_1 and Encrypted_token_2 as input of the function:
random_obfuscated_string_0x1234567890(50801780122331352337026042894364481186943364210072012998642427539196337619350, 50801780122331352337026042894659144872731148500323806259612097858952170752827)
Step 4. The contract decrypts the input data using the same key to get the original addresses 0x55d39... and 0x2170Ed... .
To encrypt and decrypt, it's better to write your own code because online services may use different padding, hard to guess how they implement.
You can craft a local contract like this to test (e.g. on remix):
contract Test{
uint256 constant not_secret = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;
function decrypt(uint256 a, uint256 b) public view returns (address, address) {
address real_addr_a = address(uint160(a ^ not_secret));
address real_addr_b = address(uint160(b ^ not_secret));
return (real_addr_a, real_addr_b);
}
function encrypt(address token1, address token2) public view returns (uint256, uint256){
return (uint256(uint160(token1)) ^ not_secret, uint256(uint160(token2)) ^ not_secret);
}
}
I used encrypt
function in this contract to produce the outputs in step 2 above.
Extra: Using uint160 for the key not_secret
is considered simpler for the code and you may be able to use some online service to check encrypt-decrypt, you may try.