(Part 19) Ethereum Solidity - ERC223 Mutability, Mutable Contract Implementation And Hacking Mutable Contracts(PT 19)

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@igormuba·
0.000 HBD
(Part 19) Ethereum Solidity - ERC223 Mutability, Mutable Contract Implementation And Hacking Mutable Contracts(PT 19)
# If you like what you read, resteem and upvote this post to show appreciation for the knowledge shared! Your followers might find this useful :)

#### Repository
https://github.com/igormuba/EthereumSolidityClasses/tree/master/class19

#### What Will I Learn?
- How to turn the ERC223 contract (implemented in the previous class) mutable
- Outsourcing functions
- Security and how hacking a mutable contract works

#### Requirements

- Internet connection
- Code editor
- Browser

#### Difficulty

- Advanced

#### Tutorial Contents

[On the last tutorial](https://steemit.com/utopian-io/@igormuba/part-18-ethereum-solidity-pt-18) I have shown what the ERC223 standard is, how to make an ERC223 ICO and how to turn your "old" ERC20 to ERC223.

ERC223 is an "evolution" of ERC20, and it makes your contract more "fool-proof", protecting the users from themselves.

The key thing I want you to pay attention to this tutorial is the "turn ERC20 to ERC223". The blockchain is immutable, once you deploy a contract the storage of it can't be changed. But I have also taught how can you "exploit" a feature of the Ethereum compiler to make a mutable contract, You can read more about it on these two tutorials
[(Part 3) Ethereum Solidity Development - Contract Mutability, DelegateCall And Calling Functions By Address(PT 3)](https://steemit.com/utopian-io/@igormuba/part-3-ethereum-solidity-development-contract-mutability-delegatecall-and-calling-functions-by-address-pt-3)
[(Part 4) Ethereum Solidity Development - Inheritance, Working With Multiple Contracts And Simple Mutability(PT 4)](https://steemit.com/utopian-io/@igormuba/part-4-ethereum-solidity-development-inheritance-working-with-multiple-contracts-and-simple-mutability-pt-4)

But, so far, everything was too theoretical. 

In case we discover that the ERC223 is still not good enough, but you have already deployed a contract that has a couple thousand users, it would be a pain to alert everyone that you are "forking" the contract. Forks of contracts have happened before, MCO (crypto, old MCO), have faced issues before and had to stop transactions on the old contract and exchange everyone's tokens to the new ones from the new contract, [some people had issues with that](https://github.com/paritytech/parity-ethereum/issues/5967).

One way to avoid such headaches is to make your contract mutable. I want to show you with practical examples of how you can make an ERC223 contract mutable.

For this, first, you need to get the [immutable version of the contract](https://github.com/igormuba/EthereumSolidityClasses/tree/master/class19/ImmutableVersion) we are going to use, as it would be repetitive to go over the ERC223 standard again. We will focus on effectively making it mutable

**NOTE:** Some people argue if mutable smart contracts are morally right or wrong. Personally, I think for most cases it would be unfair to the user to make a mutable contract, as it avoids the trustless nature of blockchain, but I understand that some business models require an evolving and ever improving code. This tutorial is for information and knowledge sharing purposes only, do not use any code taught here for final production because the security techniques used are minimal and below the needs of a real-world product, else this tutorial would be more extensive and hard than needed.

# The outsourced transfer manager contract

First, grab the full immutable version of the contract [from here](https://github.com/igormuba/EthereumSolidityClasses/tree/master/class19/ImmutableVersion), this contract was built on the last class.

There are 2 files in there, required for the ERC223 contract to work.

All of the logic, variables are exactly the same as the code from the GitHub mentioned above, and it is inside a file I called `ERC223Core.sol`, it will host the minimum amount of information possible! So if a bug is found down the line, we can change the outsourced contract to a better one!

On the import section of the core contract, import the new file with
```
import "browser/ERC223Transfers.sol";
```

Fill the `ERC223Transfers.sol` with an empty contract

```
pragma solidity ^0.5.0;

contract ERC223Transfers{
    
}
```
And on the core contract set, it's variable so we can set it's address later
```
ERC223Transfers private transferManager; //the variable to manage the outsourced contract
```

# Outsourcing the transfers

Right off the bat, copy all the imports, variables, events and transfer functions(do not delete from the original contract) and paste them on the outsourced contract

On the transfer, manager contract set the core address with
```
    address private _core; //address of the core
    bool private _coreSet; //keeps track to set core only once
```
And create a function to set the core
```
    function setCore(address _coreAddress) public{
        require(!_coreSet); //requires that core is not already set (core is immutable)
        _coreSet=true; //records that this function was called
        _core = _coreAddress; //sets core address
    }
```

Also, on the core contract, create a function to set the transfers contract, but the variable on the core can be changed, it is mutable!

```
    function setTransferManager(address _transferManager) public{
        require(msg.sender==_creator); //requires caller is the contract creator
        transferManager = ERC223Transfers(_transferManager); //sets the address of the transfers manager
    }
```


Now we will have to gather and send to the outsourced contract all the possible information we might need it to access in the future. The core contract is immutable, so, once it is deployed, if in the future you require a string or whatever to be sent to the transfers contract, you will have a bad time. We want the transfer contract to deal with everything, the core will only call the functions!

You will have, on the transfer manager contract, to change on the `transfer` functions all the `msg.sender` to `_sender`, and make the function accept one more argument, the sender, which will be passed to it from the core contract.

Also, you need to require that the caller is the core contract.


# Transfer functions on manager and core contracts
Here is an example of the transfer with data, the transfer without data is similar but with an empty data instead, just like discussed in other tutorials, so I won't repeat code, but you will have to change the 2 `transfer` functions to match the pattern.

Transfer from the transfer manager contract
```
//receives one more argument, address _sender
    function transfer(address _sender, address _receiver, uint _amount, bytes memory _data) public returns (bool) {
    require(msg.sender==_core); //requires that caller is core

//the code below was explained in other classes
//will point only the changes
        if (_balance[_sender]>=_amount&&_amount>0){ //balance of _sender instead of msg.sender
            uint codeLength;
            assembly {
                codeLength := extcodesize(_receiver)
            }
            if(codeLength>0){
                ERC223Receiver erc223Receiver = ERC223Receiver(_receiver);
                erc223Receiver.tokenFallback(_sender, _amount, _data);//_sender instead of msg.sender
            }
            _balance[_sender]-=_amount;//reduces balance of _sender not msg.sender
            _balance[_receiver]+=_amount;
            emit Transfer(_sender, _receiver, _amount); //emits event for _sender instead of msg.sender
            return true;
        }else{
            return false;
        }
    }
```

Transfer from the core contract
```
    function transfer(address _receiver, uint _amount, bytes memory _data) public returns (bool) {
        return transferManager.transfer(msg.sender, _receiver, _amount, _data); //passes msg.sender to manager
    }
```

Notice the change and apply on the transfer without data

# Transfer FROM functions on transfer manager and core contracts

Now, we will apply a similar logic on the `transferFrom` function, again, this time I will show you the logic on the function without data, but you will have to execute the changes both on the function that takes data as an argument and the function that does not.

Again, commenting only the changes as this function was discussed on both ERC20 and ERC223 classes

`transferFrom` on the transfer manager contract
```
//receives the _caller from the core
    function transferFrom(address _caller, address _sender, address _receiver, uint _amount) public returns (bool){
        if (_balance[_sender]>=_amount&&_amount>0){
            if (_allowed[_sender][_caller]>=_amount){ //changed msg.sender to _caller
                uint codeLength;
                assembly {
                    codeLength := extcodesize(_receiver)
                }
                if(codeLength>0){
                    bytes memory empty;
                    ERC223Receiver erc223Receiver = ERC223Receiver(_receiver);
                    erc223Receiver.tokenFallback(_caller, _amount, empty); //changed msg.sender to _caller
                }
                _allowed[_sender][_caller]-=_amount; //reduces allowance from _caller instead of msg.sender
                _balance[_sender]-=_amount;
                _balance[_receiver]+=_amount;
                emit Transfer(_sender, _receiver, _amount);
                return true;
            }else{
                return false;
            }

        }else{
            return false;
        }
    }
```

`transferFrom` on the core contract
```
    function transferFrom(address _sender, address _receiver, uint _amount) public returns (bool){
        return transferManager.transferFrom(msg.sender, _sender, _receiver, _amount);
    }
```

#  Outsourcing the variables

Now we will go one step further and create another contract to outsource the token data, users balances, and allowances

I have created a contract called ERC223Variables.sol
```
pragma solidity ^0.5.0;

import "browser/ERC223Receiver.sol";

contract ERC223Variables{
    
}
```

First thing, import this new contract into the core and make the variable that will manage the data from it, just like before, but this time does the same to the transfers file!

![image.png](https://files.steempeak.com/file/steempeak/igormuba/Bo3avICz-image.png)
![image.png](https://files.steempeak.com/file/steempeak/igormuba/8Xu4N0kA-image.png)

On the core and transfer files, create the functions and variables to set the variables file

on the core
```
ERC223Variables private variablesManager; //creates manager variable
    function setVariablesManager(address _transferManager) public{
        require(msg.sender==_creator); //requires caller is the creator
        variablesManager= ERC223Variables(_transferManager); //sets the address of variables manager
    }
```

on the transfers
```
    ERC223Variables private variablesManager; //variable manager
    function setVariablesManager(address _variablesManager) public{
        require(msg.sender==_creator); //requires caller is creator, mutable variable
        variablesManager=ERC223Variables(_variablesManager); //sets address of variables manager
    }
```

# Outsourcing the variables

The variable contract will have all the variable related functions and the variables themselves, excluding allowance, we will skip the allowance and leave them for the transfer contract (for now!)

The only special piece of code on the variables contract is the constructor and the "secondary constructor"

```
bool variablesConstructed; //keeps track is "second constructor" was called
    constructor() public{
        _creator = msg.sender; //sets caller as creator
    }
    
    function variablesConstructor(string memory tokenName, string memory tokenSymbol, uint totalSupply) public{
        require(msg.sender==_creator); //requires caller is the creator
        require (!variablesConstructed); //requires this contract was not yet constructed
        _tokenName=tokenName; //sets token name
        _tokenSymbol=tokenSymbol; //sets token symbol
        _totalSupply=totalSupply; //sets supply
        _balance[_creator]=_totalSupply; //gives supply to the creator
    }
```

# Outsourcing transfer variables, variables side

Now we must connect the variables contract with the transfers contract (skip the allowance for now)
Start by telling the variables contract who is the transfers contract

So, on the variables contract
```
ERC223Transfers private transferManager;
address private transferManagerAddress;

    function setTransferManager(address _transferManager) public{
        require(msg.sender==_creator);
        transferManager=ERC223Transfers(_transferManager);
    transferManagerAddress=_transferManager;
    }
```

This is necessary so that we can create functions to change the user's balance, but only the transfer manager contract can do that!

On the variables, the key functions to allow that are

```
    function balanceOf(address _owner) public view returns(uint){
        return _balance[_owner]; //returns balance
    }
    
    function setBalance(address _owner, uint _amount) public{
        require(msg.sender==transferManagerAddress);
        _balance[_owner]=_amount;
    }
```

One so that the transfers contract can see the user balance, the other so that the transfer contract can edit the user balance

# Outsourcing transfer variables, transfer side

Now, on the transfer manager contract, we need to work by refactoring the functions so they fetch the balance from the user, do the calculation, and tell the contract the new balance

There is one funny trick to do the refactoring faster!

Delete the variable that holds the users' balance and compile! The compiler will do the favor to show all the errors where you have to outsource the balance operations :)

I won't show the code for all the functions because there are 4 functions that are too similar, so it would be tedious to say the same thing 4 times, so, here is the most complete function, the transfer from with data, with comments highlighting the changes

```
    function transferFrom(address _caller, address _sender, address _receiver, uint _amount, bytes memory _data) public returns (bool){
        uint senderFinalBalance = variablesManager.balanceOf(_sender); //fetches balance form variables contract
        if (senderFinalBalance>=_amount&&_amount>0){ //compares to fetched variable
            if (_allowed[_sender][_caller]>=_amount){
               uint codeLength;
               assembly {
                    codeLength := extcodesize(_receiver)
                }
                if(codeLength>0){
                    ERC223Receiver erc223Receiver = ERC223Receiver(_receiver);
                    erc223Receiver.tokenFallback(_caller, _amount, _data);
                }
                _allowed[_sender][_caller]-=_amount;
                //sender balance
                variablesManager.setBalance(_sender, senderFinalBalance-_amount); //sets the new balance of sender
                //receiver balance
                variablesManager.setBalance(_receiver, variablesManager.balanceOf(_receiver)+_amount); //new receiver balance
                emit Transfer(_sender, _receiver, _amount);
                return true;
            }else{
                return false;
               }
    
        }else{
            return false;
        }
    }
```

# Outsourcing allowance

The last thing is to outsource the allowance to the variables manager

On the outsourced variables manager
```
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
mapping (address => mapping (address => uint)) private _allowed; //allowance
//added the _owner on the arguments
    function approve(address _owner, address _spender, uint _amount) public returns(bool){ 
        _allowed[_owner][_spender] = _amount; //allower is the _owner, not msg.sender
        emit Approval(_owner, _spender, _amount);//allower is the _owner, not msg.sender
        return true;
    }
```

On the core
```
    function approve(address _spender, uint _amount) public returns(bool){
        return variablesManager.approve(msg.sender, _spender, _amount);
    }
```

On the transfer, the manager is where we will have more work. Start with the trick of deleting the approval allowance so you can better see where are the things you need to change!
![image.png](https://files.steempeak.com/file/steempeak/igormuba/fWUVmBZc-image.png)

On the transfer you have to, basically, change all the `_allowed[_sender][_caller]` to `variablesManager.allowance(_sender, _caller)`

And instead of reducing the allowance locally, we will fetch the allowance form the variables manager, reduce from it the amount, and change the approved allowance, like this
```
                //change caller allowance
                variablesManager.approve(_sender, _caller, (variablesManager.allowance(_sender, _caller)-_amount));
```

# Testing

The core of the mutable contract is done, the balance storage and the calculation part are the only things you would most likely have to change in case of a hack or vulnerability discovered, and we have already outsourced them. The storage of the contract has been outsourced to a contract that manages the variables, the calculations have been outsourced to a contract that only does the calculation and don't store the balances.


So, let us see if the outsourcing works

With the wallet 0xca35b7d915458ef540ade6068dfe2f44e8fa733c I am deploying all 3 contracts

You will have to tell all the contracts to each other who is who like I have done below

![image.png](https://files.steempeak.com/file/steempeak/igormuba/lMenY55o-image.png)

After this, everything can be done from the core

I have successfully transferred tokens as if it were all just one contract (except the gas costs are extremely high)
![image.png](https://files.steempeak.com/file/steempeak/igormuba/X9c0nSFv-image.png)

Now the real test!

# Is it mutable?

I have arrived at the end of this tutorial too tired to think about a good test, so let us do a bad test, an EVIL test actually! I am doing this to show the dangers of mutable contracts. As the contract is mutable, someone may hack the creator and gets access to the wallet that controls.

Let us change the transfers contract, so whenever someone transfers something the tokens actually go to the wallet 0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db instead of the real receiver!

Right now the balance of that wallet is zero

![image.png](https://files.steempeak.com/file/steempeak/igormuba/56rF49iV-image.png)

I have changed the part that adds the value to the receiver to
```
            address hackerAddress=0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB; //hacker addres
            variablesManager.setBalance(hackerAddress, variablesManager.balanceOf(hackerAddress)+_amount);
```

Using the creator wallet, I compile and deploy the new transfer manager

**NOTE:** when deploying the new contract, don't forget to set the new transfer address to the core and the variables, and the old core and variables addresses to the transfers, this gave me a 10 minutes headache trying to figure out

And if the user 0x14723a09acff6d2a60dcdf7aa4aff308fddc160c that has recevied, previously, 10 tokens from the creator, send 5 back to the creator

By reading the transaction data **THERE IS NO WAY YOU WOULD KNOW SOMETHING IS WRONG**
![image.png](https://files.steempeak.com/file/steempeak/igormuba/FnaS5o6N-image.png)

But the creator should have 95 tokens now and he has 90 because he has never received it!
![image.png](https://files.steempeak.com/file/steempeak/igormuba/DoGy1EW7-image.png)

The sender sent successfully and went from 10 tokens to 5
![image.png](https://files.steempeak.com/file/steempeak/igormuba/9EKDXswX-image.png)

And the hacker has the difference!
![image.png](https://files.steempeak.com/file/steempeak/igormuba/bHnWWb7s-image.png)

The mutable contract has successfully hacked.

Of course, a real hack would not be too easy, as I imagine you don't leave your private keys hanging around anywhere, you probably save them in somewhere safe, a mutable contract is as safe as the creator is morally good and cares about his keys security.

# If you like what you read, resteem and upvote this post to show appreciation for the knowledge shared! Your followers might find this useful :)

#### Curriculum

- [(Part 18) Ethereum Solidity - ERC20 ICO, Conversion To ERC223 And "Fool-Proofing" The Contract(PT 18)](https://steemit.com/utopian-io/@igormuba/part-18-ethereum-solidity-pt-18)
- [(Part 17) Ethereum Solidity - ICO Contract, Basic Security And Token Interaction(PT 17)](https://steemit.com/utopian-io/@igormuba/part-17-ethereum-solidity-ico-contract-basic-security-and-token-interaction-pt-17)
- [(Part 16) Ethereum Solidity - ERC721 Third Party Approval, Transfer, Events And Full Implementation(PT 16)](https://steemit.com/utopian-io/@igormuba/part-16-ethereum-solidity-erc721-third-party-approval-transfer-events-and-full-implementation-pt-16)
- [(Part 15) Ethereum Solidity - ERC165, ERC721, Their Relation, Balances And Transfer Functions(PT 15)](https://steemit.com/utopian-io/@igormuba/part-15-ethereum-solidity-erc165-erc721-their-relation-balances-and-transfer-functions-pt-15)
- [(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transactions With Unique Tokens(PT 14)](https://steemit.com/utopian-io/@igormuba/part-14-ethereum-solidity-token-uniqueness-non-fungibility-and-transacions-with-unique-tokens-pt-14)
- [(Part 13) Ethereum Solidity In Truffle - Testnet Environment Function Calls And Truffle Testing(PT 13)](https://steemit.com/utopian-io/@igormuba/part-13-ethereum-solidity-in-truffle-testnet-environment-function-calls-and-truffle-testing-pt-13)
- [(Part 12) Ethereum Solidity - Using Truffle, Ganache And Zeppelin To Deploy(PT 12)](https://steemit.com/utopian-io/@igormuba/part-12-ethereum-solidity-using-truffle-ganache-and-zeppelin-to-deploy-pt-12)
- [(Part 11) Ethereum Solidity - Multisig Contract As Bank,k Multiple Users, And Where To Implement App Logic(PT 11)](https://steemit.com/utopian-io/@igormuba/part-11-ethereum-solidity-multisig-contract-as-bank-k-multiple-users-and-where-to-implement-app-logic-pt-11)
- [(Part 10) Ethereum Solidity - Multiple inheritances, Diamond Problem And Function Polymorphism(PT 10)](https://steemit.com/utopian-io/@igormuba/part-10-ethereum-solidity-multiple-inheritance-diaomond-problem-and-function-polymorphism-pt-10)
- [(Part 9) Ethereum Solidity Assembly - Return, Memory, Hexadecimal, Pointers, And Memory Addressing(PT 9)](https://steemit.com/utopian-io/@igormuba/part-9-ethereum-solidity-assembly-return-memory-hexadecimal-pointers-and-memory-addressing-pt-9)
- [(Part 8) Ethereum Solidity - Assembly, Reducing Costs And Creation Your Low-Level Expression(PT 8)](https://steemit.com/utopian-io/@igormuba/part-8-ethereum-solidity-assembly-reducing-costs-and-creation-your-low-level-expression-pt-8)
- [(Part 7) Ethereum Solidity - Fallback, Ethereum Fractions, And Collateral Backed Contract(PT 7)](https://steemit.com/utopian-io/@igormuba/part-7-ethereum-solidity-fallback-ethereum-fractions-and-collateral-backed-contract-pt-7)
- [(Part 6) Ethereum Solidity - Custom Variable Functionalities, Libraries, Using Libraries For Security(PT 6)](https://steemit.com/utopian-io/@igormuba/part-6-ethereum-solidity-custom-varaible-functionalities-libraries-using-libraries-for-security-pt-6)
- [(Part 5) Ethereum Solidity - Custom Access Modifiers, Security Breach Alerts, Assert And Require(PT 5)](https://steemit.com/utopian-io/@igormuba/part-4-ethereum-solidity-custom-access-modifiers-security-breach-alerts-assert-and-require-pt-4)
- [(Part 4) Ethereum Solidity Development - Inheritance, Working With Multiple Contracts And Simple Mutability(PT 4)](https://steemit.com/utopian-io/@igormuba/part-4-ethereum-solidity-development-inheritance-working-with-multiple-contracts-and-simple-mutability-pt-4)
- [(Part 3) Ethereum Solidity Development - Contract Mutability, DelegateCall And Calling Functions By Address(PT 3)](https://steemit.com/utopian-io/@igormuba/part-3-ethereum-solidity-development-contract-mutability-delegatecall-and-calling-functions-by-address-pt-3)
- [(Part 2) Ethereum Solidity Development - Deploying, Security And ERC20 Compliance(PT 2)](https://steemit.com/utopian-io/@igormuba/part-2-ethereum-solidity-development-deploying-securiy-and-erc20-compliance-pt-2)
- [(Part 1) Ethereum Solidity Development - Getting Started + Lower Level Explanation (PT 1)](https://steemit.com/utopian-io/@igormuba/part-1-ethereum-solidity-development-getting-started-lower-level-explanation-pt-1)

# Beneficiaries

This post has as beneficiaries
[@utopian.pay](https://steemit.com/@utopian.pay) with 5%
using the SteemPeak beneficiary tool
![image.png](https://steemitimages.com/0x0/https://files.steempeak.com/file/steempeak/igormuba/CZTbpzrU-image.png)
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,