Skip to content

Commit aa2f941

Browse files
committed
initial commit
1 parent 4461355 commit aa2f941

File tree

9 files changed

+3449
-1
lines changed

9 files changed

+3449
-1
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
3+
build

README.md

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,77 @@
1-
# erc-1167-minimal-proxy-contract-example
1+
# ERC-1167: Minimal Proxy Contract Example
2+
23
An example of a contract that implements ERC-1167: Minimal Proxy
4+
5+
__Setup commands__
6+
7+
For background information, these are the commands used to setup this project initially
8+
9+
```
10+
npm i -g truffle
11+
npm install @openzeppelin/upgrades
12+
truffle init
13+
truffle create migration store
14+
truffle create migration storeFactory
15+
```
16+
17+
__Try out this example__
18+
19+
To run this example on your local machine, you need to clone this repo(!) and then follow the below instructions.
20+
21+
Start up a new truffle console session in your terminal using `truffle console` then, in the session, compile and deploy the Store and StoreFactory contracts. In order to test this out in the Tuffle Console we essentially need to:
22+
23+
1. Compile the contracts
24+
1. Migrate the contracts
25+
1. Get an instance of the StoreFactory
26+
1. Verify the `impl` address for the implemtation of the Store Contract has been set correctly
27+
1. Check the deployed contract addresses using the `networks` command
28+
1. Now for the fun stuff! Lets clone the Store implementation using the StoreFactory contract.
29+
1. Fetch the result of the `ProxyCreated` event. This event is defined in the [OpenZeppelin ProxyFactory](https://github.com/OpenZeppelin/openzeppelin-sdk/blob/master/packages/lib/contracts/upgradeability/ProxyFactory.sol) contract that we are using here. Its fired any time we call the `deployMinimal` of the `ProxyFactory` and it includes one property: __proxy__ which is the address of the new cloned proxy contract.
30+
1. Get an instance of the proxy contract from the proxy address returned in the `ProxyCreated` event.
31+
1. Check the value of the store (it should be empty)
32+
1. Set the value of the store to something
33+
1. Check the value of the store again (it should be set to the new value)
34+
1. Now clone 2 more proxy contracts
35+
1. Repeat the above and set the value to different strings in each proxy contract
36+
1. Confirm all the value data strings are different and set correctly!
37+
38+
```
39+
compile
40+
migrate --reset
41+
sf = await StoreFactory.deployed()
42+
sf.impl() // This should be the same address as the deployed Store contract!
43+
networks // Lets verify the contract deployed addresses
44+
sf.cloneStore() // This returns the transaction receipt
45+
sf.getPastEvents('ProxyCreated') // This will return the event that contains the address of the cloned contract instance
46+
store1 = await Store.at('0x4644f030a4713387d9D02d1662Fb4e1a9A385dcb') // use the address in the returnValues 'proxy' of the ProxyCreated event
47+
store1.value() // returns ''
48+
store1.setValue('My First Store')
49+
store1.value() // returns 'My First Store'
50+
51+
// Lets create two more store proxies!
52+
53+
sf.cloneStore()
54+
sf.cloneStore()
55+
56+
sf.getPastEvents('ProxyCreated', {fromBlock: 0})
57+
58+
store2 = await Store.at('0xE872f5BEaEAfA067Eba935f20f08F84F928354C5')
59+
store3 = await Store.at('0x8871Ba7F9002287c4A40c2cce036daB7a57D2742')
60+
61+
store2.setValue('My Second store')
62+
store3.setValue('My Third store')
63+
64+
// Confirm all values are set as expected!
65+
store1.value() // returns 'My First Store'
66+
store2.value() // returns 'My Second Store'
67+
store3.value() // returns 'My Third Store'
68+
```
69+
70+
Versions used:
71+
72+
```
73+
Truffle v5.1.32 (core: 5.1.32)
74+
Solidity v0.5.16 (solc-js)
75+
Node v12.18.1
76+
Web3.js v1.2.1
77+
```

contracts/Migrations.sol

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.4.21 <0.7.0;
3+
4+
contract Migrations {
5+
address public owner;
6+
uint public last_completed_migration;
7+
8+
constructor() public {
9+
owner = msg.sender;
10+
}
11+
12+
modifier restricted() {
13+
if (msg.sender == owner) _;
14+
}
15+
16+
function setCompleted(uint completed) public restricted {
17+
last_completed_migration = completed;
18+
}
19+
}

contracts/Store.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pragma solidity ^0.5.3;
2+
3+
contract Store {
4+
string public value;
5+
6+
function setValue(string calldata newValue) external {
7+
value = newValue;
8+
}
9+
}

contracts/StoreFactory.sol

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
pragma solidity ^0.5.3;
2+
3+
import "@openzeppelin/upgrades/contracts/upgradeability/ProxyFactory.sol";
4+
import "./Store.sol";
5+
6+
contract StoreFactory is ProxyFactory {
7+
address public owner;
8+
address public impl;
9+
10+
modifier OnlyOwner() {
11+
require(msg.sender == owner, 'Only the owner can clone a store');
12+
_;
13+
}
14+
constructor (address _impl) public {
15+
owner = msg.sender;
16+
impl = _impl;
17+
}
18+
19+
function cloneStore() public OnlyOwner {
20+
deployMinimal(impl, "");
21+
}
22+
}

migrations/1_initial_migration.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const Migrations = artifacts.require("Migrations");
2+
3+
module.exports = function(deployer) {
4+
deployer.deploy(Migrations);
5+
};

migrations/2_deploy_contracts.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const Store = artifacts.require('Store');
2+
const StoreFactory = artifacts.require('StoreFactory');
3+
4+
module.exports = async function(_deployer) {
5+
_deployer.deploy(Store).then(() => {
6+
return _deployer.deploy(StoreFactory, Store.address);
7+
})
8+
};

0 commit comments

Comments
 (0)