Opcode

delegatecall 第二個目標參數的目的是什麼?

  • June 19, 2018

簡單的問題,但我想不出答案。

是否有計劃/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。

引用自:https://ethereum.stackexchange.com/questions/51515