iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Web 3

以 Python 進入以太坊虛擬機 (EVM) 的幻想境界系列 第 15

虛擬境界 15:系統指令合約呼叫及回傳

  • 分享至 

  • xImage
  •  

第15章:系統操作 call

昨天介紹完,create 系列,今天介紹剩下的系統操作指令,這幾個指令可以執行其他合約的指令,這次也順便介紹 returnrevertselfdestruct

CALL (0xF1)

CALL 指令允許一個合約調用另一個合約的功能。它會從當前合約轉移指定的以太幣到目標合約,並執行目標合約的代碼。此指令還允許合約讀取和寫入存儲,並返回數據。

def _call(self, txn):
    gas = self.evm.stack.pop()
    to = self.evm.stack.pop()
    value = self.evm.stack.pop()
    mem_start = self.evm.stack.pop()
    mem_length = self.evm.stack.pop()
    returndata_start = self.evm.stack.pop()
    returndata_length = self.evm.stack.pop()


    data = self.evm.memory[mem_start: mem_start + mem_length]

    source = self.getAccount(txn.caller)
    target = self.getAccount(hex(to))

    source['balance'] -= value
    target['balance'] += value

    # skip build tx and send tx

    self.evm.excute(target['code'])

    evm = EVM(target['code'])
    evm.memory = data
    evm.execute()

    self.evm.memory[returndata_start:returndata_start + returndata_length] = evm.stack

CALLCODE (0xF2)

CALLCODECALL 類似,但它在調用者的上下文中執行目標合約的代碼。這意味著它使用調用者的存儲和餘額,而不是被調用合約的存儲和餘額。

def callcode(self):
    self._call()

DELEGATECALL (0xF4)

DELEGATECALL 指令允許一個合約在其自己的上下文中執行另一個合約的代碼。這意味著它使用調用者的存儲、餘額和消息發送者,而不是被調用合約的這些值。

def delegatecall(self, txn):
    gas = self.evm.stack.pop()
    to = self.evm.stack.pop()
    mem_start = self.evm.stack.pop()
    mem_length = self.evm.stack.pop()
    returndata_start = self.evm.stack.pop()
    returndata_length = self.evm.stack.pop()


    data = self.evm.memory[mem_start: mem_start + mem_length]

    target = self.getAccount(hex(to))

    # skip build tx and send tx

    self.evm.excute(target['code'])

    evm = EVM(target['code'])
    evm.memory = data
    evm.storage = self.evm.storage
    evm.execute()

    self.evm.memory[returndata_start:returndata_start + returndata_length] = evm.stack

STATICCALL (0xFA)

STATICCALL 指令與 CALL 類似,但它只能進行讀取操作,不能修改存儲或轉移以太幣。這確保了調用的純粹性,因為它不會改變任何狀態。

def staticcall(self):
    gas = self.evm.stack.pop()
    to = self.evm.stack.pop()
    mem_start = self.evm.stack.pop()
    mem_length = self.evm.stack.pop()
    returndata_start = self.evm.stack.pop()
    returndata_length = self.evm.stack.pop()

    data = self.evm.memory[mem_start: mem_start + mem_length]

    target = self.getAccount(hex(to))

    self.evm.excute(target['code'])

    self.evm.memory[returndata_start:returndata_start + returndata_length] = self.evm.stack

RETURN (0xF3)

RETURN 指令允許合約返回數據給調用者。它結束當前的合約執行,並返回指定的數據。

def _return(self):
    mem_start = self.evm.stack.pop()
    mem_length = self.evm.stack.pop()

    self.evm.stack = self.evm.memory[mem_start: mem_start + mem_length]

REVERT (0xFD)

REVERT 指令允許合約在遇到錯誤時終止執行,並退還所有未使用的 Gas。它還允許合約返回一個錯誤消息,說明為什麼操作失敗。

def revert(self):
    mem_start = self.evm.stack.pop()
    mem_length = self.evm.stack.pop()

    self.evm.stack = self.evm.memory[mem_start: mem_start + mem_length]
    self.success = False

SELFDESTRUCT (0xFF)

SELFDESTRUCT 指令允許合約銷毀自己,並將其餘額發送到指定的地址。一旦合約自毀,它的代碼和存儲將從區塊鏈上永久刪除,並且不能再次調用或恢復。

def selfdestruct(self, txn):
    to = self.evm.stack.pop()
    target = self.getAccount(hex(to))

    self.evm.balance[txn.thisAddr] += target['balance']
    target['balance'] = 0

這些系統操作為智能合約提供了與外部世界交互的能力,並允許它們執行各種複雜的操作。理解這些指令的工作原理和用途對於 Ethereum 智能合約開發至關重要。


上一篇
虛擬境界 14:系統指令合約創建
下一篇
虛擬境界 16:完整 EVM 實現
系列文
以 Python 進入以太坊虛擬機 (EVM) 的幻想境界30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言