世界杯竞猜项目Dapp-第五章(合约升级)

这篇具有很好参考价值的文章主要介绍了世界杯竞猜项目Dapp-第五章(合约升级)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目前主流有三种合约升级方法

  • transparent 方式;(通用,业务逻辑和代理逻辑解耦合,比较贵)
  • uups 方式;(代理逻辑集成到了业务逻辑,通过继承来实现,便宜)
  • beacon 方式;(更加高级,一个信号,升级多个合约)

本次采用 transparent 方式,具体实现思路即,引入一个代理合约 Proxy(蓝色),用户仅与这个代理合约进行交互,由代理合约去与业务合约进行交互,因此在业务合约发生变化(升级)的时候,用户无感,并且历史数据也能够保留下来,如下图所示:
two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约
既然业务合约可以随意切换,那用户数据就只能存储在代理合约中了,在实际进行业务处理时,数据读写都是从代理合约来的,即数据与逻辑分离,其实现的核心便是 delegatecall 关键字。在此之前,先对 solidity 提供的三个合约调用方法:call、staticdall、delegatecall 进行对比说明
two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约

  • call:主要是进行常规的合约调用,比如进行合约向普通EOA进行转账时,语法为:to.call{value: value}(“”),此时目标合约中的msg.sender是调用者,即Caller Contract;
  • staticcall:与call类似,但是它不会修改合约状态,单纯调用计算而已,原理同上;(不常用)
  • delegatecall:这个是专门为代理合约 Proxy 准备的,作用是帮助用户 User 来调用 Target Contract 合约

delegatecall 特点:
1、从 Target Contract 角度来看:msg.sender 是 user,而不是 Proxy,即 Proxy 对 user 的请求进行了透传;
2、在 Target Contract 被调用时,使用的是 Proxy 的上下文,即执行合约带来的状态变化会存在 Proxy 中,而不是 Target Contract 之中
(注:由于 Transparent 模式升级时,implementation 和 proxy 不用相互关心彼此的 storage 数据,因此这种模式被称为:unstructed storage)

存储冲突问题

在 solidity 中,状态变量存储在 slot 中,slot 可以理解为 key-value 存储空间,evm 为每个合约代码提供了最多 2^256个 slot,每个 slot 可以最多存储 32 字节数据。状态变量一般是从 slot 0 开始进行存储的,在使用 delegatecall 的时候,由于需要在 Proxy 的 slot 中存储目标合约中指定的数据结构,此时如果 proxy 的 storage 布局与目标合约的 storage 布局不相同,那么就会出现存储冲突(Storage collisioin)的问题。
two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约
slot 0 分别存储的是逻辑合约地址 _imp 和管理员地址 _owner,出现存储冲突。

解决存储冲突问题

在代理合约 Proxy 中,一共需要指定两个状态变量:

  • 逻辑合约地址 implementation,用来指明被代理的合约;
  • Admin,代理合约的管理员,有权限进行合约升级;

因此,如果不进行特殊处理,则一定会出现存储 slot 冲突,我们可以将 Proxy 中的默认 slot 留出来,不要占用,而是在代理合约使用指定的 slot 来存储逻辑合约 _imp 和 admin 地址,这个解决方案也叫 EIP-1967

# implementation slot 生成规则:
bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1), 

# admin slot 生成规则:
bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)),

升级规则

1 在升级的合约中,如果有新变量的添加,那么新的状态变量只能在原始合约状态末尾依次往后添加,否则也会导致状态变量布局不一致,出现存储冲突;
2 如果一个合约定义为可升级的,那么这个合约不能有构造函数,需要使用initialize 函数来代替初始化工作。因为我们需要将部署时的数据存储在 Proxy 合约中,如果提供了构造函数,这些数据就会错误地写在逻辑合约中。

WorldCup 升级改造

首先在 node_modules 目录下安装合约升级地标准库,以使用初始化函数

npm i @openzeppelin/contracts-upgradeable

创建 WorldCupV1.sol,在原有 WorldCup 基础上修改代码

    //1. 导入标准包
    import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

    //2. 继承
    contract WorldCupV1 is Initializable {  
      //3. 将构造函数替换为初始化函数 constructor(uint256 _deadline) 
      function initialize(uint256 _deadline) public initializer {
          admin = msg.sender;
          require(
              _deadline > block.timestamp,
              "WorldCupLottery: invalid deadline!"
          );
          deadline = _deadline;
      }   
    }

再创建升级后的合约 WorldCupV2.sol,修改如下:

event ChangeDeadline(uint256 _prev, uint256 _curr);
uint256 changeCount

// 1. 增加函数,支持修改deadline
function changeDeadline(uint256 _newDeadline) external {
    require(_newDeadline > block.timestamp, "invalid timestamp!");

    // 2.增加新事件
    emit ChangeDeadline(deadline, _newDeadline); 

    // 4.状态变量
    changeCount++;  
    deadline = _newDeadline;
}

安装升级插件,在配置文件中导入

$ npm install --save-dev @openzeppelin/hardhat-upgrades

// hardhat.config.js
require('@openzeppelin/hardhat-upgrades');

编写升级脚本,创建 scripts/deployAndUpgrade.ts:

const { ethers, upgrades } = require("hardhat");

async function main() {
  const TWO_WEEKS_IN_SECS = 14 * 24 * 60 * 60;
  const timestamp = Math.floor(Date.now() / 1000)
  const deadline = timestamp + TWO_WEEKS_IN_SECS;
  console.log('deadline:', deadline)

  // Deploying
  const WorldCupv1 = await ethers.getContractFactory("WorldCupV1");
  const instance = await upgrades.deployProxy(WorldCupv1, [deadline]);
  await instance.deployed();
  console.log("WorldCupV1 address:", instance.address);
  console.log("deadline1:", await instance.deadline())

  console.log('ready to upgrade to V2...');

  // Upgrading
  const WorldCupV2 = await ethers.getContractFactory("WorldCupV2");
  const upgraded = await upgrades.upgradeProxy(instance.address, WorldCupV2);
  console.log("WorldCupV2 address:", upgraded.address);

  await upgraded.changeDeadline(deadline + 100)
  console.log("deadline2:", await upgraded.deadline())
}

main();

部署升级合约

npx hardhat run scripts/upgrade/deployAndUpgrade.ts --network goerli

two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约
我们还没 verify 业务合约 WorldCupV1 和 WorldCupV2,然后与当前的代理合约 Proxy 关联起来,我们通过 internal Txns 可以找到 WorldCupV2 的合约地址:
two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约
都对其进行 verify,并查看数据,发现都是空的
two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约

关联合约

找到代理合约-> More Options -> Is this a proxy? -> Verify -> Save
two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约
然后再回到当前页面刷新后,页面上多了两个按钮:Read as Proxy 和 Write as Proxy 如图:
two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约
我们最终暴露给用户的地址就是这个代理合约,用户的所有操作都相当于在读写着两个新方法,这两个方法会被 Proxy 传递到逻辑合约中,并把执行结果返回到代理合约中

TransparentProxy 合约关系

通过hardhat-upgrade包执行部署后,一共会自动部署三个合约:

  • 代理合约:TransparentUpgradebleProxy
  • 代理合约的管理员合约:proxyAdmin
  • 业务合约:implementation
    two_weeks_in_secs,区块链,世界杯竞猜Dapp,区块链,智能合约

当我们使用脚本执行合约升级的时候,此时内部交互为:文章来源地址https://www.toymoban.com/news/detail-793985.html

  • 自动部署 WorldCupV2 合约
  • 调用 ProxyAdmin 的 upgrade 方法,进行升级

到了这里,关于世界杯竞猜项目Dapp-第五章(合约升级)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • P2719 搞笑世界杯 (期望dp

    考虑一种票全部卖完,另一种有大于等于2 张的所有情况都为合理情况 dp[i][j]  可以 等概率的转移到 dp[i-1][j] 和 dp[j][i-1]

    2024年02月09日
    浏览(37)
  • 【疯狂世界杯】css 动画实现跳动的足球

    💖 作者简介:大家好,我是阿牛,全栈领域优质创作者😜 📝 个人主页:馆主阿牛🔥 🎉 支持我:点赞👍+收藏⭐️+留言📝 📣 系列专栏:前端实用小demo🍁 💬格言:迄今所有人生都大写着失败,但不妨碍我继续向前!🔥 2022卡塔尔世界杯正在如火如荼的进行之中,作为

    2024年02月02日
    浏览(37)
  • 数据分析案例-往届世界杯数据可视化

    目录 1.引言 2.项目简介 2.1数据集介绍 2.2技术工具 3.数据可视化 3.1往届世界杯获奖国家TOP5 3.2往届世界杯比赛数据情况 3.3往届世界杯观众人数情况 3.4往届世界杯主办方情况  3.5往届世界杯冠军队情况 足球是世界上非常受欢迎的运动之一,在全球范围内吸引了众多的参与者。

    2024年02月09日
    浏览(58)
  • 世界杯直播背后的服务器(云计算体系)

    世界杯直播过程中,各大网络平台流媒体app上最大的变化毫无疑问就是零延迟。以前球迷看球是都会发现,网络直播的球赛会比电视播出的球赛延迟40s左右。如果群里有个看电视的兄弟兄弟每个进球他都能提前40秒预告给你,那么所有惊喜荡然无存。 这种情况产生,就是因为

    2023年04月08日
    浏览(34)
  • 世界杯直播 | 抖音视频编码器优化

    动手点关注 干货不迷路 对于世界杯这样的大型体育赛事而言,视频编码算法既要在高速运动、复杂纹理的场景下确保直播内容的清晰度和流畅度,保障用户的观赛体验,又要兼顾码率、延迟等对网络传输层面尤为敏感的指标。 另外,抖音实现了业界首次的世界杯比赛支持

    2023年04月09日
    浏览(49)
  • NFT+体育,卡塔尔世界杯有哪些NFT看点!

    有人说没有冷门的世界杯不是真正的世界杯!11月22日,卡塔尔世界杯小组赛C组第1轮比赛中,沙特爆冷2:1逆转阿根廷队,成了今年世界杯的第一个冷门。世界排名第51位的沙特队战胜了排名第3的阿根廷队,结束了阿根廷队此前的36场国际比赛不败纪录。为庆祝这一胜利,沙特

    2024年02月02日
    浏览(36)
  • 基于Flask+Bootstrap+机器学习的世界杯比赛预测系统

    🤵‍♂️ 个人主页:@艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 目录 一、项目介绍 1.1项目简介 1.2技术工具 1.3页面概述  二、项目步骤 2.1首页模块 2.2查看

    2024年02月09日
    浏览(44)
  • 一零六四、世界杯数据可视化分析(阿里云天池赛)

    目录 赛制官方链接 活动背景 活动时间:即日起-12月31日17点 数据说明 世界杯成绩信息表:WorldCupsSummary 世界杯比赛比分汇总表:WorldCupMatches.csv 世界杯球员信息表:WorldCupPlayers.csv  代码实现 赛制官方链接 世界杯数据可视化分析_学习赛_天池大赛-阿里云天池 活动背景 2022世界

    2024年02月16日
    浏览(38)
  • 微信小程序|使用小程序制作一个世界杯球员识别工具

    四年一次的世界杯正在卡塔尔进行着,不同的社交圈也在疯狂的刷着世界杯的动态,来自全球各地的三十二支队伍的球员是否让你看的眼花缭乱呢? 当朋友跟你聊起昨晚那场比赛

    2024年01月16日
    浏览(41)
  • 沉睡者 - 在世界杯之前,看“去中心化Betting协议层”

    2022 年 11 月将临的世界杯赛事,正在给加密领域带来更多期待。 上周 Binance 上线足球粉丝 Token 指数 U 本位永续合约,就是一个很好的信号,合约标的指数用于追踪在该平台现货市场上一系列头部市值的足球粉丝 Token 的表现。 加密领域与世界杯赛事密切相关的不仅仅只有粉丝

    2024年01月16日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包