I'm looking to make low-level delegatecall to a library that can be changed via a setter on the contract(see code below). Within the library, I am looking to make state changes to the calling contract. I have two issues.
First, I am unable to pass a storage struct to the delagatecall function correctly. The call below to updateStruct fails. I am aware of abi encoding difference between libraries vs contracts (https://docs.soliditylang.org/en/v0.8.14/contracts.html#function-signatures-and-selectors-in-libraries). From the docs I have applied "Other storage pointer types use the type identifier of their corresponding non-storage type, but append a single space followed by storage to it." So in the code below I am doing exactly that abi.encodeWithSignature("updateStruct(Test.A storage)", refType)
. Why is this not correct?
Second, I am trying to update the state of the value type like uint in the updateUint function. Is that possible via a delegatecall to lib? The code below does not fail when calling updateUint but it does not update the valueType state variable of the calling contract.
Any help appreciated
library Test{
struct A {
uint256 a;
}
function updateStruct(A storage refType)external {
refType.a=5;
}
function updateUint(uint256 valueType)external {
valueType=5;
}
}
contract TestContract {
address public adapterLib;
struct A {
uint256 a;
}
A public refType;
uint public valueType;
function setLib(address lib)public{
adapterLib = lib;
}
function updateStruct()public {
(bool success, bytes memory result)=adapterLib.delegatecall(abi.encodeWithSignature("updateStruct(Test.A storage)", refType));
require(success);
}
function updateUint()public {
(bool success, bytes memory result)=adapterLib.delegatecall(abi.encodeWithSignature("updateUint(uint256)", valueType));
require(success);
}
}