<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Solidity學習之時間鎖

      什么是時間鎖

      在合約中有一種時間鎖設計,它的作用是延遲執(zhí)行某個操作。比如在金庫合約中,轉(zhuǎn)出的方法必須要通過時間鎖去調(diào)用,那么在轉(zhuǎn)賬發(fā)起之后,會經(jīng)過一段指定時間才能執(zhí)行。

      假設合約owner的私鑰被盜,那么即使黑客想要轉(zhuǎn)出資金,也必須等待一定的時間,這時合約持有者就可以采取一定的措施去減少損失。

      實現(xiàn)邏輯

      首先為了保證合約內(nèi)部的敏感方法無法被直接調(diào)用,而是必須經(jīng)過時間鎖,那么就需要設計一個修飾器,這個修飾器下的函數(shù)的調(diào)用方必須是合約本身,這就避免了外部調(diào)用。

      然后是時間鎖的實現(xiàn),時間鎖的結(jié)構(gòu)是一個map,第一次使用時間鎖是將某個調(diào)用放入到map中,第二次使用則將map中的調(diào)用取出并執(zhí)行。

      那么map的key是什么呢,它由target、value、signature、data、executeTime幾個字段組成,代表的含義是

      在executeTime的時候,由合約去調(diào)用target的方法,方法的簽名為signature,參數(shù)為data,并攜帶value的native token

      這代表調(diào)用方和合約達成了約定,當executeTime時間到的時候,合約就要允許調(diào)用方用約定好的參數(shù)去執(zhí)行約定好的方法,所以這是一個提前約定的機制。

      因為有executeTime的存在,可以保證key是唯一的。

      因此時間鎖有兩個方法:addTransaction2QueueexecuteTransaction

      具體實現(xiàn)

      成員變量

      contract TimeClock  {
          address public admin;
          uint public delay;
          uint public constant GRACE_PERIOD = 7 days; // 交易過期時間
          
      
          mapping (bytes32=>bool) public queuedTransactions;
      	  
      	  constructor(uint delay_) {
      	    admin = msg.sender;
      	    delay = delay_;
      		 }
      }
      

      admin是合約的控制方,保證了其他人無法使用時間鎖,但無法避免admin地址被盜。

      delay是時間鎖的鎖定時間,交易的執(zhí)行時間必須大于當前時間+delay

      GRACE_PERIOD是過期機制,為了避免任務長期不執(zhí)行帶來的風險,屬于防御機制,如果超過約定好的executeTime+GRACE_PERIOD,任務失效無法再被執(zhí)行。

      queuedTransactions就是存放任務的隊列。

      事件

          event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint executeTime);
          
          event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint executeTime);
          
          event NewTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint executeTime);
      

      修飾器

        modifier onlyOwner {
            require(msg.sender == admin, "caller not admin");
            _;
        }
      
        modifier onlyTimeclock {
            require(msg.sender == address(this), "caller not timeclock");
            _;
        }
      

      onlyOwner用來控制隊列方法,保證只有合約的owner才能調(diào)用。

      onlyTimeclock則用來控制實際要執(zhí)行的邏輯,保證這些邏輯都在時間鎖的控制之下。

      函數(shù)

      控制隊列有三個函數(shù):add,cancel和execute

        function addTransaction2Queue(address target, uint value, string memory signature, bytes memory data, uint256 executeTime) public onlyOwner returns (bytes32) {
            bytes32 txHash = getTxHash(target, value, signature, data, executeTime);
            require(!queuedTransactions[txHash], "transaction already queued");
            require(executeTime >  getBlockTimestamp() + delay, "estimated transaction must satisfy delay");
            require(msg.value > value, "value not enough");
            
            queuedTransactions[txHash] = true;
            emit NewTransaction(txHash, target, value, signature, data, executeTime);
            return txHash;
        }
      
          function cancelTransaction(address target, uint256 value, string memory signature, bytes memory data, uint256 executeTime) public onlyOwner{
          // 計算交易的唯一識別符:一堆東西的hash
          bytes32 txHash = getTxHash(target, value, signature, data, executeTime);
          // 檢查:交易在時間鎖隊列中
          require(queuedTransactions[txHash], "Timelock::cancelTransaction: Transaction hasn't been queued.");
          // 將交易移出隊列
          queuedTransactions[txHash] = false;
      
          emit CancelTransaction(txHash, target, value, signature, data, executeTime);
      }
      

      add和cancel方法都比較簡單,主要就是條件的檢查,然后做了一個map的插入移除操作。

      考慮到復用性,就把getTxHash和getBlockTimestamp方法都抽出來了。

      function getTxHash(address target, uint value, string memory signature, bytes memory data, uint executeTime) public pure returns (bytes32) {
          return keccak256(abi.encode(target, value, signature, data, executeTime));
      }
      function getBlockTimestamp() public view  returns (uint256) {
          return block.timestamp;
      }
      

      最后是execute方法:

        function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint256 executeTime) external payable onlyOwner returns (bool) {
            bytes32 txHash = getTxHash(target, value, signature, data, executeTime);
            require(queuedTransactions[txHash], "transaction not valid");
            queuedTransactions[txHash] = false;
            require(getBlockTimestamp() > executeTime, "executed time not reached");
            require(getBlockTimestamp() < executeTime + GRACE_PERIOD, "grace period over");
            bytes memory callData;
            if (bytes(signature).length == 0) {
                callData =  data;
            } else {
                callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);
            }
            (bool success, ) = target.call{value:msg.value}(callData);
            require(success, "execution failed");
            emit ExecuteTransaction(txHash, target, value, signature, data, executeTime);
            return true;
        }
      

      其中的邏輯判斷表示:如果沒有指定函數(shù)的話,那直接用data,會觸發(fā)目標合約的fallback()receive()邏輯;如果有的話則發(fā)起函數(shù)調(diào)用。

      此時callData的封裝使用了abi.encodePacked而非abi.encodeWithSignature或是abi.encodeWithSelector,這是因為調(diào)用方法的參數(shù)是不定的,已經(jīng)被封裝成bytes的data了,所以selector也只能手動封裝。

      函數(shù)選擇器 = keccak256("函數(shù)名(參數(shù)類型列表)") 的前 4 個字節(jié),即bytes4(keccak256(bytes(signature)))

      最后寫一個方法用來模擬:

      function changeAdmin(address newAdmin) public onlyTimeclock {
          admin = newAdmin;
          emit ChangeOwner(newAdmin);
      }
      

      調(diào)用的時候需要手動做一下data的encode,比如我傳入的是地址

      0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2,那么data就是

      0x000000000000000000000000ab8483f64d9c6d1ecf9b849ae677dd3315835cb2

      posted @ 2025-07-27 19:45  Felix07  閱讀(50)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 人妻丰满熟妇av无码区| 亚洲热视频这里只有精品| 国产剧情福利一区二区麻豆 | 亚洲精品视频一二三四区| 国产女主播喷水视频在线观看| 欧洲无码一区二区三区在线观看| 久久夜色精品久久噜噜亚| 国产成人精品18| 国产精品久久无码不卡黑寡妇| 亚洲av成人一区国产精品| 他掀开裙子把舌头伸进去添视频| 深夜福利啪啪片| 国产美女被遭强高潮免费一视频| 精品久久久久久久中文字幕| 成人午夜福利精品一区二区| 久久久久香蕉国产线看观看伊| 亚洲va在线∨a天堂va欧美va| 九九热在线精品免费视频| 九九视频热最新在线视频| 精品一区二区三区东京热| 亚洲自拍偷拍一区二区三区| 国产第一页浮力影院入口| 神木县| 亚洲中文字幕亚洲中文精| 日本一道一区二区视频| 长岭县| 亚洲无码精品视频| 污污网站18禁在线永久免费观看| av男人的天堂在线观看国产| 国产精品中出一区二区三区| 久久久久久久久久久免费精品| 亚洲欧美日韩综合久久久| 久久精品国产亚洲精品色婷婷| 综1合AV在线播放| 亚洲国产成人久久一区久久 | 国产精品三级一区二区三区| 国产精品欧美福利久久| 亚洲中文字幕第一页在线| 日韩精品一区二区三区中文无码| 欧美一区二区三区欧美日韩亚洲 | 88国产精品视频一区二区三区|