0

I've created a upgradable contract as suggested here: Upgradeable smart contracts

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Relay { address public _addr; address public owner;

constructor(address addr) {
    _addr = addr;
    owner = msg.sender;
}

function update(address addr) public {
    if (msg.sender != owner) revert();
    _addr = addr;
}

fallback() external payable {
    (bool success, ) = _addr.delegatecall(msg.data);
    if (! success) revert();
}

}

contract RealContract { mapping(address => uint256) private count;

receive() external payable {
    count[msg.sender] ++;
}

function getBalance(address a) public view returns (uint256) {
    return count[a];
}

}

In migrations I have

var Relay = artifacts.require("Relay")
var RealContract = artifacts.require("RealContract")

module.exports = function(deployer, network, accounts) { deployer.deploy(RealContract).then(function () { return deployer.deploy(Relay, RealContract.address) }) };

In the unit test file:

let Relay = artifacts.require("Relay")
let RealContract = artifacts.require("RealContract")

it('upgradable-test', async () => { let accounts = await web3.eth.getAccounts() let RelayDeployed = await Relay.deployed() let RealContractDeployed = await RealContract.deployed()

let callData = web3.eth.abi.encodeFunctionCall({
    name: 'update',
    type: 'function',
    inputs: [{
        type: 'uint256',
        name: 'addr'
    }]
}, [RealContractDeployed.address]);
await web3.eth.sendTransaction({
    from: accounts[0],
    to:   RelayDeployed.address,
    data: callData
})

await RelayDeployed.sendTransaction({
    from:  accounts[0],
    to:    RelayDeployed.address,
    value: web3.utils.toWei("1", "ether")
})

let balance = await RelayDeployed.getBalance(accounts[0])
console.log(balance.toString())

})

I'm unable to call update() here, it just reverts() and I'm not sure why. Does anyone know?

EDIT

Errors from truffle test xx.js:

> Compiled successfully using:
   - solc: 0.8.0+commit.c7dfd78e.Emscripten.clang
  1. upgradable-test

0 passing (211ms) 1 failing

  1. upgradable-test: Error: Returned error: VM Exception while processing transaction: revert at Object.ErrorResponse (/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-core-helpers/lib/errors.js:28:1) at /usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-core-requestmanager/lib/index.js:302:1 at /usr/local/lib/node_modules/truffle/build/webpack:/packages/provider/wrapper.js:107:1 at exports.XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-providers-http/lib/index.js:98:1) at exports.XMLHttpRequest.dispatchEvent (/xxxx/eth-test/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:591:25) at setState (/xxxx/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:610:14) at IncomingMessage.<anonymous> (/xxxx/eth-test/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:447:13) at endReadableNT (internal/streams/readable.js:1333:12) at processTicksAndRejections (internal/process/task_queues.js:82:21)

daisy
  • 284
  • 1
  • 8

1 Answers1

0

call update() on the Relay contract directly. calling it via the fallback function will try to execute the function on the RealContract where it doesn't exist.

also, the storage vars on both contracts should be in alignment it seems a bit around the wrong way to me, and perhaps using the terms proxy and implementation vs. Relay and Real would be clearer.

The proxy contract (Relay) should be where the state and balances are kept, but the mapping doesn't exist there. Just functions/logic should be on the implementation contract (RealContract), and state vars declared to coincide with what's on proxy contract.

sola24
  • 1,238
  • 3
  • 20