Opcode
delegatecall 第二個目標參數的目的是什麼?
簡單的問題,但我想不出答案。
是否有計劃/EIP 使用 的第二個參數
DELEGATECALL
?還是我錯了(在這種情況下參數不會被忽略)?在 c++ Ethereum evm 中,程式碼如下:
if (m_ext->balance(m_ext->myAddress) >= callParams->valueTransfer && m_ext->depth < 1024) { callParams->onOp = m_onOp; callParams->senderAddress = m_OP == Instruction::DELEGATECALL ? m_ext->caller : m_ext->myAddress; // if Delegatecall the sender address and value stays the same // STATICCALL is rejected by !m_schedule->haveStaticCall elsewhere callParams->receiveAddress = (m_OP == Instruction::CALL || m_OP == Instruction::STATICCALL) ? callParams->codeAddress : m_ext->myAddress; // if opcode isn’t CALL, the target address to call is the current one. callParams->data = bytesConstRef(m_mem.data() + inOff, inSize); o_output = bytesRef(m_mem.data() + outOff, outSize); return true; } return false;
並在 execution.go 的 Go Ethereum 中:
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) { evm := env.Vm() // Depth check execution. Fail if we're trying to execute above the // limit. if env.Depth() > callCreateDepthMax { caller.ReturnGas(gas, gasPrice) return nil, common.Address{}, errCallCreateDepth } snapshot := env.SnapshotDatabase() var to vm.Account if !env.Db().Exist(*toAddr) { to = env.Db().CreateAccount(*toAddr) } else { to = env.Db().GetAccount(*toAddr) } // Iinitialise a new contract and make initialise the delegate values contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate() contract.SetCallCode(codeAddr, codeHash, code) defer contract.Finalise() ret, err = evm.Run(contract, input) if err != nil { contract.UseGas(contract.Gas) env.RevertToSnapshot(snapshot) } return ret, addr, err }
where
.AsDelegate()
返回要被 DELEGATECALLED 的地址的呼叫者地址(這是在 處呼叫的地址evm.Run
):// AsDelegate sets the contract to be a delegate call and returns the current // contract (for chaining calls) func (c *Contract) AsDelegate() *Contract { c.DelegateCall = true // NOTE: caller must, at all times be a contract. It should never happen // that caller is something other than a Contract. c.CallerAddress = c.caller.(*Contract).CallerAddress return c }
因此,當從堆棧中讀取目標參數時,它會在稍後階段被忽略,如那些參考實現中所示。
DELEGATECALL 的第二個參數是
to
,用的非常多。我假設您所指的是黃紙中的一行,上面寫著“與 CALL 相比,DELEGATECALL 需要更少的參數。省略的參數是 µs$$ 2 $$.” 這只是說 DELEGATECALL 與 CALL 相同,只是它在索引 2 處沒有 CALL 所具有的參數(實際上是第三個參數)。DELEGATECALL 中省略的參數是
value
,例如你不能在委託呼叫期間發送 eth。