Skip to content

Commit

Permalink
feat: enable proxiable implementations to be clonable as well
Browse files Browse the repository at this point in the history
  • Loading branch information
guidiaz committed Feb 16, 2023
1 parent 8816dcd commit c60c2d7
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 48 deletions.
6 changes: 1 addition & 5 deletions contracts/impls/WitnetProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import "../patterns/Upgradeable.sol";
/// @author The Witnet Foundation.
contract WitnetProxy {

struct WitnetProxySlot {
address implementation;
}

/// Event emitted every time the implementation gets updated.
event Upgraded(address indexed implementation);

Expand Down Expand Up @@ -110,7 +106,7 @@ contract WitnetProxy {
}

/// @dev Complying with EIP-1967, retrieves storage struct containing proxy's current implementation address.
function __proxySlot() private pure returns (WitnetProxySlot storage _slot) {
function __proxySlot() private pure returns (Proxiable.ProxiableSlot storage _slot) {
assembly {
// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
_slot.slot := 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
Expand Down
15 changes: 1 addition & 14 deletions contracts/patterns/Clonable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ abstract contract Clonable

event Cloned(address indexed by, address indexed self, address indexed clone);

modifier onlyDelegateCalls {
modifier onlyDelegateCalls virtual {
require(address(this) != _SELF, "Clonable: not a delegate call");
_;
}
Expand All @@ -32,19 +32,6 @@ abstract contract Clonable
);
}

/// Internal virtual function for initializing contract's storage
function _initialize(bytes memory) virtual internal;

/// @notice Initializes a cloned instance.
/// @dev Every cloned instance can only get initialized once.
function initializeClone(bytes memory _initData)
external
initializer // => ensure a cloned instance can only be initialized once
onlyDelegateCalls // => this method can only be called upon cloned instances
{
_initialize(_initData);
}

/// @notice Tells whether this instance has been initialized.
function initialized() virtual public view returns (bool);

Expand Down
24 changes: 22 additions & 2 deletions contracts/patterns/Proxiable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,28 @@

pragma solidity >=0.6.0 <0.9.0;

interface Proxiable {
abstract contract Proxiable {
/// @dev Complying with EIP-1822: Universal Upgradeable Proxy Standard (UUPS)
/// @dev See https://eips.ethereum.org/EIPS/eip-1822.
function proxiableUUID() external view returns (bytes32);
function proxiableUUID() virtual external view returns (bytes32);

struct ProxiableSlot {
address implementation;
address proxy;
}

function __implementation() internal view returns (address) {
return __proxiable().implementation;
}

function __proxy() internal view returns (address) {
return __proxiable().proxy;
}

function __proxiable() internal pure returns (ProxiableSlot storage proxiable) {
assembly {
// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
proxiable.slot := 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
}
}
}
2 changes: 1 addition & 1 deletion contracts/patterns/Upgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ abstract contract Upgradeable is Initializable, Proxiable {
bytes32 internal immutable _CODEHASH;
bool internal immutable _UPGRADABLE;

modifier onlyDelegateCalls {
modifier onlyDelegateCalls virtual {
require(
address(this) != _BASE,
"Upgradeable: not a delegate call"
Expand Down
62 changes: 36 additions & 26 deletions contracts/requests/WitnetRequestMalleableBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,16 @@ abstract contract WitnetRequestMalleableBase
return _afterCloning(_cloneDeterministic(_salt));
}

/// @notice Initializes a cloned instance.
/// @dev Every cloned instance can only get initialized once.
function initializeClone(bytes memory _initData)
virtual external
initializer // => ensure a cloned instance can only be initialized once
onlyDelegateCalls // => this method can only be called upon cloned instances
{
_initialize(_initData);
}

/// @notice Tells whether this instance has been initialized.
function initialized()
override
Expand All @@ -199,32 +209,6 @@ abstract contract WitnetRequestMalleableBase
return __storage().template.length > 0;
}

/// @dev Initializes witnessing params and template bytecode.
function _initialize(bytes memory _template)
virtual override internal
initializer
{
_transferOwnership(_msgSender());

assert(_template.length > 0);
__storage().template = _template;

WitnetRequestWitnessingParams storage _params = __storage().params;
_params.numWitnesses = 2;
_params.minWitnessingConsensus = 51;
_params.witnessingCollateral = 10 ** 9; // 1 WIT
_params.witnessingReward = 5 * 10 ** 5; // 0.5 milliWITs
_params.witnessingUnitaryFee = 25 * 10 ** 4; // 0.25 milliWITs

_malleateBytecode(
_params.numWitnesses,
_params.minWitnessingConsensus,
_params.witnessingCollateral,
_params.witnessingReward,
_params.witnessingUnitaryFee
);
}


// ================================================================================================================
// --- 'Ownable' overriden functions ------------------------------------------------------------------------------
Expand Down Expand Up @@ -278,6 +262,32 @@ abstract contract WitnetRequestMalleableBase
return WitnetRequestMalleableBase(_newInstance);
}

/// @dev Initializes witnessing params and template bytecode.
function _initialize(bytes memory _template)
virtual internal
initializer
{
_transferOwnership(_msgSender());

assert(_template.length > 0);
__storage().template = _template;

WitnetRequestWitnessingParams storage _params = __storage().params;
_params.numWitnesses = 2;
_params.minWitnessingConsensus = 51;
_params.witnessingCollateral = 10 ** 9; // 1 WIT
_params.witnessingReward = 5 * 10 ** 5; // 0.5 milliWITs
_params.witnessingUnitaryFee = 25 * 10 ** 4; // 0.25 milliWITs

_malleateBytecode(
_params.numWitnesses,
_params.minWitnessingConsensus,
_params.witnessingCollateral,
_params.witnessingReward,
_params.witnessingUnitaryFee
);
}

/// @dev Serializes new `bytecode` by combining immutable template with given parameters.
function _malleateBytecode(
uint8 _numWitnesses,
Expand Down

0 comments on commit c60c2d7

Please sign in to comment.