Upgrading the contract

In the previous section, we looked at the StableToken contract code, which is prone to integer overflow attacks. Once the bug is identified for a production contract, you can upgrade the implementation contract and deploy it to fix the issue. 

ZeppelinOS manages the upgrading of the contract logic and storage structure seamlessly. Let's now use the following steps to fix the integer overflow issue present in the StableToken contract:

  1. Manage the version of the project so that it becomes easy to track the changes that were introduced and fixed in a specific version of the contract. For that, let's bump the project version:
$ npx zos bump v2

This command will bump the project version from v1 to v2 and update the zos.json file accordingly.

  1. Change the code to fix the issues:
contract StableToken is Initializable {
//Introduced in version v2
address public minter;

event Transfer(address indexed _from, address indexed _to,
uint256 _value);

modifier onlyMinter() {
require(msg.sender == minter);
_;
}


//Fixed integer overflow issue in v2
function transfer(address _to, uint _amount) public returns
(bool) {
require(balances[msg.sender] >= _amount);
balances[msg.sender] -= _amount;
balances[_to] += _amount;

emit Transfer(msg.sender, _to, _amount);
return true;
}

function initializeMinter(address _minter) public {
require(minter == address(0));
minter = _minter;
}


function mint(uint _newTokens) public onlyMinter {
uint tempTotalSupply = totalSupply + _newTokens;
require(tempTotalSupply >= totalSupply);

totalSupply += _newTokens;
balances[minter] += _newTokens;
}

}

The actual code file is a bit large, so we have only shown part of the code. For the full code, you can head to this GitHub link: https://github.com/PacktPublishing/Mastering-Blockchain-Programming-with-Solidity/blob/master/Chapter11/contracts/StableToken_v2.sol. The code is kept in the StableToken_v2.sol file. You can now copy and paste this file into the project/contracts folder. Ensure that you remove the StableToken_v1.sol file from the folder, so that only a single StableToken contract definition is present in the contracts folder.

As you can see in the preceding code, we have fixed the integer overflow issue present in the transfer() function. We have also introduced an address minter variable to the contract, which has the permission to mint new tokens anytime via the mint() function. The minter user's address will be stored in a state variable—minter. Also, note that we have added the variable definition at the end of the preexisting state variables list. Later in this chapter, we will discuss the recommendations and precautions that need to be taken when adding new variables to the upgraded contract.

Also, note that a new function, initializeMinter(), has been added to initialize the minter state variable in the new contract version. We could have added a new parameter in the initialize() function itself; however, we cannot do this as the v1 version contract is already initialized, and, to add a new state variable in the existing contract, we need to add its initialization function separately. If you are deploying the contract for the first time, then you could add the parameters in the initialize() function itself.

  1. Deploy the new version of the StableToken contract, v2. However, one thing to note here is that, as of now, we are running and executing these contracts on the local blockchain, and to preserve the previous state of the blockchain, you must have kept the previous ganache-cli session running. In the case of testnet and mainnet, you do not have to worry about it. Our contract code is ready, so we can first push the contract that will deploy the v2 version of the StableToken contract:
$ npx zos push

This command would generate the following output:

Validating contract StableToken
- New variable 'address minter' was added in contract StableToken in contracts/StableToken.sol:1 at the end of the contract.
See https://docs.zeppelinos.org/docs/writing_contracts.html#modifying-your-contracts for more info.
Uploading StableToken contract as StableToken
Deploying logic contract for StableToken
Updated zos.dev-1557538865119.json

As you can see in the preceding command output, zos identifies that the new address minter variable is added into the contract; it also validates that the new state variable is correctly added at the end of the contract. Then, it proceeds with the deployment of the logic contract.

  1. As the logic contract is deployed, let's update the Proxy contract with the new implementation and initialize the minter address by calling the initializeMinter function on the contract. In the following command, we are sending a second public key from the accounts generated with ganache-cli, as we want to give that account minter rights:
$ npx zos update StableToken --init initializeMinter --args 0x4cfae0c67f1b831d331934aec4cf437da6043bd5

The preceding command would generate the following output:

Using session with sender address 0x0421E4eB85b5a8443A8Fd5cc8ab3FfA0B723Db26, timeout 600 seconds
Upgrading proxy to logic contract 0x1E46054894464408F200eF48a2fc16a5f213E7Fa and initializing by calling initializeMinter with:
- _minter (address): "0x4cfae0c67f1b831d331934aec4cf437da6043bd5"
Upgrading proxy at 0xF2A348783dC30b8219854b647fA157448256deeE and calling initializeMinter with:
- _minter (address): "0x4cfae0c67f1b831d331934aec4cf437da6043bd5"...
TX receipt received: 0xec93c41d2008cddf845d658a6bda562f2c7c330ccc0a2d57642a09923d463092
Instance at 0xF2A348783dC30b8219854b647fA157448256deeE upgraded
0xF2A348783dC30b8219854b647fA157448256deeE
Updated zos.dev-1557590753547.json

As you can see, the address of the proxy remains the same as 0xF2A348783dC30b8219854b647fA157448256deeE; however, the implementation logic contract has changed. Also, we have added a new state variable, address minter, which has also been initialized with the address passed in from the command.

Now that everything is done and updated, the proxy points to the new version, the v2 implementation of the StableToken contract. To verify this, we can check the current status as follows:

$ npx zos status

The command will generate the following output:

Project status for network dev-1557538865119
Application contracts:
- StableToken is deployed and up to date
Deployed proxies:
- project/StableToken at 0xF2A348783dC30b8219854b647fA157448256deeE version v2

As you can see, the new version of the contractv2, is being used by the proxy. As you can see, the proxy address, 0xF2A348783dC30b8219854b647fA157448256deeE, remains the same in version v1 and version v2.

We can also check that the new variables are properly initialized, and old variables remain intact in the contract. To check this, we can use truffle console and run the following command:

$ truffle console --network local

The command will open the truffle console Command Prompt as truffle(local)>, under which you can run the following command. Make sure to use the deployed proxy address in the following command:

truffle(local)> st = await StableToken.at('0xF2A348783dC30b8219854b647fA157448256deeE')

The preceding command will initialize an internal variable, st, in Command Prompt, which you can use to call the functions on the contract:

truffle(local)> st.name()
'StableToken'
truffle(local)> st.owner()
'0x0421E4eB85b5a8443A8Fd5cc8ab3FfA0B723Db26'
truffle(local)> st.minter()
'0x4cFAE0c67F1b831D331934AEC4cF437dA6043bd5'

As you can see, all the existing variables from contract version v1 are intact, and the new minter state variable, added in version v2, returned the minter's address.

During the contract deployment and upgrade processes, we used some of the zos commands. However, there are many other commands that you can use according to your needs. Let's look at the zos supported commands.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.180.71