Spoof and Sniffing protection, and a dead Krakin’t contract…

It is always the same old story of adding something new, realizing an improvement and never putting together everything before and after a deployment. So, what if someone put a Trojan on my machine and got the secret key to a contract owner address or what if the contract owner private key got lost for whatever reason ? Well, there is a solution… Make two owners! So I did and then realized my stupid mistake which costed me $180.00. In any-way it is better than costing me the whole project, and now I can finally relax.

If you go to a contract: 0x4180CE5a616E75512fd9DF0bd896AC955C64a246 you will see two owner addresses, added just a few minutes before the deployment, and now… I have to do the whole deployment thing again.

The problem is, if the first contract owner is stolen, they can simply change the second one and there is no purpose at all to having the second one… this means that we had to imply a mechanism that does not contradict the purpose of two owners… so after a careful examination, the Owned contract became this:

contract Ownable is Context {
address private _owner;
address private _failsafeOwner; //failsafe
bool private setFailsafeOwner = false;

event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

bool private ownershipConstructorLocked = false;
constructor() {
if (!ownershipConstructorLocked) {
address msgSender = _msgSender();
_owner = msgSender;
_failsafeOwner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
ownershipConstructorLocked = true;
}
}

function owner() public view returns(address) {
return _owner;
}

function failsafe() internal view returns(address) {
return _failsafeOwner;
}

modifier onlyOwner() {
require(_owner == _msgSender(), “Ownable: caller is not the owner”);
_;
}

modifier allOwners() {
require(_owner == _msgSender() || _failsafeOwner == _msgSender(), “Ownable: caller is not the owner”);
_;
}

modifier onlyFailsafeOwner() {
require(_failsafeOwner == _msgSender(), “Ownable: caller is not the failsafe owner”);
_;
}

// We do not want this to be executed under any circumstance
// function renounceOwnership() public virtual onlyOwner {
// emit OwnershipTransferred(_owner, address(0));
// _owner = address(0);
// }

function initiateFailsafeOwner(address newOwner) public virtual onlyOwner {
require(!setFailsafeOwner);
_failsafeOwner = newOwner;
setFailsafeOwner = true;
}

function transferOwnership(address newOwner) public virtual allOwners {
require(newOwner != address(0), “Ownable: new owner is the zero address”);
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}

function changeFailsafeOwnerAddress(address newOwner) public virtual onlyFailsafeOwner {
require(newOwner != address(0), “Ownable: new owner is the zero address”);
_failsafeOwner = newOwner;
}

}

DONE !

The thing that is happening there is that we have the _failsafe owner and the boolean that locks the setup of the _failsafe. Now, the failsafe owner becomes the super-owner and the owner just the owner. This way, if we keep the super-owner account safe and locked we will never have to worry about the token and the project getting stolen or hacked. If it does get stolen/hacked, it is very easy to take it back… However, if you really want to be paranoid, you can follow the comment:

//Failsafe is an address-key pair generated offline in case the original owner is sniffed or spoofed.
//Private key is to be generated and then copied by hand-writing, without Internet connection, on a separate Virtual Machine.
//Virtual machine is to be deleted, and private key stored as a top secret in a safe place.

The private-public keypairs can be generated offline (can be coded too) and nobody in the world would know what those pairs were.

Enjoy the extreme safety of the block-chain !