Questions on upgradeable contracts and events

Hi @MWaser

Yes.

You may want to look at the Interacting Programmatically guide and using OpenZeppelin Contract Loader.

Yes.

Though as far as I am aware events don't impact contract storage (for upgradeable contracts). I will confirm on this topic: Using events in upgradeable contracts?

I assume so too.


To try this out, I created a project for the Box contract

Box.sol

// contracts/Box.sol
pragma solidity ^0.5.0;

contract Box {
    uint256 private value;

    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);

    // Stores a new value in the contract
    function store(uint256 newValue) public {
        value = newValue;
        emit ValueChanged(newValue);
    }

    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
}

Deploy

Using OpenZeppelin CLI 2.8 Release Candidate deploying to ganache-cli

$ npx oz deploy
✓ Compiled contracts with solc 0.5.16 (commit.9c3226ce)
? Choose the kind of deployment upgradeable
? Pick a network development
? Pick a contract to deploy Box
✓ Added contract Box
✓ Contract Box deployed
All implementations have been deployed
? Call a function to initialize the instance after creating it? No
✓ Setting everything up to create contract instances
✓ Instance created at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601
0xCfEB869F69431e42cdB54A4F4f105C19C080A601

Interact

$ npx oz send-tx
? Pick a network development
? Pick an instance Box at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601
? Select which function store(newValue: uint256)
? newValue: uint256: 42
✓ Transaction successful. Transaction hash: 0x9f007d7f0fcb278a979fafecfceb45a9190b707bb8a0c08a90ce33a16e5feaff
Events emitted:
 - ValueChanged(42)

In a separate project (based on Interacting Programmatically guide)
Install web3 and OpenZeppelin Contract-Loader

$ npm install web3 @openzeppelin/contract-loader

JavaScript to get past events

// src/index.js
const Web3 = require('web3');
const { setupLoader } = require('@openzeppelin/contract-loader');

async function main() {
    // Set up web3 object, connected to the local development network, and a contract loader
    const web3 = new Web3('http://localhost:8545');
    const loader = setupLoader({ provider: web3 }).web3;

    // Set up a web3 contract, representing our deployed Box instance, using the contract loader
    const address = '0xCfEB869F69431e42cdB54A4F4f105C19C080A601';
    const box = loader.fromArtifact('Box', address);

    box.getPastEvents('ValueChanged', {
        fromBlock: 0,
        toBlock: 'latest'
    }, function(error, events){ console.log(events); });
    
}

main();

Copy build/contracts from other project

Run script

$ node ./src/index.js
[ { logIndex: 0,
    transactionIndex: 0,
    transactionHash:
     '0x9f007d7f0fcb278a979fafecfceb45a9190b707bb8a0c08a90ce33a16e5feaff',
    blockHash:
     '0xa4e5a458f7e8f88016f90455beb4daa4e47b4618d16b7de648e536a3be64e383',
    blockNumber: 4,
    address: '0xCfEB869F69431e42cdB54A4F4f105C19C080A601',
    type: 'mined',
    id: 'log_bc7583d8',
    returnValues: Result { '0': '42', newValue: '42' },
    event: 'ValueChanged',
    signature:
     '0x93fe6d397c74fdf1402a8b72e47b68512f0510d7b98a4bc4cbdf6ac7108b3c59',
    raw:
     { data:
        '0x000000000000000000000000000000000000000000000000000000000000002a',
       topics: [Array] } } ]

Box.sol (updated)

Add an additional event

// contracts/Box.sol
pragma solidity ^0.5.0;

contract Box {

    uint256 private value;

    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);
    event ValueChanging(uint256 oldValue, uint256 newValue);

    // Stores a new value in the contract
    function store(uint256 newValue) public {
        emit ValueChanging (value, newValue);
        value = newValue;
        emit ValueChanged(newValue);
    }

    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
}

Upgrade

$ npx oz upgrade
? Pick a network development
✓ Compiled contracts with solc 0.5.16 (commit.9c3226ce)
✓ Contract Box deployed
All implementations have been deployed
? Which instances would you like to upgrade? Choose by address
? Pick an instance to upgrade Box at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601
? Call a function on the instance after upgrading it? No
✓ Instance upgraded at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601. Transaction receipt: 0xcd85e8481c8e15f37a2822e5ac829cec315484dc8cddde37625270358ff9370f
✓ Instance at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601 upgraded

Interact

$ npx oz send-tx
? Pick a network development
? Pick an instance Box at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601
? Select which function store(newValue: uint256)
? newValue: uint256: 23
✓ Transaction successful. Transaction hash: 0x3e607e53c9ff6d8831673840d6edc99e44cb7d75b52f469a7704300c7097d028
Events emitted:
 - ValueChanging(42, 23)
 - ValueChanged(23)

Run script

Without updating artifacts in project, run script

$ node ./src/index.js
[ { logIndex: 0,
    transactionIndex: 0,
    transactionHash:
     '0x9f007d7f0fcb278a979fafecfceb45a9190b707bb8a0c08a90ce33a16e5feaff',
    blockHash:
     '0xa4e5a458f7e8f88016f90455beb4daa4e47b4618d16b7de648e536a3be64e383',
    blockNumber: 4,
    address: '0xCfEB869F69431e42cdB54A4F4f105C19C080A601',
    type: 'mined',
    id: 'log_bc7583d8',
    returnValues: Result { '0': '42', newValue: '42' },
    event: 'ValueChanged',
    signature:
     '0x93fe6d397c74fdf1402a8b72e47b68512f0510d7b98a4bc4cbdf6ac7108b3c59',
    raw:
     { data:
        '0x000000000000000000000000000000000000000000000000000000000000002a',
       topics: [Array] } },
  { logIndex: 1,
    transactionIndex: 0,
    transactionHash:
     '0x3e607e53c9ff6d8831673840d6edc99e44cb7d75b52f469a7704300c7097d028',
    blockHash:
     '0x65c9aa204213922c0db2afe8c45625eb5905b06a2332bfd20576a677eca5dac0',
    blockNumber: 7,
    address: '0xCfEB869F69431e42cdB54A4F4f105C19C080A601',
    type: 'mined',
    id: 'log_8120791b',
    returnValues: Result { '0': '23', newValue: '23' },
    event: 'ValueChanged',
    signature:
     '0x93fe6d397c74fdf1402a8b72e47b68512f0510d7b98a4bc4cbdf6ac7108b3c59',
    raw:
     { data:
        '0x0000000000000000000000000000000000000000000000000000000000000017',
       topics: [Array] } } ]

Change script to get events for ValueChanging event and get an error

$ node ./src/index.js
(node:14909) UnhandledPromiseRejectionWarning: Error: Event "ValueChanging" doesn't exist in this contract.

Copy artifacts and rerun

$ node ./src/index.js
[ { logIndex: 0,
    transactionIndex: 0,
    transactionHash:
     '0x3e607e53c9ff6d8831673840d6edc99e44cb7d75b52f469a7704300c7097d028',
    blockHash:
     '0x9dec8e13054fba7872c5e56bd5ed354dfb97c798f1a8151682b06dced9156011',
    blockNumber: 7,
    address: '0xCfEB869F69431e42cdB54A4F4f105C19C080A601',
    type: 'mined',
    id: 'log_a08093e6',
    returnValues:
     Result { '0': '42', '1': '23', oldValue: '42', newValue: '23' },
    event: 'ValueChanging',
    signature:
     '0x737c5296e2c8ee4fe448f01f4b31dc800ecc70702e1f71a3d02d02eb441d5fb2',
    raw:
     { data:
        '0x000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000017',
       topics: [Array] } } ]