Files
contract/test/TestProxy.sol
dexorder 25def69c66 dexorder
2024-10-17 02:42:28 -04:00

80 lines
2.0 KiB
Solidity

pragma solidity 0.8.26;
import "@forge-std/console2.sol";
import "@forge-std/Test.sol";
// Inplementaton shared as library
contract Impl {
// Begin storage shared with Proxy
uint256 inc;
// End storage
function proxy_target(uint256 x) external view returns(uint256) {
return(x+inc);
}
}
// The proxy for the implementation
contract Proxy {
// Begin storage shared with implementation
uint256 inc;
// End storage
Impl immutable impl; // Address of the library or implementation contract
constructor(Impl _impl, uint256 _inc) {
impl = _impl;
inc = _inc;
}
fallback() external payable {
address _impl = address(impl);
assembly {
// Copy the data sent to the memory at position `0`
calldatacopy(0, 0, calldatasize())
// Forward the call to the implementation contract with the provided input
let result := delegatecall(gas(), _impl, 0, calldatasize(), 0, 0)
// Copy the returned data
returndatacopy(0, 0, returndatasize())
// Check if the call was successful and return the data or revert
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
}
// Interface for Proxy/Implementation
interface IProxy {
function proxy_target(uint256 x) external returns(uint256);
}
// Test it
contract TestProxy is Test {
// Create shared implementation
Impl _impl = new Impl();
IProxy _proxy;
IProxy _proxy2;
function setUp() public {
// New proxy instance linked to _impl with IProxy interface
_proxy = IProxy(address(new Proxy(_impl, 1))); // cannot directly cast Proxy to Iproxy
_proxy2 = IProxy(address(new Proxy(_impl, 2))); // cannot directly cast Proxy to Iproxy
}
function testProxy() public {
require(_proxy.proxy_target(1) == 2, "fail");
require(_proxy2.proxy_target(1) == 3, "fail");
}
}