Issue : Storing Variables Using a Proxy

I'm having an issue with a simple storage example through a proxy. I've been using Remix's browser IDE.

Here's what I've done.

  • Create two contracts, one is Proxy.sol other is Main.sol.
  • Deploy Main.sol
  • Deploy Proxy.sol with argument Main.sol address.
  • In Remix, now re-deploy Main.sol At Address of proxy (Which I believe is just a way to implement a given contract at the specified address, in this case for convenience sake).
  • Now transact setAppStorage(x) where x is some uint256 value
  • Now transact getAppStorage() to retrieve the stored value.

I'm expecting to retrieve the stored value x, but instead I'm receiving a zero-storage slot.
In Remix's debugger I see x is stored at the zeroth address slot, but I'm not familiar enough with assembly to see where that breakdown occurs in retrieving that value from storage.

Main.sol

pragma solidity ^0.8.0;


contract Main {
    uint256 internal s;
    function initializer() public {
    }
    function setAppStorage(uint256  a) public {
        s = a;
    }
    function getAppStorage() public returns(uint256 a) {
        return s;
    }
}


Proxy.sol

pragma solidity ^0.8.0;

contract Proxy {
    
    // Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7"
    constructor(address contractLogic) public {
        // save the code address
        assembly { // solium-disable-line
            sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, contractLogic)
        }
        
    }

    fallback() external payable {
        assembly { // solium-disable-line
            let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)
            calldatacopy(0x0, 0x0, calldatasize())
            let success := delegatecall(sub(gas(), 10000), contractLogic, 0x0, calldatasize(), 0, 0)
            let retSz := returndatasize()
            returndatacopy(0, 0, retSz)
            switch success
            case 0 {
                revert(0, retSz)
            }
            default {
                return(0, retSz)
            }
        }
    }
}

Any help with this problem would be greatly appreciated.