Upgradation in smart contract is very important part, to enhance functionality or improve security. But updating a smart contract is different from tradition method. e.g.
storage.sol a seperate storage contract to handle storage. and its library.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Storage{
mapping(bytes32=>uint) uintVars;
mapping(bytes32=>string) stringVars;
function setUintVars(bytes32 varName, uint value)public {
uintVars[varName] = value;
}
function getUintVarsValue(bytes32 varName)public view returns(uint){
return uintVars[varName];
}
function setStringVars(bytes32 varName, string calldata value)public {
stringVars[varName] = value;
}
function getStringVarsValue(bytes32 varName)public view returns(string memory){
return stringVars[varName];
}
}
library StorageLib{
function setXVar(address storageContractAddress, uint value)public {
Storage(storageContractAddress).setUintVars(keccak256('x'),value);
}
function getXVar(address storageContractAddress)public view returns(uint){
return Storage(storageContractAddress).getUintVarsValue(keccak256('x'));
}
function setUserNameVar(address storageContractAddress, string memory value)public {
Storage(storageContractAddress).setStringVars(keccak256('Username'),value);
}
function getUserNameVar(address storageContractAddress)public view returns(string memory){
return Storage(storageContractAddress).getStringVarsValue(keccak256('Username'));
}
}
Contract version 1:
use the library of storage contract to access the storage contract.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import './Storage.sol';
contract BackendContract{
using StorageLib for address;
address storageAddr;
constructor(address storageContractAddress){
storageAddr = storageContractAddress;
}
function addX(uint a, uint b)public {
uint x = a + b;
storageAddr.setXVar(x);
}
function getX()public view returns(uint){
return storageAddr.getXVar();
}
}
Backend contract version 2
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import './Storage.sol';
contract BackendContractVersion2{
using StorageLib for address;
address storageAddr;
constructor(address storageContractAddress){
storageAddr = storageContractAddress;
}
function addX(uint a, uint b)public {
uint x = a + b + 5;
storageAddr.setXVar(x);
}
function getX()public view returns(uint){
return storageAddr.getXVar();
}
}
Here is another storage contract with assembly to optimize gas cost significantly.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Storage{
function setUintVars(bytes32 varName, uint value)public {
assembly {
sstore(varName, value)
}
}
function getUintVarsValue(bytes32 varName)public view returns(uint val){
assembly {
val := sload(varName)
}
}
function setStringVars(bytes32 varName, string memory value)public {
assembly {
sstore(varName, value)
}
}
function getStringVarsValue(bytes32 varName)public view returns(string memory val){
assembly {
val := sload(varName)
}
}
}
library StorageLib{
function setXVar(address storageContractAddress, uint value)public {
Storage(storageContractAddress).setUintVars(keccak256('x'),value);
}
function getXVar(address storageContractAddress)public view returns(uint){
return Storage(storageContractAddress).getUintVarsValue(keccak256('x'));
}
function setUserNameVar(address storageContractAddress, string memory value)public {
Storage(storageContractAddress).setStringVars(keccak256('Username'),value);
}
function getUserNameVar(address storageContractAddress)public view returns(string memory){
return Storage(storageContractAddress).getStringVarsValue(keccak256('Username'));
}
}