`

Beacon

阅读更多
Beacon
a.Implementation地址并不存放在Proxy合约里,而是存放在Beacon合约里,Proxy合约里存放的是Beacon合约的地址
b.在合约交互的时候,用户同样是和Proxy合约打交道,不过此时因为Proxy合约中并未保存Implementation地址,所以它要先访问Beacon合约获取Implementation地址,然后再通过delegatecall调用Implementation。
c.在合约升级的时候,管理员并不需要和Proxy合约打交道,而只需要交互Beacon合约,把Beacon合约存储的Implementation改掉就行了。
d.就是多个Proxy共享相同的Implementation、需要批量升级的场景。此时,如果想把所有Proxy都升级,那么升级Beacon就天然可以达到升级所有Proxy的效果

MyBeaconProxy.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.0;
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import "hardhat/console.sol";

contract MyBeaconProxy is BeaconProxy {
    constructor(address _beacon, bytes memory _data) 
    BeaconProxy(_beacon,_data) {}
}


MyUpgradeableBeacon.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.0;
import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import "hardhat/console.sol";

contract MyUpgradeableBeacon is UpgradeableBeacon {
    constructor(address _impl)UpgradeableBeacon(_impl){}
}


BeaconImplement.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.0;
import "hardhat/console.sol";

contract BeaconImplement {
    uint public num;
    address addr;
    constructor() {
        num = 1;
        addr = msg.sender;
    }

    function fun() external {
        num = 2;
        addr = msg.sender;
        console.log("logic fun");
    }
}


BeaconImplementNew.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.0;
import "hardhat/console.sol";

contract BeaconImplementNew {
    uint num;
    address addr;
    uint num2;
    constructor() {
        num = 1;
        addr = msg.sender;
    }

    function fun() external {
        num = 3;
        addr = address(this);
        num2 = 100;
        console.log("new logic fun");
    }
}


test
const { ethers } = require("hardhat")

contractProxy = "MyBeaconProxy";
contractUpgradeableBeacon = "MyUpgradeableBeacon";
contractImpl = "BeaconImplement";
contractImplNew = "BeaconImplementNew";

describe("beacon1", function () {
  it("beacon ", async function () {
    const ContractImpl = await ethers.getContractFactory(contractImpl);
    const impl = await ContractImpl.deploy();
    console.log("impl addr:",impl.address);

    const ContractImplNew = await ethers.getContractFactory(contractImplNew);
    const implNew = await ContractImplNew.deploy();
    console.log("new impl addr:",implNew.address);

    const ContractUpgradeableBeacon = await ethers.getContractFactory(contractUpgradeableBeacon);
    const upgradeableBeacon = await ContractUpgradeableBeacon.deploy(impl.address);
    console.log("upgradeableBeacon addr:",upgradeableBeacon.address);

    const ContractProxy = await ethers.getContractFactory(contractProxy);
    const data = Buffer.from('');//string转bytes
    const proxy = await ContractProxy.deploy(upgradeableBeacon.address,data);
    console.log("proxy:",proxy.address);

    const ContractProxy2 = await ethers.getContractFactory(contractProxy);
    const proxy2 = await ContractProxy.deploy(upgradeableBeacon.address,data);
    console.log("proxy2:",proxy2.address);

    console.log("通过proxy调用fun():");
    const funTx = {
        to: proxy.address,
        data: ContractImpl.interface.encodeFunctionData('fun()', [])
    }
    await ethers.provider.call(funTx)

    console.log("upgrade:")
    await upgradeableBeacon.upgradeTo(implNew.address)

    console.log("new impl:",await upgradeableBeacon.implementation());

    console.log("再次通过proxy调用fun():")
    await ethers.provider.call(funTx)

    console.log("通过proxy2调用fun():")
    const funTx2 = {
        to: proxy2.address,
        data: ContractImpl.interface.encodeFunctionData('fun()', [])
    }
    await ethers.provider.call(funTx2)

  });
});


  beacon1
impl addr: 0x5FbDB2315678afecb367f032d93F642f64180aa3
new impl addr: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
upgradeableBeacon addr: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
proxy: 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
proxy2: 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9
通过proxy调用fun():
logic fun
upgrade:
new impl: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
再次通过proxy调用fun():
new logic fun
通过proxy2调用fun():
new logic fun
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics