Skip to content

Commit

Permalink
Add Proxies from OpenZeppelin SDK (#2335)
Browse files Browse the repository at this point in the history
  • Loading branch information
frangio authored Aug 28, 2020
1 parent 0b489f4 commit cb791a1
Show file tree
Hide file tree
Showing 17 changed files with 1,618 additions and 0 deletions.
20 changes: 20 additions & 0 deletions contracts/mocks/ClashingImplementation.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;


/**
* @dev Implementation contract with an admin() function made to clash with
* @dev TransparentUpgradeableProxy's to test correct functioning of the
* @dev Transparent Proxy feature.
*/
contract ClashingImplementation {

function admin() external pure returns (address) {
return 0x0000000000000000000000000000000011111142;
}

function delegatedFunction() external pure returns (bool) {
return true;
}
}
57 changes: 57 additions & 0 deletions contracts/mocks/DummyImplementation.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

abstract contract Impl {
function version() public pure virtual returns (string memory);
}

contract DummyImplementation {
uint256 public value;
string public text;
uint256[] public values;

function initializeNonPayable() public {
value = 10;
}

function initializePayable() payable public {
value = 100;
}

function initializeNonPayable(uint256 _value) public {
value = _value;
}

function initializePayable(uint256 _value) payable public {
value = _value;
}

function initialize(uint256 _value, string memory _text, uint256[] memory _values) public {
value = _value;
text = _text;
values = _values;
}

function get() public pure returns (bool) {
return true;
}

function version() public pure virtual returns (string memory) {
return "V1";
}

function reverts() public pure {
require(false);
}
}

contract DummyImplementationV2 is DummyImplementation {
function migrate(uint256 newVal) payable public {
value = newVal;
}

function version() public pure override returns (string memory) {
return "V2";
}
}
36 changes: 36 additions & 0 deletions contracts/mocks/InitializableMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "../proxy/Initializable.sol";

/**
* @title InitializableMock
* @dev This contract is a mock to test initializable functionality
*/
contract InitializableMock is Initializable {

bool public initializerRan;
uint256 public x;

function initialize() public initializer {
initializerRan = true;
}

function initializeNested() public initializer {
initialize();
}

function initializeWithX(uint256 _x) public payable initializer {
x = _x;
}

function nonInitializable(uint256 _x) public payable {
x = _x;
}

function fail() public pure {
require(false, "InitializableMock forced failure");
}

}
76 changes: 76 additions & 0 deletions contracts/mocks/MultipleInheritanceInitializableMocks.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "../proxy/Initializable.sol";

// Sample contracts showing upgradeability with multiple inheritance.
// Child contract inherits from Father and Mother contracts, and Father extends from Gramps.
//
// Human
// / \
// | Gramps
// | |
// Mother Father
// | |
// -- Child --

/**
* Sample base intializable contract that is a human
*/
contract SampleHuman is Initializable {
bool public isHuman;

function initialize() public initializer {
isHuman = true;
}
}

/**
* Sample base intializable contract that defines a field mother
*/
contract SampleMother is Initializable, SampleHuman {
uint256 public mother;

function initialize(uint256 value) public initializer virtual {
SampleHuman.initialize();
mother = value;
}
}

/**
* Sample base intializable contract that defines a field gramps
*/
contract SampleGramps is Initializable, SampleHuman {
string public gramps;

function initialize(string memory value) public initializer virtual {
SampleHuman.initialize();
gramps = value;
}
}

/**
* Sample base intializable contract that defines a field father and extends from gramps
*/
contract SampleFather is Initializable, SampleGramps {
uint256 public father;

function initialize(string memory _gramps, uint256 _father) public initializer {
SampleGramps.initialize(_gramps);
father = _father;
}
}

/**
* Child extends from mother, father (gramps)
*/
contract SampleChild is Initializable, SampleMother, SampleFather {
uint256 public child;

function initialize(uint256 _mother, string memory _gramps, uint256 _father, uint256 _child) public initializer {
SampleMother.initialize(_mother);
SampleFather.initialize(_gramps, _father);
child = _child;
}
}
66 changes: 66 additions & 0 deletions contracts/mocks/RegressionImplementation.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "../proxy/Initializable.sol";

contract Implementation1 is Initializable {
uint internal _value;

function initialize() public initializer {
}

function setValue(uint _number) public {
_value = _number;
}
}

contract Implementation2 is Initializable {
uint internal _value;

function initialize() public initializer {
}

function setValue(uint _number) public {
_value = _number;
}

function getValue() public view returns (uint) {
return _value;
}
}

contract Implementation3 is Initializable {
uint internal _value;

function initialize() public initializer {
}

function setValue(uint _number) public {
_value = _number;
}

function getValue(uint _number) public view returns (uint) {
return _value + _number;
}
}

contract Implementation4 is Initializable {
uint internal _value;

function initialize() public initializer {
}

function setValue(uint _number) public {
_value = _number;
}

function getValue() public view returns (uint) {
return _value;
}

// solhint-disable-next-line payable-fallback
fallback() external {
_value = 1;
}
}
49 changes: 49 additions & 0 deletions contracts/mocks/SingleInheritanceInitializableMocks.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "../proxy/Initializable.sol";

/**
* @title MigratableMockV1
* @dev This contract is a mock to test initializable functionality through migrations
*/
contract MigratableMockV1 is Initializable {
uint256 public x;

function initialize(uint256 value) public payable initializer {
x = value;
}
}

/**
* @title MigratableMockV2
* @dev This contract is a mock to test migratable functionality with params
*/
contract MigratableMockV2 is MigratableMockV1 {
bool internal _migratedV2;
uint256 public y;

function migrate(uint256 value, uint256 anotherValue) public payable {
require(!_migratedV2);
x = value;
y = anotherValue;
_migratedV2 = true;
}
}

/**
* @title MigratableMockV3
* @dev This contract is a mock to test migratable functionality without params
*/
contract MigratableMockV3 is MigratableMockV2 {
bool internal _migratedV3;

function migrate() public payable {
require(!_migratedV3);
uint256 oldX = x;
x = y;
y = oldX;
_migratedV3 = true;
}
}
62 changes: 62 additions & 0 deletions contracts/proxy/Initializable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT

pragma solidity >=0.4.24 <0.7.0;


/**
* @title Initializable
*
* @dev Helper contract to support initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
contract Initializable {

/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;

/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;

/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}

_;

if (isTopLevelCall) {
_initializing = false;
}
}

/// @dev Returns true if and only if the function is running in the constructor
function _isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
// solhint-disable-next-line no-inline-assembly
assembly { cs := extcodesize(self) }
return cs == 0;
}
}
Loading

0 comments on commit cb791a1

Please sign in to comment.