Skip to content

Instantly share code, notes, and snippets.

@cassc
Created July 14, 2022 09:33
Show Gist options
  • Save cassc/41cfb69b15a37ad42fded872f8db3c2e to your computer and use it in GitHub Desktop.
Save cassc/41cfb69b15a37ad42fded872f8db3c2e to your computer and use it in GitHub Desktop.
beacon contract
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
contract Vaultv1 is Initializable {
string public name;
uint256 public vaLue;
error Down(string reason);
function initialize(string memory _name, uint256 _vaLue) public initializer {
name = _name;
vaLue = _vaLue;
}
function down() public {
if (vaLue == 0) revert Down("!vaLue");
vaLue--;
}
}
contract Vaultv2 is Initializable {
string public name;
uint256 public vaLue;
error Down(string reason);
function initialize(string memory _name, uint256 _vaLue) public initializer {
name = _name;
vaLue = _vaLue;
}
function down() public {
if (vaLue == 0) revert Down("!vaLue");
vaLue--;
}
function up() public {
vaLue++;
}
}
contract VaultBeacon {
UpgradeableBeacon immutable beacon;
address public vLogic;
constructor(address _vLogic) {
beacon = new UpgradeableBeacon(_vLogic);
vLogic = _vLogic;
}
function update(address _vLogic) public {
beacon.upgradeTo(_vLogic);
vLogic = _vLogic;
}
function implementation() public view returns(address) {
return beacon.implementation();
}
}
contract Factory {
mapping(uint256 => address) private vaults;
VaultBeacon immutable beacon;
constructor(address _vLogic) {
beacon = new VaultBeacon(_vLogic);
}
function create(string calldata _name, uint256 _vaLue, uint256 x) external returns (address) {
BeaconProxy proxy = new BeaconProxy(address(beacon),
abi.encodeWithSelector(Vaultv1(address(0)).initialize.selector, _name, _vaLue)
);
vaults[x] = address(proxy);
return address(proxy);
}
function getImplementation() public view returns (address) {
return beacon.implementation();
}
function getBeacon() public view returns (address) {
return address(beacon);
}
function getVault(uint256 x) public view returns (address) {
return vaults[x];
}
}
@cassc
Copy link
Author

cassc commented Jul 14, 2022

https://www.youtube.com/watch?v=2oUHr8hxzBA

A simple demo showing upgrading contract with beacon

  • First deploy Vaultv1 and get address, e.g., 0xvault1
  • Deploy Factory and use 0xvault1 as constructor argument
  • To create a vault, call Factory#create(vaultname, value, idx) to set name and value and index of the vault
  • To access the vault as Vaultv1, call Factory#getVault(idx) to get the vault address and invoke the method in Vaultv1 from this address
  • To update the vault to Vaultv2, first deploy Vaultv2 to 0xvault2
  • Call Factory#getBeacon() to get the beacon address and invoke the VaultBeacon#update(v2Address) to use Vaultv2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment