delegatecall插槽冲突
1.了解delegatecall的插槽冲突原理 首先严格来说应该不是插槽得冲突问题,而是本身delegate得运行机制问题,因为所有得delegatecall得运行环境都是在当前得被委托得合约里面
2.本身delegatecall他机制运行环境就是这样,所有修改得状态都会根据委托目标地址修改得状态变量内存位置,修改到被委托得合约里面。此委托调用无法修改目标地址得任何状态
3.如何解决
- 一种解决方案是存储代理合约的数据时避开通常的Solidity存储布局机制,使用 EVM的sstore和sload指令来读取或写入数据到伪随机插槽中
- 例如,使用由keccak256(my.proxy.version)返回的值作为插槽号。这样我们就可以避免槽位的冲突。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol";
/**
* @title InitializedProxy
* @author Anna Carroll
*/
contract InitializedProxy {
// address of logic contract
// slot bytes32(uint256(keccak256('EIP1967.PROXY.CONFTI.IMPLEMENTATION')) - 1)
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x5f62ce3c9aebd463c7a36ab1b244d2bb94f07a2c13889b3b687940ebc467b9b3;
// ======== Constructor =========
constructor(
address logic,
bytes memory initializationCalldata
) {
require(logic != address(0),"Proxy :: Logical contracts cannot be zero addresses");
StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = logic;
// Delegatecall into the logic contract, supplying initialization calldata
(bool _ok, bytes memory returnData) =
logic.delegatecall(initializationCalldata);
// Revert if delegatecall to implementation reverts
require(_ok, string(returnData));
}
// ======== Fallback =========
fallback() external payable {
address _impl = StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize())
let result := delegatecall(gas(), _impl, ptr, calldatasize(), 0, 0)
let size := returndatasize()
returndatacopy(ptr, 0, size)
switch result
case 0 {
revert(ptr, size)
}
default {
return(ptr, size)
}
}
}
// ======== Receive =========
receive() external payable {} // solhint-disable-line no-empty-blocks
}
- 另一种方法是使用相同的存储布局和高级别的数据争议解决,就像这个github仓库中的实现。 使用结构体\
问题模拟
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?